Compare commits

...

1267 Commits

Author SHA1 Message Date
Leendert de Borst
38db3c5054 Update docs 2025-05-31 15:56:50 +02:00
Leendert de Borst
971a21a16a Update README.md 2025-05-31 15:39:59 +02:00
Leendert de Borst
8058912eee Bump iOS app version and tweak bump version script (#878) 2025-05-31 15:39:59 +02:00
Leendert de Borst
8a9e1dc9a3 Update create-new-release docs (#878) 2025-05-31 15:39:59 +02:00
Leendert de Borst
cde78650b9 Bump version to 0.18.0 (#878) 2025-05-31 15:39:59 +02:00
Leendert de Borst
4ef9e58665 Update StartupTasks.cs (#876) 2025-05-31 12:12:55 +02:00
Leendert de Borst
b6b1d9dec9 Add amount of emails stored per user to admin user listing (#876) 2025-05-31 12:12:55 +02:00
Leendert de Borst
fa2dedb05a Unblock admin user when a password request has been requested (#876) 2025-05-31 12:12:55 +02:00
Leendert de Borst
f148ccdeba Add revoke all option to admin user refresh tokens (#874) 2025-05-31 11:42:43 +02:00
Leendert de Borst
9b038cb76c Truncate credential name/preview if too long (#872) 2025-05-31 08:47:41 +02:00
Leendert de Borst
aa726706a4 Make browser extension auth settings less strict (#872) 2025-05-31 08:47:41 +02:00
Leendert de Borst
d0017d9207 Add android app download link (#870) 2025-05-31 08:37:42 +02:00
Leendert de Borst
cde4b87371 Return fake login response if username is invalid (#868) 2025-05-31 07:45:40 +02:00
Leendert de Borst
431d8d4fca Only trigger autofill popup on username/email/password field types (#866) 2025-05-30 23:41:50 +02:00
Leendert de Borst
9fddb5f450 Reset client url on wrong input (#858) 2025-05-30 22:59:16 +02:00
Leendert de Borst
dbb6cf5b94 Add yup validation schema to auth settings (#858) 2025-05-30 22:59:16 +02:00
Leendert de Borst
bd41507ef9 Use absolute path for docker volume bind mounts (#859) 2025-05-30 18:03:53 +02:00
Leendert de Borst
ebb0e7cf68 Merge pull request #863 from lanedirt/846-add-native-android-app
Add native Android app
2025-05-30 18:03:42 +02:00
Leendert de Borst
4603051a91 Build and push docker images even if other optional steps fail (#846) 2025-05-30 18:01:26 +02:00
Leendert de Borst
f66fb53706 Update mobile-app-build.yml (#846) 2025-05-30 17:54:45 +02:00
Leendert de Borst
b603160d99 Add autofill screenshots to Android docs (#846) 2025-05-30 16:42:11 +02:00
Leendert de Borst
096b0277f3 Update mobile-app-build.yml (#846) 2025-05-30 15:52:05 +02:00
Leendert de Borst
f271040ff4 Improve android autofill settings open, bump version (#846) 2025-05-30 15:35:41 +02:00
Leendert de Borst
f313950112 Make safari extension project version the same for all projects (#846) 2025-05-30 15:11:24 +02:00
Leendert de Borst
ef1ad127e3 Update mobile-app-build.yml (#846) 2025-05-30 15:06:33 +02:00
Leendert de Borst
cac691a43d Delete lowercase duplicate validationSchema.ts (#846) 2025-05-30 13:50:36 +02:00
Leendert de Borst
4efe201224 Add iOS app build (#846) 2025-05-30 13:37:14 +02:00
Leendert de Borst
ca477c310c Make android app signed build manual dispatch (#846) 2025-05-30 12:40:21 +02:00
Leendert de Borst
77189373ba Add signed android app build (#846) 2025-05-30 11:57:36 +02:00
Leendert de Borst
1aaa5c2d55 Update mobile-app-build.yml (#846) 2025-05-30 11:04:51 +02:00
Leendert de Borst
163e5c51c2 Merge branch '846-add-native-android-app' of https://github.com/lanedirt/AliasVault into 846-add-native-android-app
* '846-add-native-android-app' of https://github.com/lanedirt/AliasVault:
  Make unit tests work from CLI (#846)
2025-05-30 10:58:59 +02:00
Leendert de Borst
29895f375f Split tasks in mobile-app-build.yml (#846) 2025-05-30 10:58:56 +02:00
Leendert de Borst
2803dcf02c Add bump-version.sh script (#846) 2025-05-30 10:56:32 +02:00
Leendert de Borst
a8e075d932 Update version to be equal for all subprojects (#846) 2025-05-30 09:59:30 +02:00
Leendert de Borst
49ba704135 Update docs (#846) 2025-05-30 09:38:59 +02:00
Leendert de Borst
9669307480 Make unit tests work from CLI (#846) 2025-05-29 21:22:09 +02:00
Leendert de Borst
343ced5b38 Make unit tests work from CLI (#846) 2025-05-29 21:08:38 +02:00
Leendert de Borst
8f66670804 Update mobile-app-build.yml (#846) 2025-05-29 20:12:33 +02:00
Leendert de Borst
c2d1fcfcd4 Update linting (#846) 2025-05-29 20:01:49 +02:00
Leendert de Borst
e5a340b67d Add android build to workflow (#846) 2025-05-29 20:00:48 +02:00
Leendert de Borst
6a0e8909a8 Refactor default auth method setting to be part of login flow (#846) 2025-05-29 18:40:10 +02:00
Leendert de Borst
5a90b4271c Fix android crash on back button (#846) 2025-05-29 18:39:41 +02:00
Leendert de Borst
f0bd837d5e Improve security (#846) 2025-05-29 17:16:55 +02:00
Leendert de Borst
de45c286b1 Fix android header issues (#846) 2025-05-29 16:26:13 +02:00
Leendert de Borst
fac0fd5f32 Add android edge-to-edge module to fix menu bar height issues (#846) 2025-05-29 16:05:42 +02:00
Leendert de Borst
5a8b6b7f29 Refactor android to satisfy linting rules (#846) 2025-05-29 13:48:19 +02:00
Leendert de Borst
c864bfcab5 Npx expo-doctor fixes (#846) 2025-05-28 20:23:02 +02:00
Leendert de Borst
c9c692ce6e Add detekt.yml for kotlin code style analysis (#846) 2025-05-28 20:20:07 +02:00
Leendert de Borst
a640e4d280 Update kotlin linting settings (#846) 2025-05-28 19:55:17 +02:00
Leendert de Borst
2f03db7951 Remove unnecessary call (#846) 2025-05-28 19:26:32 +02:00
Leendert de Borst
9e5b733c8a Update logo icons (#846) 2025-05-28 18:44:45 +02:00
Leendert de Borst
09c380afdd Rebuild Android via npx expo rebuild (#846) 2025-05-28 18:04:39 +02:00
Leendert de Borst
7d9cc6118e Rebuild iOS via npx expo prebuild to standardize (#846) 2025-05-28 17:17:49 +02:00
Leendert de Borst
c7ab42e9f2 Add android linting checks and integrate in build process (#846) 2025-05-28 16:43:05 +02:00
Leendert de Borst
1b07c5de9f Update Android UI (#846) 2025-05-28 16:00:49 +02:00
Leendert de Borst
84df5b7d98 Add native settings page open callback for android (#846) 2025-05-28 15:32:27 +02:00
Leendert de Borst
347721a575 Update docs (#846) 2025-05-28 13:51:10 +02:00
Leendert de Borst
463c31641d Make system bar transparent on android (#846) 2025-05-28 13:30:04 +02:00
Leendert de Borst
67759a814e Linting fixes (#846) 2025-05-28 12:33:46 +02:00
Leendert de Borst
763a859e22 Update UI margins to work with Android and iOS (#846) 2025-05-28 12:32:21 +02:00
Leendert de Borst
d7db5a4e76 Refactor UrlUtility to be app-specific (#846) 2025-05-28 10:37:44 +02:00
Leendert de Borst
85bb5cf944 Optimize create new credential for Android (#846) 2025-05-28 10:30:07 +02:00
Leendert de Borst
cdc59e43a9 Update android-autofill.tsx (#846) 2025-05-28 09:19:46 +02:00
Leendert de Borst
9d0a003b2d Refactor (#846) 2025-05-27 17:16:12 +02:00
Leendert de Borst
e430ae9f4f Refactor FieldFinder to separate file (#846) 2025-05-27 16:58:48 +02:00
Leendert de Borst
41ba1260d7 Add SVG icon support (#846) 2025-05-27 16:49:44 +02:00
Leendert de Borst
c7572ac3f7 Fix issue where open app was not displayed always (#846) 2025-05-27 16:32:45 +02:00
Leendert de Borst
fe5c50b3c4 Add vault locked notice (#846) 2025-05-27 15:53:48 +02:00
Leendert de Borst
2a8ed28ff9 Improve password field type detection (#846) 2025-05-27 15:35:21 +02:00
Leendert de Borst
f6764b2f33 Simplify logic (#846) 2025-05-27 15:16:40 +02:00
Leendert de Borst
1afa153381 Improve field type detection (#846) 2025-05-27 14:52:09 +02:00
Leendert de Borst
ac59273161 Trigger on both password and likely username fields (#846) 2025-05-27 13:55:00 +02:00
Leendert de Borst
551fc42de1 Show service logo if it has one in autofill suggestion (#846) 2025-05-27 13:50:46 +02:00
Leendert de Borst
4b844189bc Add aliasvault logo to autofill list item (#846) 2025-05-27 13:05:39 +02:00
Leendert de Borst
5c277e747f Refactor FieldFinder (#846) 2025-05-27 12:00:49 +02:00
Leendert de Borst
8cbd275134 Improve credential matching (#846) 2025-05-27 11:21:27 +02:00
Leendert de Borst
765625b163 Add credentialmatcher and autofill test scaffolding (#846) 2025-05-26 20:16:28 +02:00
Leendert de Borst
b3df153128 Remove obsolete sharedcredentialstore (#846) 2025-05-26 20:15:57 +02:00
Leendert de Borst
604cffc622 Add autofill docs (#846) 2025-05-26 19:34:25 +02:00
Leendert de Borst
3b114445a3 Add android docs (#846) 2025-05-26 19:34:17 +02:00
Leendert de Borst
e8942c9833 Make basic autofill dropdown work in chrome (#846) 2025-05-26 14:46:50 +02:00
Leendert de Borst
b1da32ceae Add inline suggestion flag (#846) 2025-05-26 13:12:35 +02:00
Leendert de Borst
ef58217ed3 Update autocomplete logic to only trigger for username or password fields (#846) 2025-05-26 12:07:36 +02:00
Leendert de Borst
e0dd04263c Refactor AutofillService to use VaultStore (#846) 2025-05-26 11:53:26 +02:00
Leendert de Borst
29c52c844f Add vaultstore generic instance for sharing main app and autofill component (#846) 2025-05-26 11:41:01 +02:00
Leendert de Borst
b99025c48a Remove deprecated files (#846) 2025-05-26 11:40:02 +02:00
Leendert de Borst
8ba8eb684e Add android autofill instructions page (#846) 2025-05-26 09:49:40 +02:00
Leendert de Borst
b736edbb68 Update skeleton loader color for light mode (#846) 2025-05-25 12:16:52 +02:00
Leendert de Borst
1fa0d275cc Update search input style (#846) 2025-05-24 19:21:52 +02:00
Leendert de Borst
4a05cd00e3 Fix add-edit on Android (#846) 2025-05-23 16:50:17 +02:00
Leendert de Borst
574b5ff693 Add generic ThemedContainer component (#846) 2025-05-23 16:32:35 +02:00
Leendert de Borst
e6b7d1afa1 Display add button on android (#846) 2025-05-23 15:44:56 +02:00
Leendert de Borst
cbe224385d Refactor function naming (#846) 2025-05-23 15:08:07 +02:00
Leendert de Borst
adb2f9a3d6 Add Android specific header style (#846) 2025-05-23 14:05:55 +02:00
Leendert de Borst
6790391d37 Use Base64.NO_WRAP for android to be compatible with other RFC 4648 clients (#846) 2025-05-23 12:35:14 +02:00
Leendert de Borst
2a7855e1dc Refactor (#846) 2025-05-23 11:50:07 +02:00
Leendert de Borst
f3e47d7e67 Add autolock timer to Android logic (#846) 2025-05-22 18:09:17 +02:00
Leendert de Borst
bc76e85a9c Update function naming (#846) 2025-05-22 16:54:37 +02:00
Leendert de Borst
890025cd49 Allow PIN fallback on Android unlock flow (#846) 2025-05-22 13:41:08 +02:00
Leendert de Borst
1868370d8f Make basic biometric keystore flow work (#846) 2025-05-22 13:01:38 +02:00
Leendert de Borst
9a4fc7fb37 Update vault unlock page for android (#846) 2025-05-21 17:56:16 +02:00
Leendert de Borst
199fdebd5d Add KeystoreProvider scaffolding (#846) 2025-05-21 16:11:35 +02:00
Leendert de Borst
d5f17ef99c Add base64 conversion logic (#846) 2025-05-21 14:56:18 +02:00
Leendert de Borst
3b1e039d75 Implement commitTransaction (#846) 2025-05-21 14:05:55 +02:00
Leendert de Borst
01cdd28e32 Add .code-workspace to .vscode folder (#846) 2025-05-20 22:39:00 +02:00
Leendert de Borst
95a71f6ab2 Merge pull request #855 from lanedirt/854-prepare-0173-release
Prepare 0.17.3 release
2025-05-20 15:42:46 +02:00
Leendert de Borst
41cb92befd Merge branch 'main' into 854-prepare-0173-release 2025-05-20 15:42:32 +02:00
Leendert de Borst
2cfd1a922f Merge pull request #853 from lanedirt/852-bug-vault-import-fails-if-one-or-more-2fa-tokens-cannot-be-read
Vault import fails if one or more 2FA tokens cannot be parsed
2025-05-20 15:37:30 +02:00
Leendert de Borst
511ec31d17 Bump version to 0.17.3 (#854) 2025-05-20 15:31:22 +02:00
Leendert de Borst
080e505991 Merge branch '850-prepare-0172-release' into 854-prepare-0173-release
* 850-prepare-0172-release:
  Bump version to 0.17.2 (#850)
2025-05-20 15:29:11 +02:00
Leendert de Borst
461c1a042d Silently fail incorrect 2FA codes during import instead of throwing exception (#852) 2025-05-20 15:22:09 +02:00
Leendert de Borst
f30fcf4624 Make SQLite in-memory writable, add test to verify (#846) 2025-05-20 12:57:57 +02:00
Leendert de Borst
522eeefda4 Update docs (#846) 2025-05-20 12:19:22 +02:00
Leendert de Borst
94656c4d14 Update iOS podfile (#846) 2025-05-20 11:48:14 +02:00
Leendert de Borst
bbba8d1393 Make icon symbols generic between Android and iOS platforms (#846) 2025-05-20 11:47:48 +02:00
Leendert de Borst
680f5ba926 Proxy all calls from NativeVaultManager to VaultStore (#846) 2025-05-20 11:24:23 +02:00
Leendert de Borst
04d3f80019 Add getMetadata call (#846) 2025-05-20 11:06:14 +02:00
Leendert de Borst
a4d78cf7fc Make login and vault store/get flow work (#846) 2025-05-20 10:43:35 +02:00
Leendert de Borst
9713c8ed11 Implement getAllCredentials in kotlin, make all unit tests work (#846) 2025-05-19 10:04:39 +02:00
Leendert de Borst
2f4dbf34ba Update formatting (#846) 2025-05-19 10:04:10 +02:00
Leendert de Borst
232d110e49 Update license in index.template.html (#846) 2025-05-18 16:30:01 +02:00
Leendert de Borst
0af1507686 Implement basic vault decrypt/unlock flow (#846) 2025-05-18 16:18:27 +02:00
Leendert de Borst
e481769198 Add storage provider abstraction, move vaultstore its own namespace (#846) 2025-05-18 15:47:02 +02:00
Leendert de Borst
830c390b95 Update Android unit test docs (#846) 2025-05-18 13:51:02 +02:00
Leendert de Borst
c733a60571 Refactor query specific logic to VaultStore instead of NativeVaultManager (#846) 2025-05-18 13:45:22 +02:00
Leendert de Borst
d164d8e785 Merge pull request #851 from lanedirt/850-prepare-0172-release
Prepare 0.17.2 release
2025-05-17 17:41:30 +02:00
Leendert de Borst
79221f35c6 Bump version to 0.17.2 (#850) 2025-05-17 17:39:16 +02:00
Leendert de Borst
826bd23767 Restore docker-compose.yml container versions to :latest (#848) 2025-05-17 17:35:51 +02:00
Leendert de Borst
baf81392eb Restore docker-compose.yml container versions to :latest (#848) 2025-05-17 17:14:01 +02:00
Leendert de Borst
a70f6fca56 Add Android native vault manager unit test scaffolding (#846) 2025-05-17 12:00:12 +02:00
Leendert de Borst
1480fd88d1 Implement NativeVaultManager kotlin scaffolding (#846) 2025-05-17 11:04:22 +02:00
Leendert de Borst
11a5e10f4b Update comments (#846) 2025-05-17 11:00:39 +02:00
Leendert de Borst
eecf61b8b2 Fix packages to make android buildable (#846) 2025-05-16 17:46:55 +02:00
Leendert de Borst
6c620e34e6 Update docs (#846) 2025-05-16 17:14:05 +02:00
Leendert de Borst
aa99bbc111 Remove sqlite migration scripts (#494) 2025-05-15 16:37:39 +02:00
Leendert de Borst
e34b5f586c Remove SQLite server database implementation in code (#494) 2025-05-15 16:37:39 +02:00
Leendert de Borst
80c0992eb4 Update docs (#494) 2025-05-15 16:37:39 +02:00
Leendert de Borst
1fe7f7d8dc Bump version to 0.17.1 (#843) 2025-05-14 11:23:03 +02:00
Leendert de Borst
e41552a2c0 Fix credential edit password existence check (#840) 2025-05-14 11:05:45 +02:00
Leendert de Borst
8e9c100eac Fix browser extension popup manual search/filter bug (#839) 2025-05-14 11:05:36 +02:00
Leendert de Borst
a46bc9699f Bump version to 0.17.0 (#837) 2025-05-14 10:40:54 +02:00
Leendert de Borst
78cc9e7ec1 Simplify account creation validation (#837) 2025-05-14 10:40:54 +02:00
Leendert de Borst
5c8b093514 Add namespace (#827) 2025-05-14 09:21:24 +02:00
Leendert de Borst
39a3c84fb8 Make browser extension popup more reliable (#834) 2025-05-14 09:20:58 +02:00
Leendert de Borst
a1ec4fb7fd Merge pull request #836 from lanedirt/834-add-extra-enabledisable-setting-toggles-to-browser-extension
Add extra enable/disable setting toggles to browser extension
2025-05-14 00:21:06 +02:00
Leendert de Borst
183130fd3e Merge branch 'main' into 834-add-extra-enabledisable-setting-toggles-to-browser-extension 2025-05-14 00:12:55 +02:00
Leendert de Borst
b03a2f5da6 Make autofill popup show logic more robust (#834) 2025-05-14 00:07:23 +02:00
Leendert de Borst
531fb2486f Add shortcuts link to Chrome (#834) 2025-05-13 22:59:52 +02:00
Leendert de Borst
db825f415e Do not show site-specific autofill settings if globally disabled (#834) 2025-05-13 22:19:08 +02:00
Leendert de Borst
3d3522a262 Use shared date util for min date check in browser extension (#834) 2025-05-13 22:10:25 +02:00
Leendert de Borst
ff112aa5f9 Fix background script errors by moving constants to separate file (#834) 2025-05-13 20:31:32 +02:00
Leendert de Borst
a0aaa8ec1e Context menu refactor (#834) 2025-05-13 20:31:32 +02:00
Leendert de Borst
ead45c0282 Add dismiss for 1 hour option, add context menu disable option (#834) 2025-05-13 20:31:32 +02:00
Leendert de Borst
aa0a61ccf1 Fix background script errors by moving constants to separate file (#834) 2025-05-13 20:25:29 +02:00
Leendert de Borst
4fd2eb7034 Context menu refactor (#834) 2025-05-13 19:01:41 +02:00
Leendert de Borst
fa3f4e78cc Add dismiss for 1 hour option, add context menu disable option (#834) 2025-05-13 18:34:43 +02:00
Leendert de Borst
71a1c105bd Update eslint.config.js (#832) 2025-05-13 16:56:16 +02:00
Leendert de Borst
86fcc66a75 Upgrade WXT to latest stable version (#832) 2025-05-13 16:56:16 +02:00
Leendert de Borst
d29cb5e654 Update browser extension npm package-lock.json (#832) 2025-05-13 16:56:16 +02:00
Leendert de Borst
291d245e47 Update file headers in new files (#828) 2025-05-13 16:47:16 +02:00
Leendert de Borst
85528cdb79 Update CONTRIBUTING.md (#828) 2025-05-13 16:47:16 +02:00
Leendert de Borst
96fd9bb837 Update to AGPLv3 license (#828) 2025-05-13 16:47:16 +02:00
Leendert de Borst
4d1d982eeb Combine mobile app links with browser extension links (#827) 2025-05-13 15:35:24 +02:00
Leendert de Borst
bc7f2d9d3a Add mobile app download link constants (#827) 2025-05-13 15:35:24 +02:00
Leendert de Borst
7e86d0f99a Update sonarcloud-code-analysis.yml 2025-05-13 15:21:31 +02:00
Leendert de Borst
4efa91beeb Update app build version (#825) 2025-05-13 15:21:31 +02:00
Leendert de Borst
2d347dd435 Return explicit new revision number on password change (#825) 2025-05-13 15:21:31 +02:00
Leendert de Borst
56b9fee4fb Merge pull request #822 from lanedirt/771-add-native-ios-app
Add native iOS app
2025-05-13 14:51:51 +02:00
Leendert de Borst
0fca053dba Update README.md 2025-05-12 21:30:16 +02:00
Leendert de Borst
349a911eda Bump iOS build version (#771) 2025-05-11 18:20:58 +02:00
Leendert de Borst
ba373d5d0d Add confirm dialog to logout action (#771) 2025-05-11 18:20:47 +02:00
Leendert de Borst
3cde63c5e9 Only sync emails when component is visible (#771) 2025-05-11 18:14:06 +02:00
Leendert de Borst
f7f6873689 UI tweaks (#771) 2025-05-11 18:11:12 +02:00
Leendert de Borst
afa9ad8b2f Add delete account implementation (#771) 2025-05-11 16:59:09 +02:00
Leendert de Borst
822815080c Add vault password change logic to react native (#771) 2025-05-11 15:31:47 +02:00
Leendert de Borst
9a0a5f3bbf Set correct Argon2id defaults in Typescript (#771) 2025-05-11 15:30:09 +02:00
Leendert de Borst
819e00feaa Use correct default encryption type (#771) 2025-05-11 13:16:10 +02:00
Leendert de Borst
9a43e74c3f Implement active sessions and recent auth logs pages (#771) 2025-05-10 22:43:19 +02:00
Leendert de Borst
3958ce94c1 Add security settings nav scaffolding (#771) 2025-05-10 11:50:57 +02:00
Leendert de Borst
6714201057 Make notes section properly selectable (#771) 2025-05-10 11:00:55 +02:00
Leendert de Borst
64b3cd16e4 Update README.md
Update README.md

Update README.md

Update README.md
2025-05-10 10:54:34 +02:00
Leendert de Borst
bddc128202 Fix username input (#771) 2025-05-09 18:28:06 +02:00
Leendert de Borst
e2e0413912 Add native InAppBrowserView component for handling external links (#771) 2025-05-09 08:57:17 +02:00
Leendert de Borst
68a1cc0b4e Update README.md (#771) 2025-05-08 21:56:29 +02:00
Leendert de Borst
068041db70 Update mobile app version tags (#771) 2025-05-08 16:07:11 +02:00
Leendert de Borst
073510e58f Update dotnet-e2e-tests.yml (#771) 2025-05-08 15:21:22 +02:00
Leendert de Borst
c24fca5bfe Update version and release docs (#771) 2025-05-08 15:17:24 +02:00
Leendert de Borst
2b49834c83 Remove duplicate workspace (#771) 2025-05-08 15:04:33 +02:00
Leendert de Borst
ca37c62bab Add exempt flag to browser extension xcode (#771) 2025-05-08 15:03:44 +02:00
Leendert de Borst
0ed0f3ab47 Remove duplicate aliasvault lowercase folder (#771) 2025-05-08 15:02:21 +02:00
Leendert de Borst
bd07510251 Add exempt encryption flag (#771) 2025-05-08 15:01:44 +02:00
Leendert de Borst
1219d49fb4 Update offline mode checks (#771) 2025-05-08 14:35:20 +02:00
Leendert de Borst
928860bd38 Add server sanity checks to login flow (#771) 2025-05-08 14:32:00 +02:00
Leendert de Borst
7238792895 Responsive tweaks (#771) 2025-05-08 14:05:07 +02:00
Leendert de Borst
a22875081b Responsive tweaks (#771) 2025-05-08 12:31:43 +02:00
Leendert de Borst
2eb7bbf1b3 Update CollapsibleHeader margins (#771) 2025-05-08 12:11:46 +02:00
Leendert de Borst
da3515d44c Offline mode tweaks (#771) 2025-05-08 11:41:04 +02:00
Leendert de Borst
255ac518a2 Store key derivation params locally for offline password unlock (#771) 2025-05-08 11:35:40 +02:00
Leendert de Borst
05575bdc5f Tweak pull to refresh (#771) 2025-05-07 22:44:55 +02:00
Leendert de Borst
e0e7315d44 Fix unlock page flow (#771) 2025-05-07 22:44:45 +02:00
Leendert de Borst
4ed6b30256 Add read-only offline mode (#771) 2025-05-07 17:59:01 +02:00
Leendert de Borst
88a1491b83 Update UI margins (#771) 2025-05-07 09:06:56 +02:00
Leendert de Borst
6dc4a6e307 Update NPM packages (#771) 2025-05-07 09:06:47 +02:00
Leendert de Borst
e24b270610 Tweak email display (#771) 2025-05-06 23:09:03 +02:00
Leendert de Borst
8d6b04448f Update view margins for main tabs (#771) 2025-05-06 22:54:07 +02:00
Leendert de Borst
a1dd44d8fc Disable autocorrect and autocapitalize for login/register (#771) 2025-05-06 22:50:19 +02:00
Leendert de Borst
b705263144 Performance tweaks (#771) 2025-05-06 22:43:06 +02:00
Leendert de Borst
b0a40ef5ee Add inline skeleton loader (#771) 2025-05-06 22:12:24 +02:00
Leendert de Borst
e11c647f50 Add skeleton loading animations (#771) 2025-05-06 20:29:20 +02:00
Leendert de Borst
94c4783c01 Create separate add-edit page instead of modal for better deep link compatibility (#771) 2025-05-06 19:32:04 +02:00
Leendert de Borst
751903029c Refactor initial sync to happen outside of navigation context (#771) 2025-05-06 18:25:53 +02:00
Leendert de Borst
fb318c7669 Update login screen (#771) 2025-05-06 14:57:36 +02:00
Leendert de Borst
52340b8238 Update colors (#771) 2025-05-06 14:34:45 +02:00
Leendert de Borst
82423fffcb Add translucent headers (#771) 2025-05-06 14:22:22 +02:00
Leendert de Borst
e714d8563c UI tweaks (#771) 2025-05-06 13:05:38 +02:00
Leendert de Borst
e6ab1be77f Update light/dark mode styling (#771) 2025-05-05 22:23:00 +02:00
Leendert de Borst
0be6caf0bb Merge branch '771-add-native-ios-app' of https://github.com/lanedirt/AliasVault into 771-add-native-ios-app
* '771-add-native-ios-app' of https://github.com/lanedirt/AliasVault:
  Update light/dark mode styling (#771)
2025-05-05 22:16:40 +02:00
Leendert de Borst
51b03b5eaa Update iOS app download link (#771) 2025-05-05 22:16:23 +02:00
Leendert de Borst
5a019098e1 Update light/dark mode styling (#771) 2025-05-05 22:16:12 +02:00
Leendert de Borst
e992dea23e Update light/dark mode styling (#771) 2025-05-05 17:52:27 +02:00
Leendert de Borst
095a3f617e Update browser extension imports (#771) 2025-05-05 17:50:37 +02:00
Leendert de Borst
77a48f4235 Git check in with correct casing in mobile app dir (#771) 2025-05-05 15:33:00 +02:00
Leendert de Borst
af5a830759 Update docs (#771) 2025-05-05 15:07:08 +02:00
Leendert de Borst
af1a4b6930 Update package.json (#771) 2025-05-05 13:28:31 +02:00
Leendert de Borst
0fe969dfad Merge branch '771-add-native-ios-app' of https://github.com/lanedirt/AliasVault into 771-add-native-ios-app
* '771-add-native-ios-app' of https://github.com/lanedirt/AliasVault:
  Update README.md
2025-05-05 13:22:39 +02:00
Leendert de Borst
43e642116e Add passWithNoTests flag (#771) 2025-05-05 13:21:58 +02:00
Leendert de Borst
68da15603a Merge branch 'main' into 771-add-native-ios-app 2025-05-05 13:16:25 +02:00
Leendert de Borst
f5753f654c Update workflow names (#771) 2025-05-05 13:13:05 +02:00
Leendert de Borst
6f26649647 Update README.md badges 2025-05-05 13:12:48 +02:00
Leendert de Borst
20135afe4d Update mobile app build workflow (#771) 2025-05-05 13:04:12 +02:00
Leendert de Borst
19a38ba14f Update CredentialDetails.tsx (#771) 2025-05-05 12:40:11 +02:00
Leendert de Borst
eae70b41f1 Update GitHub workflows (#771) 2025-05-05 12:32:46 +02:00
Leendert de Borst
fb3530281f Update .gitignore (#771) 2025-05-05 12:08:18 +02:00
Leendert de Borst
df937cf039 Group related GitHub workflows (#771) 2025-05-05 12:08:11 +02:00
Leendert de Borst
f77a220096 Add shared lib build to github workflow (#771) 2025-05-05 12:07:23 +02:00
Leendert de Borst
93040e2377 Linting refactor (#771) 2025-05-05 11:51:10 +02:00
Leendert de Borst
d758de2674 Replace KeychainAccess with native iOS API for more control (#771) 2025-05-05 11:47:09 +02:00
Leendert de Borst
8bc1a49602 Add toast on vault unlock biometric enable (#771) 2025-05-05 11:40:07 +02:00
Leendert de Borst
38a69649af Update CredentialProviderView (#771) 2025-05-05 11:24:39 +02:00
Leendert de Borst
f3aa8fe085 Prompt for authentication and sanity checks before opening autofill view (#771( 2025-05-05 10:48:45 +02:00
Leendert de Borst
3066512341 Auto hide credential created confirm when app opens again (#771) 2025-05-05 09:34:28 +02:00
Leendert de Borst
af53abac0b Show loading state when deleting a credential (#771) 2025-05-05 09:02:46 +02:00
Leendert de Borst
5743056084 Fix mobile app credential creation (#771) 2025-05-05 09:01:32 +02:00
Leendert de Borst
7917270aee Update date parsing to use shared library (#771) 2025-05-05 09:01:01 +02:00
Leendert de Borst
533b4cf7a2 Update vault mutate private email filter (#771) 2025-05-05 08:22:12 +02:00
Leendert de Borst
9435c7e657 Cleanup xcode generated file headers (#771) 2025-05-04 22:42:01 +02:00
Leendert de Borst
30a6315e9e Refactor native iOS parts (#771) 2025-05-04 22:38:49 +02:00
Leendert de Borst
61692db40b Refactor VaultStoreKit and fix linting issues (#771) 2025-05-04 18:06:37 +02:00
Leendert de Borst
e7aae996d1 Refactor VaultStoreKit (#771) 2025-05-04 16:39:27 +02:00
Leendert de Borst
5e576b1ed2 Add swiftlint scaffolding (#771) 2025-05-04 16:39:15 +02:00
Leendert de Borst
51b1b383f9 Merge branch '771-add-native-ios-app' of https://github.com/lanedirt/AliasVault into 771-add-native-ios-app
* '771-add-native-ios-app' of https://github.com/lanedirt/AliasVault:
  Linting refactor misc utilities (#771)
2025-05-04 16:37:55 +02:00
Leendert de Borst
76a5e1bae4 Fix notes mutation (#771) 2025-05-04 16:37:51 +02:00
Leendert de Borst
3429c34eb4 Linting refactor misc utilities (#771) 2025-05-04 15:58:06 +02:00
Leendert de Borst
d9942ea57c Linting refactor misc utilities (#771) 2025-05-04 15:54:55 +02:00
Leendert de Borst
738f228ea6 Linting refactor turbo native spec (#771) 2025-05-04 14:19:25 +02:00
Leendert de Borst
3318748853 Linting refactor hooks (#771) 2025-05-04 14:11:41 +02:00
Leendert de Borst
f06cf511eb Linting refactor context (#771) 2025-05-04 14:00:45 +02:00
Leendert de Borst
15d707615a Linting refactor components (#771) 2025-05-04 13:48:14 +02:00
Leendert de Borst
5e2bdc6861 Linting refactor (#771) 2025-05-04 12:11:05 +02:00
Leendert de Borst
6e7e985c26 Enable eslint for react native project (#771) 2025-05-03 19:46:25 +02:00
Leendert de Borst
d47852420a Cleanup xcscheme and refactor swift test setup (#771) 2025-05-03 19:32:32 +02:00
Leendert de Borst
1cc6567d6f Refactor storeEncryptedDatabase method to separate metadata set (#771) 2025-05-03 18:08:22 +02:00
Leendert de Borst
616705b80d Remove VaultUITests file as its not used (#771) 2025-05-03 10:04:25 +02:00
Leendert de Borst
198b532299 Refactor VaultStoreKit function naming (#771) 2025-05-03 09:59:10 +02:00
Leendert de Borst
c763b79c3c Extract service icons during both credential create and update (#771) 2025-05-03 08:51:06 +02:00
Leendert de Borst
043ce5c588 Explicitly navigate to show credential after creation/update (#771) 2025-05-03 08:39:06 +02:00
Leendert de Borst
e7e7bc5f87 Remove unused native add methods (#771) 2025-05-03 08:38:41 +02:00
Leendert de Borst
15f10788b1 Add dynamic public email domain check (#771) 2025-05-03 08:29:06 +02:00
Leendert de Borst
71530ef79d Enforce biometrics for native iOS autofill (#771) 2025-05-02 18:28:20 +02:00
Leendert de Borst
d6f7d8c039 Add context menu links to native autofill list (#771) 2025-05-02 16:56:46 +02:00
Leendert de Borst
1dfbd38586 Fix credential name focus and refactor (#771) 2025-05-02 16:25:14 +02:00
Leendert de Borst
f849b94d5d Update README.md 2025-05-02 14:48:57 +02:00
Leendert de Borst
06a5c50359 Add transaction commit to credential delete (#771) 2025-05-02 14:46:46 +02:00
Leendert de Borst
866dd1c919 Add loading overlay component (#771) 2025-05-02 14:01:40 +02:00
Leendert de Borst
3be65beb06 Add credential form validation (#771) 2025-05-02 13:22:15 +02:00
Leendert de Borst
8c06b46044 Add proper UX flow for identity and password generator into mobile app (#771) 2025-05-01 17:38:42 +02:00
Leendert de Borst
f8d5ae6107 Implement identity and password generator in mobile app (#771) 2025-05-01 13:03:06 +02:00
Leendert de Borst
b6b9e05a31 Update manual setup docs (#771) 2025-05-01 12:51:50 +02:00
Leendert de Borst
b80e47dab3 Copy shared modules to mobile app project (#771) 2025-05-01 11:19:50 +02:00
Leendert de Borst
d291ad5ba2 Update shared build script (#771) 2025-05-01 11:19:33 +02:00
Leendert de Borst
037e1902b1 Merge branch 'main' into 771-add-native-ios-app
* main:
  Bump version to 0.16.2 (#818)
  Bump vite
2025-05-01 11:11:15 +02:00
Leendert de Borst
ab82a63a0a Bump version to 0.16.2 (#818) 2025-05-01 08:57:09 +02:00
dependabot[bot]
82376b696c Bump vite
Bumps the npm_and_yarn group with 1 update in the /browser-extension directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.6 to 6.3.4
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.3.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.3.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-01 08:45:37 +02:00
Leendert de Borst
18e6698f7d Fix linting (#771) 2025-04-30 23:32:47 +02:00
Leendert de Borst
b002b23078 Update file extensions (#771) 2025-04-30 23:22:47 +02:00
Leendert de Borst
1f2f53a124 Update shared package names (#771) 2025-04-30 23:19:24 +02:00
Leendert de Borst
46d56b06ed Remove deprecated identityGenDictLoader from browser extension (#771) 2025-04-30 23:19:12 +02:00
Leendert de Borst
4f6e419524 Implement new shared generator modules in browser extension (#771) 2025-04-30 23:11:42 +02:00
Leendert de Borst
7ae8655c2d Add build script for shared modules (#771) 2025-04-30 23:10:44 +02:00
Leendert de Borst
048e6f8d2a Rename packages to shared in root and to be standalone modules (#771) 2025-04-30 22:13:37 +02:00
Leendert de Borst
8498102076 Make shared packages buildable (#771) 2025-04-30 19:45:37 +02:00
Leendert de Borst
f2d78538a9 Refactor dictionaries from txt to .ts (#771) 2025-04-30 19:19:46 +02:00
Leendert de Borst
5babd0b982 Move all apps to subfolder in monorepo (#771) 2025-04-30 19:03:18 +02:00
Leendert de Borst
0f45f49ed1 Add shared packages folder (#771) 2025-04-30 17:08:48 +02:00
Leendert de Borst
699aa83c4e Merge branch 'main' into 771-add-native-ios-app
* main: (33 commits)
  Update date format in RecentEmails.razor (#815)
  Tweak Login.razor margins (#809)
  Refresh password salt and ephemeral after changing it  (#809)
  Add dashlane importer and unittest (#811)
  Bump the npm_and_yarn group across 1 directory with 2 updates
  Bump nokogiri in /docs in the bundler group across 1 directory
  Fix nullability warning in FaviconExtractor.cs (#805)
  Bump HtmlAgilityPack from 1.12.0 to 1.12.1
  Bump version to 0.16.1 (#803)
  Add form detector improvements and tests (#794)
  Add reliable click handler for all autofill popup elements (#797)
  Update Filter.ts (#801)
  Fix autofill popup z-index visibility (#801)
  Show email in credential list if username is empty (#801)
  Improve autofill matching (#801)
  Make browser extension autofill dismiss button more reliable (#797)
  Remove cancel for sonarcloud runner as it uses pull_request_target
  Simplify service name to a single input for both modes (#798)
  Show service name suggestions (#798)
  Add service name extraction unit tests (#798)
  ...
2025-04-30 17:04:32 +02:00
Leendert de Borst
7e3bb548e4 Refactor add-edit by wrapping vault mutate (#771) 2025-04-30 15:50:41 +02:00
Leendert de Borst
ae3ae6032f Add credential delete functionality (#771) 2025-04-30 14:57:46 +02:00
Leendert de Borst
0c8fc191a6 Update date format in RecentEmails.razor (#815) 2025-04-30 14:41:26 +02:00
Leendert de Borst
96b7b4cc97 Add autofill credential create confirm screen to improve UX (#771) 2025-04-30 14:26:04 +02:00
Leendert de Borst
d95807711a Make toast a shared component (#771) 2025-04-30 14:25:34 +02:00
Leendert de Borst
1051ee653e Add favicon extraction to mobile app (#771) 2025-04-30 13:56:24 +02:00
Leendert de Borst
2fd117ae96 Make vault save to server flow work in app (#771) 2025-04-29 17:16:52 +02:00
Leendert de Borst
6c5247a4b0 Make local vault db persist and encryption flow work (#771) 2025-04-29 16:05:52 +02:00
Leendert de Borst
a46d1ca39e Add credential update scaffolding (#771) 2025-04-29 14:19:50 +02:00
Leendert de Borst
caef74477b Refactor nav structure, make credential create deep link work (#771) 2025-04-29 13:37:20 +02:00
Leendert de Borst
d554f0f3cc Make credential create work locally (#771) 2025-04-29 11:43:14 +02:00
Leendert de Borst
c0e1c75a1b Add credential AddEdit page scaffolding to app (#771) 2025-04-28 21:32:26 +02:00
Leendert de Borst
b71f0dd2c3 Tweak Login.razor margins (#809) 2025-04-28 18:44:15 +02:00
Leendert de Borst
3617c551e3 Refresh password salt and ephemeral after changing it (#809) 2025-04-28 18:44:15 +02:00
Leendert de Borst
901caa896b Add dashlane importer and unittest (#811) 2025-04-28 18:44:08 +02:00
Leendert de Borst
8d68d175bf Create new credential via main app link (#771) 2025-04-28 17:00:02 +02:00
Leendert de Borst
27dbd53786 Add "text to insert" method support (#771) 2025-04-28 16:39:18 +02:00
Leendert de Borst
a37052e4dc Add actionsheet when selecting autofill credential to choose username or email (#771) 2025-04-28 16:07:19 +02:00
Leendert de Borst
cd8b2deb04 Add encryption key retry to make it more robust (#771) 2025-04-28 16:06:51 +02:00
Leendert de Borst
16a858ee08 Add iOS suggestion credential insert scaffolding (#771) 2025-04-28 13:34:32 +02:00
Leendert de Borst
01f1cc8bc3 Auto filter native credentials list based on provided URL (#771) 2025-04-28 12:26:06 +02:00
Leendert de Borst
9f79c0cfeb Update credential cards for all clients to show email if username is empty (#771) 2025-04-28 12:08:46 +02:00
Leendert de Borst
65d3b1d94f Add iOS autofill tip to settings screen with simple state (#771) 2025-04-28 11:18:33 +02:00
Leendert de Borst
96d5606632 Update credential view search input style (#771) 2025-04-27 21:17:50 +02:00
Leendert de Borst
535de6b7b4 Refactor iOS app native logic to frameworks and make SwiftUI preview work (#771) 2025-04-27 21:01:42 +02:00
Leendert de Borst
a86896ee99 Make SVG work in autofill credential view (#771) 2025-04-27 15:19:49 +02:00
Leendert de Borst
51bb5b84bd Add default placeholder icon to swift view (#771) 2025-04-27 13:23:29 +02:00
Leendert de Borst
c005c0cdc0 Make logo SQLIte blob to Data() conversion work (#771) 2025-04-27 10:26:14 +02:00
Leendert de Borst
83f64c505e Update swift logic to test for specific credential values (#771) 2025-04-26 16:10:32 +02:00
Leendert de Borst
1c3627d985 Make autofill work in simulator and fix password get (#771) 2025-04-26 11:31:44 +02:00
Leendert de Borst
c05b436e3c Fix GetAllCredentials so unittest passes (#771) 2025-04-26 11:09:18 +02:00
Leendert de Borst
cb61b73553 Make db init test work (#771) 2025-04-25 21:08:37 +02:00
Leendert de Borst
51b3956caf Fix vault generator output by taking latest vault blob (#771) 2025-04-25 19:50:48 +02:00
Leendert de Borst
128826d0ec Add TestVaultGeneratorTests.cs (#771) 2025-04-25 17:39:50 +02:00
dependabot[bot]
89534bf78e Bump the npm_and_yarn group across 1 directory with 2 updates
Bumps the npm_and_yarn group with 2 updates in the /browser-extension directory: [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) and [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom).


Updates `react-router` from 7.2.0 to 7.5.2
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.5.2/packages/react-router)

Updates `react-router-dom` from 7.2.0 to 7.5.2
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.5.2/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router
  dependency-version: 7.5.2
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: react-router-dom
  dependency-version: 7.5.2
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-25 17:18:01 +02:00
Leendert de Borst
605ac2e6d4 Add VaultStoreTests scaffolding which can run via xcode (#771) 2025-04-25 14:42:33 +02:00
Leendert de Borst
5a7e0cf9e5 Update VaultStore logic, getAllCredentials currently breaks (#771) 2025-04-25 14:13:42 +02:00
Leendert de Borst
0bd9b990b6 Make native autofill init db first (#771) 2025-04-25 13:14:16 +02:00
Leendert de Borst
a37d2d0934 Make 2FA input field render properly (#771) 2025-04-24 23:49:16 +02:00
Leendert de Borst
b747161b24 Rename SharedCredentialStore to VaultStore, add readmes (#771) 2025-04-24 23:36:46 +02:00
Leendert de Borst
ce6cdf1d9a Rename NativeCredentialManager to NativeVaultManager (#771) 2025-04-24 23:01:47 +02:00
Leendert de Borst
c94b5339b9 Refactor React Native bridge to Turbo Native Module (#771) 2025-04-24 22:33:13 +02:00
Leendert de Borst
9af505ffb3 Tweak login and unlock layout (#771) 2025-04-24 16:40:39 +02:00
Leendert de Borst
b1b4d7bff7 Make vault decryption catch and print errors (#771) 2025-04-24 16:37:15 +02:00
Leendert de Borst
d4a39caa22 Fix color scheme light mode flash when app comes to foreground (#771) 2025-04-24 16:00:39 +02:00
Leendert de Borst
cc1ca7f683 Make 2FA login flow show proper loading indicator (#771) 2025-04-24 15:03:07 +02:00
Leendert de Borst
4f3c436dd9 Tweak faceid enable/disable logic flow (#771) 2025-04-24 14:43:55 +02:00
Leendert de Borst
01adb3df07 Fix settings screen flicker issue (#771) 2025-04-24 13:50:10 +02:00
Leendert de Borst
038e22db62 Move enabled auth methods to native module and add conditional faceid check (#771) 2025-04-24 13:44:55 +02:00
Leendert de Borst
b0203882f3 Fix bug with birthdate parsing (#771) 2025-04-23 19:38:45 +02:00
Leendert de Borst
d88e0ca4cf Add two-factor auth viewer to mobile app (#771) 2025-04-23 19:20:55 +02:00
Leendert de Borst
1bf6a5dec3 Fix login flow (#771) 2025-04-23 18:57:08 +02:00
Leendert de Borst
951f80b4bb Tweak app timeout lock logic (#771) 2025-04-23 18:37:05 +02:00
Leendert de Borst
079415184f Store autolock timeout in native code (#771) 2025-04-23 17:21:03 +02:00
Leendert de Borst
db58bc8942 Refactor app index flow, add auto lock settings (#771) 2025-04-23 16:47:21 +02:00
Leendert de Borst
2a808fb137 Fix keychain accessibility issue (#771) 2025-04-23 14:15:46 +02:00
Leendert de Borst
b19ee32b28 Add settings page stack and add unlock method options (#771) 2025-04-23 13:53:17 +02:00
Leendert de Borst
31d3c1d1a2 Make manual unlock page with password unlock work (#771) 2025-04-23 11:43:48 +02:00
Leendert de Borst
70151f0587 Tweak collapsible header UI (#771) 2025-04-22 22:11:00 +02:00
Leendert de Borst
37f2f445c2 Add search icon to credential search input (#771) 2025-04-22 20:35:24 +02:00
Leendert de Borst
d88ecb5fec Make list content overflow under bottom nav bar (#771) 2025-04-22 20:21:28 +02:00
Leendert de Borst
91b223bac9 Add collapsible header component (#771) 2025-04-22 20:09:58 +02:00
Leendert de Borst
ecb2d29dcf Tweak index.tsx app startup and vault unlock flow (#771) 2025-04-22 17:33:06 +02:00
Leendert de Borst
470ffec21a Refresh email list on email delete (#771) 2025-04-22 15:58:10 +02:00
Leendert de Borst
30ac7b1f1d Make emailpreview auto refresh (#771) 2025-04-22 15:47:30 +02:00
Leendert de Borst
bef4ee7c03 Make credential service url clickable (#771) 2025-04-22 14:40:33 +02:00
Leendert de Borst
af3e455477 Add email preview component (#771) 2025-04-22 14:27:06 +02:00
Leendert de Borst
279a2f6bba Add scroll to top on email bottom nav bar click (#771) 2025-04-22 13:49:45 +02:00
Leendert de Borst
a04586c959 Add credential link to email details page (#771) 2025-04-22 13:44:39 +02:00
Leendert de Borst
26b63a282b Fix email navigation path (#771) 2025-04-22 13:08:52 +02:00
Leendert de Borst
0eb7e74eb6 Add pull to refresh to email page (#771) 2025-04-22 13:01:54 +02:00
Leendert de Borst
14b90fb047 Refactor email row to separate component (#771) 2025-04-22 12:56:46 +02:00
dependabot[bot]
e82595162f Bump nokogiri in /docs in the bundler group across 1 directory
Bumps the bundler group with 1 update in the /docs directory: [nokogiri](https://github.com/sparklemotion/nokogiri).


Updates `nokogiri` from 1.18.4 to 1.18.8
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.18.4...v1.18.8)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-version: 1.18.8
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-22 12:37:19 +02:00
Leendert de Borst
4480eb897a Update emails nav structure (#771) 2025-04-22 12:36:47 +02:00
Leendert de Borst
38b3b242d9 Make RSA decryption for emails work in react native (#771) 2025-04-22 11:26:19 +02:00
Leendert de Borst
c2b313c272 Disable autocorrect in search field (#771) 2025-04-22 09:25:23 +02:00
Leendert de Borst
93c439e852 Fix nullability warning in FaviconExtractor.cs (#805) 2025-04-21 16:01:22 +02:00
dependabot[bot]
ff08fae579 Bump HtmlAgilityPack from 1.12.0 to 1.12.1
Bumps [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) from 1.12.0 to 1.12.1.
- [Release notes](https://github.com/zzzprojects/html-agility-pack/releases)
- [Commits](https://github.com/zzzprojects/html-agility-pack/compare/v1.12.0...v1.12.1)

---
updated-dependencies:
- dependency-name: HtmlAgilityPack
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-21 16:01:22 +02:00
Leendert de Borst
758597353f Remove haptic touch from bottom nav bar (#771) 2025-04-20 22:02:17 +02:00
Leendert de Borst
f720c46958 Tweak login flow (#771) 2025-04-20 21:10:48 +02:00
Leendert de Borst
b9c0f23e45 Add empty field sanity check to login (#771) 2025-04-20 20:48:27 +02:00
Leendert de Borst
13fcadb2fa Add AliasVault themed loading indicators (#771) 2025-04-20 19:46:47 +02:00
Leendert de Borst
6c7f5f2e02 Add login API URL settings page (#771) 2025-04-20 18:16:46 +02:00
Leendert de Borst
dd01ada1b7 Add TitleContainer component with SVG logo (#771) 2025-04-20 16:58:55 +02:00
Leendert de Borst
abfaefa289 Add credential search reset button (#771) 2025-04-19 12:22:55 +02:00
Leendert de Borst
f40ba50607 Reset credentials page when tapping on tabbar item again (#771) 2025-04-19 11:58:02 +02:00
Leendert de Borst
0a19318e2d Add CredentialCard component (#771) 2025-04-19 11:13:57 +02:00
Leendert de Borst
2e5107098e Add app version to settings page (#771) 2025-04-18 17:43:32 +02:00
Leendert de Borst
ba4eea2dc8 Make notes component detect links and show on top (#771) 2025-04-18 14:09:44 +02:00
Leendert de Borst
87b1d49544 Refactor credential detail component structure (#771) 2025-04-18 13:49:10 +02:00
Leendert de Borst
355f198293 Make credential card show username/email uniformly in all clients (#771) 2025-04-18 13:24:18 +02:00
Leendert de Borst
9e1eb67ae8 Add URL to credential search filter logic (#771) 2025-04-18 13:17:08 +02:00
Leendert de Borst
8dcacd2ea4 Refactor color scheme usage (#771) 2025-04-18 09:27:59 +02:00
Leendert de Borst
0eb6a501af Update credential index layout (#771) 2025-04-18 08:57:36 +02:00
Leendert de Borst
05dae94336 Use generic colors in credential list (#771) 2025-04-18 08:52:22 +02:00
Leendert de Borst
2e7fde861e Add generic color definition (#771) 2025-04-18 00:13:32 +02:00
Leendert de Borst
c1ba8217fb Add separate index page that calls init logic (#771) 2025-04-17 18:40:45 +02:00
Leendert de Borst
39f8157683 Refactor get metadata call (#771) 2025-04-16 22:09:49 +02:00
Leendert de Borst
c0b0c97106 Persist vault metadata via react native bridge (#771) 2025-04-16 21:55:10 +02:00
Leendert de Borst
984adce3d4 Fix typo (#771) 2025-04-16 21:02:06 +02:00
Leendert de Borst
98dead8c0a Add vault update check to main layout scaffolding (#771) 2025-04-16 15:42:02 +02:00
Leendert de Borst
e771af4a7a Add pull to refresh to credential list (#771) 2025-04-16 08:13:43 +02:00
Leendert de Borst
5fdcee50d5 Bump version to 0.16.1 (#803) 2025-04-15 18:39:10 +02:00
Leendert de Borst
8526172ec7 Add form detector improvements and tests (#794) 2025-04-15 18:39:10 +02:00
Leendert de Borst
5156988319 Merge pull request #800 from lanedirt/798-browser-extension-make-service-name-extraction-more-accurate
Browser extension make service name extraction more accurate
2025-04-15 18:02:03 +02:00
Leendert de Borst
18d92ecced Add reliable click handler for all autofill popup elements (#797) 2025-04-15 17:07:27 +02:00
Leendert de Borst
0a0bec99b1 Merge branch 'main' into 798-browser-extension-make-service-name-extraction-more-accurate 2025-04-15 17:02:46 +02:00
Leendert de Borst
791f8a758b Update Filter.ts (#801) 2025-04-15 17:00:22 +02:00
Leendert de Borst
3f11e29787 Fix autofill popup z-index visibility (#801) 2025-04-15 17:00:22 +02:00
Leendert de Borst
046d09453a Show email in credential list if username is empty (#801) 2025-04-15 17:00:22 +02:00
Leendert de Borst
1d77d05e7c Improve autofill matching (#801) 2025-04-15 17:00:22 +02:00
Leendert de Borst
22d2e09982 Make browser extension autofill dismiss button more reliable (#797) 2025-04-15 16:59:50 +02:00
Leendert de Borst
8b835a4a77 Remove cancel for sonarcloud runner as it uses pull_request_target 2025-04-15 16:58:28 +02:00
Leendert de Borst
a435305093 Simplify service name to a single input for both modes (#798) 2025-04-15 15:51:18 +02:00
Leendert de Borst
e4f3de927f Show service name suggestions (#798) 2025-04-15 15:34:48 +02:00
Leendert de Borst
1d5c288514 Add service name extraction unit tests (#798) 2025-04-15 12:57:04 +02:00
Leendert de Borst
5d3ad60dee Improve browser extension service name extractor (#798) 2025-04-15 12:56:55 +02:00
Leendert de Borst
c5244b31ec Cancel already running CI jobs on newer commit 2025-04-15 11:34:19 +02:00
Leendert de Borst
a6c7c54592 Add password visibility toggle to browser extension credential create (#793) 2025-04-15 11:24:59 +02:00
Leendert de Borst
bf46c155bd Fix browser extension autofill from causing scrollbars to appear (#794) 2025-04-15 11:24:51 +02:00
Leendert de Borst
d4e5b724ff Make autofill work with more input element variations (#794) 2025-04-15 11:24:51 +02:00
Leendert de Borst
e51219d513 Add explicit type=text for accessibility improvements (#794) 2025-04-15 11:24:51 +02:00
Leendert de Borst
ba5f81ee86 Show icon in react native app (#771) 2025-04-14 22:17:21 +02:00
Leendert de Borst
800f015947 Update all .NET dependencies to 9.0.4 (#791) 2025-04-14 20:55:36 +02:00
dependabot[bot]
5f3c36263d Bump Microsoft.AspNetCore.Authorization and Microsoft.AspNetCore.Components.Web
Bumps [Microsoft.AspNetCore.Authorization](https://github.com/dotnet/aspnetcore) and [Microsoft.AspNetCore.Components.Web](https://github.com/dotnet/aspnetcore). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Authorization` from 9.0.3 to 9.0.4
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.3...v9.0.4)

Updates `Microsoft.AspNetCore.Components.Web` from 9.0.3 to 9.0.4
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.3...v9.0.4)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authorization
  dependency-version: 9.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.AspNetCore.Components.Web
  dependency-version: 9.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 17:00:32 +02:00
dependabot[bot]
4617d5efc4 Bump Microsoft.AspNetCore.Components.WebAssembly.DevServer
Bumps [Microsoft.AspNetCore.Components.WebAssembly.DevServer](https://github.com/dotnet/aspnetcore) from 9.0.3 to 9.0.4.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.3...v9.0.4)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Components.WebAssembly.DevServer
  dependency-version: 9.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 17:00:22 +02:00
dependabot[bot]
1401982e2c Bump Microsoft.EntityFrameworkCore and Microsoft.EntityFrameworkCore.SqlServer
Bumps [Microsoft.EntityFrameworkCore](https://github.com/dotnet/efcore) and [Microsoft.EntityFrameworkCore.SqlServer](https://github.com/dotnet/efcore). These dependencies needed to be updated together.

Updates `Microsoft.EntityFrameworkCore` from 9.0.3 to 9.0.4
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.3...v9.0.4)

Updates `Microsoft.EntityFrameworkCore.SqlServer` from 9.0.3 to 9.0.4
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.3...v9.0.4)

---
updated-dependencies:
- dependency-name: Microsoft.EntityFrameworkCore
  dependency-version: 9.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.EntityFrameworkCore.SqlServer
  dependency-version: 9.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 17:00:15 +02:00
Leendert de Borst
ebdbf41208 Merge pull request #778 from lanedirt/775-add-spacing-in-webauthn-login-message-ui
Update webauthn unlock animation margin
2025-04-13 21:09:36 +02:00
Leendert de Borst
3a8d08c53b Make credential tap work if keyboard is up (#771) 2025-04-13 14:12:11 +02:00
Leendert de Borst
8b9a60689a Add ThemedSafeAreaView component (#771) 2025-04-13 13:52:57 +02:00
Leendert de Borst
8bb6d04038 Update index.tsx header (#771) 2025-04-13 10:10:55 +02:00
Leendert de Borst
8455d6be88 Add credential search (#771) 2025-04-12 18:55:04 +02:00
Leendert de Borst
4d72c74731 Update theme (#771) 2025-04-12 18:31:13 +02:00
Leendert de Borst
f76a396e6d Add toast message on copy (#771) 2025-04-12 18:16:17 +02:00
Leendert de Borst
5ae6e069ab Add credentials detail page (#771) 2025-04-12 18:01:27 +02:00
Leendert de Borst
a73d6adad5 Update main nav and cleanup (#771)
Update main nav (#771)

Make autofill filter work (#771)

Add isVaultInitialized native func (#771)

Cleanup (#771)
2025-04-12 17:59:18 +02:00
Leendert de Borst
ed4b82e125 Update webauthn unlock animation margin (#775) 2025-04-12 16:06:12 +02:00
dependabot[bot]
1976255e98 Bump vite
Bumps the npm_and_yarn group with 1 update in the /browser-extension directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.5 to 6.2.6
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.6/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.6/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.2.6
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-12 16:03:32 +02:00
Leendert de Borst
e817326162 Merge pull request #774 from lanedirt/772-feature-request-add-proton-pass-import
Add Proton Pass importer
2025-04-12 16:03:19 +02:00
Leendert de Borst
461f765395 Make autofill work with new sqlite client (#771) 2025-04-11 22:18:03 +02:00
Leendert de Borst
f8b5f4a3dd Fix Swift base64 sqlite decryption flow (#771) 2025-04-11 21:00:01 +02:00
Leendert de Borst
55648e95b4 Add native swift SQLite implementation (#771) 2025-04-11 18:09:55 +02:00
Leendert de Borst
1c75782e46 Fix 2FA code entry (#771) 2025-04-11 17:00:10 +02:00
Leendert de Borst
098cf162fd Add deploy to phone task (#771) 2025-04-11 16:50:05 +02:00
Leendert de Borst
653ea2b657 Show credentials when logged in (#771) 2025-04-11 16:41:42 +02:00
Leendert de Borst
eda0fb4d4e Make sqlite work (#771) 2025-04-11 16:41:15 +02:00
Leendert de Borst
baf1f24379 Implement react-native AES-GCM-256 decryption (#771) 2025-04-11 15:24:02 +02:00
Leendert de Borst
cfcce0ec3e Add native react argon2id implementation, add SRP polyfill (#771) 2025-04-11 14:32:43 +02:00
Leendert de Borst
1b70c0c727 Add scaffolding for react native based on browser extension react (#771) 2025-04-11 13:48:46 +02:00
Leendert de Borst
0065d4be10 Update iOS scheme name (#771) 2025-04-11 12:56:18 +02:00
Leendert de Borst
9d2a397317 Add ProtonPass importer (#772) 2025-04-11 11:32:13 +02:00
Leendert de Borst
27e279e812 Update android logo and splashscreen (#771) 2025-04-10 17:03:08 +02:00
Leendert de Borst
568f2c61af Refactor xcode project name conventions (#771) 2025-04-10 15:51:53 +02:00
Leendert de Borst
d1b3e97c6b Port java to kotlin (#771) 2025-04-10 14:37:46 +02:00
Leendert de Borst
87a6807d04 Make basic autofill implementation work for FF in Android (#771) 2025-04-10 13:26:04 +02:00
Leendert de Borst
77a14bedcd Make AutofillService mock implementation (#711) 2025-04-10 13:12:40 +02:00
Leendert de Borst
59fc34a09e Add Android autofill service declaration (#771) 2025-04-10 12:47:33 +02:00
Leendert de Borst
9dfca63703 Only trigger encrypt key retrieval if there are encrypted contents (#771) 2025-04-10 12:25:44 +02:00
Leendert de Borst
7e7d86be25 Generate random encryption key and persist in keyvault (#771) 2025-04-10 12:20:37 +02:00
Leendert de Borst
15b44e4575 Add basic encrypt/decrypt with IV part of encrypted blob (#771) 2025-04-10 12:04:56 +02:00
Leendert de Borst
c87a1cc37a Revert SharedCredentialStore.java to simple starting point (#771) 2025-04-10 11:56:33 +02:00
Leendert de Borst
4b828002ec Refactor SharedCredentialStore.java (#771) 2025-04-09 23:31:53 +02:00
Leendert de Borst
46d9709dcf Make biometric auth protection work in Android (#771) 2025-04-09 22:51:00 +02:00
Leendert de Borst
ba02533b5c Make android app buildable (#771) 2025-04-09 22:41:41 +02:00
Leendert de Borst
a99fa1215e Update splash screen logo (#771) 2025-04-09 18:54:10 +02:00
Leendert de Borst
e8a077041b Add app icons (#771) 2025-04-09 18:25:22 +02:00
Leendert de Borst
82304029bf Convert UIKit to SwiftUI (#771) 2025-04-09 17:55:09 +02:00
Leendert de Borst
ae5b4e070f Remove storyboard from extension (#771) 2025-04-09 17:23:20 +02:00
Leendert de Borst
e6149a8936 Add more scaffolding (#771) 2025-04-09 15:49:37 +02:00
Leendert de Borst
de6a46fb8e Add keychain access protected storage to iOS app (#771) 2025-04-09 12:39:45 +02:00
Leendert de Borst
dc0ee00084 Refresh credential list on focus (#771) 2025-04-08 17:23:33 +02:00
Leendert de Borst
8a1154522e Show saved credentials in react native (#771) 2025-04-08 17:19:58 +02:00
Leendert de Borst
a6c4d1e8a5 Make credentialmanager work from react native (#771) 2025-04-08 17:05:24 +02:00
Leendert de Borst
1652a41840 Add example credential add to extension (#771) 2025-04-08 16:55:11 +02:00
Leendert de Borst
03772511bb Enable autofill extension to show up (#771) 2025-04-08 16:23:02 +02:00
Leendert de Borst
dd3a41735f Update bundle identifier and add app group (#771) 2025-04-08 14:09:53 +02:00
Leendert de Borst
5cfa1e2b13 Update app.json (#771) 2025-04-08 13:57:10 +02:00
Leendert de Borst
d661b3961b Add iOS app run task (#771) 2025-04-08 13:48:57 +02:00
Leendert de Borst
9b0661f0de Add react native expo scaffolding (#771) 2025-04-08 13:44:44 +02:00
dependabot[bot]
8f42ebdfa4 Bump System.Drawing.Common from 8.0.0 to 9.0.3
Bumps [System.Drawing.Common](https://github.com/dotnet/winforms) from 8.0.0 to 9.0.3.
- [Release notes](https://github.com/dotnet/winforms/releases)
- [Changelog](https://github.com/dotnet/winforms/blob/main/docs/release-activity.md)
- [Commits](https://github.com/dotnet/winforms/compare/v8.0.0...v9.0.3)

---
updated-dependencies:
- dependency-name: System.Drawing.Common
  dependency-version: 9.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 09:38:52 +02:00
dependabot[bot]
3aab43b17a Bump Swashbuckle.AspNetCore from 8.0.0 to 8.1.0
Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 8.0.0 to 8.1.0.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v8.0.0...v8.1.0)

---
updated-dependencies:
- dependency-name: Swashbuckle.AspNetCore
  dependency-version: 8.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 09:38:42 +02:00
dependabot[bot]
6e922237c0 Bump NUglify from 1.21.13 to 1.21.14
Bumps [NUglify](https://github.com/trullock/NUglify) from 1.21.13 to 1.21.14.
- [Release notes](https://github.com/trullock/NUglify/releases)
- [Changelog](https://github.com/trullock/NUglify/blob/master/changelog.md)
- [Commits](https://github.com/trullock/NUglify/compare/v1.21.13...v1.21.14)

---
updated-dependencies:
- dependency-name: NUglify
  dependency-version: 1.21.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 09:38:36 +02:00
Leendert de Borst
ebac252162 Merge pull request #767 from lanedirt/dependabot/nuget/main/NUnit.Analyzers-4.7.0
Bump NUnit.Analyzers from 4.6.0 to 4.7.0
2025-04-08 09:38:20 +02:00
dependabot[bot]
9df76ffb43 Bump NUnit.Analyzers from 4.6.0 to 4.7.0
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 4.6.0 to 4.7.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.md)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/4.6.0...4.7.0)

---
updated-dependencies:
- dependency-name: NUnit.Analyzers
  dependency-version: 4.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 09:56:30 +00:00
Leendert de Borst
2d59117112 Merge pull request #765 from lanedirt/764-prepare-0160-release
Bump version to 0.16.0
2025-04-07 09:36:36 +02:00
dependabot[bot]
ccb66af1ca Bump vite (#766)
Bumps the npm_and_yarn group with 1 update in the /browser-extension directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.4 to 6.2.5
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.5/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.2.5
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 21:42:36 +02:00
Leendert de Borst
f4093a9199 Fix safari extension settings open bug (#764) 2025-04-03 19:35:32 +02:00
Leendert de Borst
290601ccfb Update README.md (#764) 2025-04-03 17:35:46 +02:00
Leendert de Borst
77be2a339e Bump version to 0.16.0 (#764) 2025-04-03 16:52:05 +02:00
Leendert de Borst
c0b23c15e7 Make browser extension identity generator language aware (#761) 2025-04-03 15:25:20 +02:00
Leendert de Borst
4af158b35d Update tests (#760) 2025-04-03 13:28:22 +02:00
Leendert de Borst
abfabc2a4a Update credential terminology (#760) 2025-04-03 13:28:22 +02:00
Leendert de Borst
a0036da781 Fix search widget click outside behavior (#760) 2025-04-03 13:28:22 +02:00
Leendert de Borst
99f084558d Improve form autofill and add new test case (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
d7be5fc308 Add enter to submit for custom alias form (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
485e867c50 Generic refactor and UX tweaks (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
d2e5f3c715 Add datetime empty string sanity check converter to client (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
0cbe5fec93 Update alias email reference (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
7f7c729e82 Update create popup UI (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
35cc29e751 Refactor linting issues (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
8a16a29727 Remember last used email/username input (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
708cffc49e UI usability tweaks (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
74c0ace2b5 Pass password to the to be created credential (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
55175a7db6 UI tweaks (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
7e1f33e4e1 Update form validation (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
81362b165b Add manual credential option to create new alias popup (#758) 2025-04-03 12:54:08 +02:00
Leendert de Borst
41d6511eb2 Attach shadowroot to html immediately instead as waiting for element doesn't work (#756) 2025-04-02 17:12:50 +02:00
Leendert de Borst
60ba96cb86 Remove autocomplete=off check and attach autofill popup shadowroot to input itself (#756) 2025-04-02 17:12:50 +02:00
Leendert de Borst
fdd8c8b37e Add BadRequest handling to browser extension auth (#734) 2025-04-02 12:55:55 +02:00
Leendert de Borst
53fcb2f2e4 Exclude primary email from confirm email field search (#732) 2025-04-01 22:44:03 +02:00
Leendert de Borst
b1848320d9 Add FormDetector hidden field tests (#732) 2025-04-01 22:44:03 +02:00
Leendert de Borst
610be7e30b Improve FormDetector to ignore hidden elements and improve email detection (#732) 2025-04-01 22:44:03 +02:00
Leendert de Borst
933e458776 Fill in username in email field if no email is available (#732) 2025-04-01 22:44:03 +02:00
Leendert de Borst
b460e6ec20 Fix null issue when searching in popup (#732) 2025-04-01 22:44:03 +02:00
Leendert de Borst
80cd371ee3 Add retry to faviconextractor to bypass certain cookiewalls (#745) 2025-04-01 17:16:58 +02:00
Leendert de Borst
915e12d541 Centralize favicon render logic and make it format aware (#745) 2025-04-01 17:16:58 +02:00
Leendert de Borst
c8d78e0b02 Merge pull request #748 from lanedirt/746-bug-browser-extension-renders-credential-without-alias-full-name-field-as-null-null
Optimize display of legacy credentials that don't have alias fields
2025-04-01 13:54:55 +02:00
Leendert de Borst
199941a837 Make CheckHasAlias static (#746) 2025-04-01 13:54:34 +02:00
Leendert de Borst
1e0c586dba Merge branch '746-bug-browser-extension-renders-credential-without-alias-full-name-field-as-null-null' of https://github.com/lanedirt/AliasVault into 746-bug-browser-extension-renders-credential-without-alias-full-name-field-as-null-null
* '746-bug-browser-extension-renders-credential-without-alias-full-name-field-as-null-null' of https://github.com/lanedirt/AliasVault:
  Add birthdate minvalue filter to main client UI (#746)
2025-04-01 13:38:27 +02:00
Leendert de Borst
37e59dcd4e Update PlaywrightInputHelper.cs (#746) 2025-04-01 13:37:52 +02:00
Leendert de Borst
e665130ea7 Add birthdate minvalue filter to main client UI (#746) 2025-04-01 13:29:23 +02:00
Leendert de Borst
c0aac4ef72 Add birthdate minvalue filter to main client UI (#746) 2025-04-01 13:06:31 +02:00
Leendert de Borst
8319ddcce4 Only show fields when they have a value in main client (#746) 2025-04-01 12:58:07 +02:00
Leendert de Borst
adc6293f4b Only show credential fields that have a value in browser extension (#746) 2025-04-01 12:47:28 +02:00
Leendert de Borst
418bfed663 Add browser extension vscode build task (#746) 2025-04-01 10:41:16 +02:00
Leendert de Borst
7074113cbf Update install.md 2025-04-01 10:22:10 +02:00
Leendert de Borst
ddb610051a Fix install curl command to follow redirects 2025-04-01 10:21:38 +02:00
Leendert de Borst
188b7a4062 Update FaviconExtractor.cs (#736) 2025-04-01 00:28:12 +02:00
Leendert de Borst
989d17708f Add duplicate entry detection to import wizard 2025-04-01 00:28:12 +02:00
Leendert de Borst
77a4b4fcba Make credential view link have a http prefix (#542) 2025-04-01 00:27:54 +02:00
Leendert de Borst
0462e3522b Remove git pre-commit hook requirement 2025-03-31 23:57:28 +02:00
Leendert de Borst
f6bddf730f Make search field output full width on mobile (#736) 2025-03-31 23:26:41 +02:00
dependabot[bot]
035403e3e3 Bump vite
Bumps the npm_and_yarn group with 1 update in the /browser-extension directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.3 to 6.2.4
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.4/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 21:04:15 +02:00
Leendert de Borst
33ebbf0fd5 Include favicon and username in search results (#736) 2025-03-31 18:40:24 +02:00
Leendert de Borst
55c75ec094 Change loading spinners to non-blocking AliasVault style (#739) 2025-03-31 18:08:24 +02:00
Leendert de Borst
6e244e611c Refactor to reduce complexity (#735) 2025-03-31 17:53:03 +02:00
Leendert de Borst
e1dc9eb447 Add bulk favicon extraction to import (#735) 2025-03-31 17:53:03 +02:00
Leendert de Borst
7a8b31a98a Improve favicon extraction by resizing too large icons (#735) 2025-03-31 17:53:03 +02:00
Leendert de Borst
9baa70f022 Update text and CSS (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
24106475f9 Refactor (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
c50178967a Add E2E import test (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
a69a6a91e2 Update comments (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
1dca845731 Add separate ResourceReaderUtility to E2E project because of namespace(#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
9bec5a3ae5 Fix double navigation redirect bug (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
1a8dae44ec Refactor returnUrl methods in client (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
ec15c76001 Add import link to OOBE home screen (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
e0c11ba0f6 Add separate importers for KeePass, KeePassXC and Strongbox (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
a72f1139f9 Add firefox import card (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
a3a3d39664 Add firefox importer and unit test (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
014a705a5e Add chrome import card (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
6dfb922292 Add chrome importer and unit test (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
cb78d8a636 Add combined client build task and unit test task (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
a4c4a9c8ec Update todos (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
6f5ae7c17e Add 1Password importer (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
43f5e0c647 Add confirm dialog to vault export actions (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
0e5f611670 Add TOTP code sanitize to import (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
70b7ac6f9f Make AliasVault export/import work again (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
14ee466bec Add logo to modal (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
ea9c3c5683 Update importer icons (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
30b812e8a3 Add importer help text (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
27ba14ee34 UI tweaks (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
2e851701f9 Update multistep form flow and reduce boilerplate (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
a2c2caed79 Add multistep import flow (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
c00e6c6a4d Do import on submit (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
09dda0147b Update ImportExport.razor (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
ef7398b47a Fix Bitwarden CSV import (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
dc769bb5d4 Adjust UnitTests namespace, add CSV importer unit tests (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
634fc281a2 Add Bitwarden importer scaffolding (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
e93b0575ff Refactor import record to credential conversion to BaseImporter.cs (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
3f6575dfe5 Refactor CSV import logic to utility class (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
390877f8f3 Rename CsvImportExport to ImportExport utility (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
55ee3bfd4a Add sample CSV import mapping logic (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
423fe00692 Make example import flow work (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
f8e0d6a293 Refactor import base component to use Blazor childcontent (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
a20b0ed83a Add import/export page UI scaffolding (#542) 2025-03-31 14:18:29 +02:00
Leendert de Borst
ca043954ec Update roadmap 2025-03-28 17:36:37 +01:00
Leendert de Borst
4f0104e8f9 Bump version to 0.15.1 (#729) 2025-03-27 15:52:59 +01:00
Leendert de Borst
ea37c4d8c6 Make .env.example work with install.sh (#727) 2025-03-27 15:41:51 +01:00
Leendert de Borst
95be4beb13 Do env create before other env set commands (#727) 2025-03-27 15:41:51 +01:00
Leendert de Borst
716ef0b30c Update docs layout (#727) 2025-03-27 15:41:51 +01:00
Leendert de Borst
fc0eb0e7e7 Update README.md (#727) 2025-03-27 15:41:51 +01:00
Leendert de Borst
9670178aec Update manual setup instructions (#727) 2025-03-27 15:41:51 +01:00
Leendert de Borst
8503be4d52 Add documentation to .env.example (#727) 2025-03-27 15:41:51 +01:00
Leendert de Borst
9eadcaa2ed Make latest version retrieval work in latest MacOS bash (#725) 2025-03-27 10:17:54 +01:00
dependabot[bot]
e0ed8fd285 Bump vite
Bumps the npm_and_yarn group with 1 update in the /browser-extension directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 6.2.0 to 6.2.3
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.3/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.3/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 20:19:33 +01:00
Leendert de Borst
61748c3d03 Update README.md 2025-03-25 18:37:57 +01:00
Leendert de Borst
faff4844f5 Update release.yml publish paths (#722) 2025-03-25 13:32:50 +01:00
Leendert de Borst
09d931484a Update GitHub workflows (#722) 2025-03-25 13:29:26 +01:00
Leendert de Borst
1678595c13 Bump version to 0.15.0 (#722) 2025-03-25 13:13:05 +01:00
Leendert de Borst
8945b33705 Add install.sh to release artifacts (#722) 2025-03-25 13:13:05 +01:00
Leendert de Borst
4ee044ffb9 Update faviconextractor HtmlAgilityPack call (#715) 2025-03-25 11:53:04 +01:00
dependabot[bot]
5443e147b1 Bump HtmlAgilityPack from 1.11.74 to 1.12.0
Bumps [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) from 1.11.74 to 1.12.0.
- [Release notes](https://github.com/zzzprojects/html-agility-pack/releases)
- [Commits](https://github.com/zzzprojects/html-agility-pack/compare/v1.11.74...v1.12.0)

---
updated-dependencies:
- dependency-name: HtmlAgilityPack
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 11:53:04 +01:00
Leendert de Borst
05edda8b48 Show returning users count in admin dashboard (#720) 2025-03-25 10:48:55 +01:00
Leendert de Borst
179bb62604 Fix bug in search for null credential fields (#718) 2025-03-24 22:21:34 +01:00
Leendert de Borst
1f5863b066 Fix vault dismiss logic when user is not logged in (#718) 2025-03-24 22:21:34 +01:00
Leendert de Borst
ef36a08ef4 Update password autofill to improve compatibility (#718) 2025-03-24 22:21:34 +01:00
dependabot[bot]
4f7212668e Bump Swashbuckle.AspNetCore from 7.3.2 to 8.0.0
Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 7.3.2 to 8.0.0.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v7.3.2...v8.0.0)

---
updated-dependencies:
- dependency-name: Swashbuckle.AspNetCore
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-24 17:52:47 +01:00
dependabot[bot]
41bb7ed701 Bump Microsoft.AspNetCore.Components.WebAssembly.DevServer
Bumps [Microsoft.AspNetCore.Components.WebAssembly.DevServer](https://github.com/dotnet/aspnetcore) from 9.0.2 to 9.0.3.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.2...v9.0.3)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Components.WebAssembly.DevServer
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-24 17:51:49 +01:00
dependabot[bot]
78286b1ac1 Bump nokogiri in /docs in the bundler group across 1 directory
Bumps the bundler group with 1 update in the /docs directory: [nokogiri](https://github.com/sparklemotion/nokogiri).


Updates `nokogiri` from 1.18.3 to 1.18.4
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.18.3...v1.18.4)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-22 10:34:01 +01:00
Leendert de Borst
7bc8bb3fc2 Create FUNDING.yml 2025-03-21 16:36:47 +01:00
Leendert de Borst
c576062025 Fix hyperlinks absolute vs relative address (#711) 2025-03-20 13:55:32 +01:00
Leendert de Borst
1194d54e6f Add E2E test for email claim disable logic (#711) 2025-03-20 13:55:32 +01:00
Leendert de Borst
e782a6a51f Reject emails addressed to disabled email claim (#711) 2025-03-20 13:55:32 +01:00
Leendert de Borst
2071a7c4fe Add email claim enable/disable toggle to admin (#711) 2025-03-20 13:55:32 +01:00
Leendert de Borst
8c1e5a7bf8 Add email claim table disabled boolean (#711) 2025-03-20 13:55:32 +01:00
Leendert de Borst
b8f9e7fa2c Merge pull request #710 from lanedirt/641-add-statistics-graphs-to-admin
Add analytics charts to admin dashboard
2025-03-20 10:04:24 +01:00
Leendert de Borst
a0a541aff9 Update admin tests (#641) 2025-03-19 22:17:59 +01:00
Leendert de Borst
d6932f33ea Update email list page and tweak search fields (#641) 2025-03-19 22:10:13 +01:00
Leendert de Borst
9ea845b497 Add ApexChart service and integrate dark mode (#641) 2025-03-19 19:33:42 +01:00
Leendert de Borst
917d6f6bcc Add charts to admin dashboard (#641) 2025-03-19 17:49:09 +01:00
Leendert de Borst
39a263d157 Update docs (#641) 2025-03-19 15:34:35 +01:00
Leendert de Borst
c7360ee23c Add general log source context to term filter (#705) 2025-03-19 14:23:51 +01:00
Leendert de Borst
d1924f4044 Update header text (#705) 2025-03-19 14:23:51 +01:00
Leendert de Borst
4d86356990 Update users page with credential count column (#705) 2025-03-19 14:23:51 +01:00
Leendert de Borst
505a2445eb Reset page back to 1 when search term changes in admin (#705) 2025-03-19 14:23:51 +01:00
Leendert de Borst
75385c4b5d Remove WASM DevServer package from admin which caused it to not run in debug (#705) 2025-03-19 14:23:51 +01:00
Leendert de Borst
4d4053c7fb Update package-lock.json (#705) 2025-03-19 14:23:51 +01:00
Leendert de Borst
43062d0d93 Update .vscode tasks (#705) 2025-03-19 14:23:51 +01:00
Leendert de Borst
956709da54 Merge pull request #706 from lanedirt/167-allow-customizing-password-generation-options
Make password generation options customizable
2025-03-18 22:15:53 +01:00
Leendert de Borst
496e0ab754 Refactor PasswordGenerator.ts (#167) 2025-03-18 22:04:11 +01:00
Leendert de Borst
ef97aac848 Merge branch 'main' into 167-allow-customizing-password-generation-options 2025-03-18 18:22:09 +01:00
Leendert de Borst
998fa1913f Update dotnet nuget packages to 9.0.3 (#707) 2025-03-18 18:08:32 +01:00
Leendert de Borst
79cd265c3e Add browser extension password settings test (#167) 2025-03-18 17:40:31 +01:00
Leendert de Borst
ed5fd5b861 Disable autofill extension for aliasvault client by default (#167) 2025-03-18 17:12:34 +01:00
Leendert de Borst
5e2dde252d Update tests (#167) 2025-03-18 16:51:49 +01:00
Leendert de Borst
79950ab9fc Add password generator settings awareness to browser extension (#167) 2025-03-18 16:30:41 +01:00
Leendert de Borst
dffa651512 Cleanup (#167) 2025-03-18 14:37:24 +01:00
Leendert de Borst
2dc36cea11 Add password settings to general settings page (#167) 2025-03-18 14:17:49 +01:00
Leendert de Borst
ad4c2c7b41 Add modalwrapper component for keydown detection (#167) 2025-03-18 13:41:43 +01:00
Leendert de Borst
2022cdb58b Improve UX (#167) 2025-03-18 13:08:56 +01:00
Leendert de Borst
5f779ce360 Update UI style (#167) 2025-03-18 12:37:10 +01:00
Leendert de Borst
b9d981f80b Refactor (#167) 2025-03-18 11:30:36 +01:00
Leendert de Borst
65110abf4c Add range binds and sanity checks (#167) 2025-03-18 10:47:06 +01:00
Leendert de Borst
b0e939ef23 Add support for temp or global password settings persist (#167) 2025-03-18 10:19:53 +01:00
Leendert de Borst
607c0da5b4 Make password settings a separate component (#167) 2025-03-18 10:05:10 +01:00
Leendert de Borst
1de7f831b5 Fix recent email refresh duplicate calls (#167) 2025-03-17 22:19:31 +01:00
Leendert de Borst
ef328718cd Refactor password generator and make all use general settings (#167) 2025-03-17 21:28:57 +01:00
Leendert de Borst
465c4cc730 Update username and password button style (#167) 2025-03-17 20:37:26 +01:00
Leendert de Borst
0dceeeffa4 Update docs to include Windows instructions (#703) 2025-03-17 17:56:21 +01:00
Leendert de Borst
af24464a8d Convert install.sh line endings so it works on Windows out of the box (#703) 2025-03-17 17:56:21 +01:00
Leendert de Borst
5aa82d8149 Update username and password edit field GUI (#167) 2025-03-17 15:06:15 +01:00
Leendert de Borst
e848e05cce Cleanup and simplify install.sh (#690) 2025-03-16 15:35:58 +01:00
Leendert de Borst
323be10d03 Tweak password edit component UI (#167) 2025-03-15 18:24:35 +01:00
Leendert de Borst
51b382a739 Add password generation settings GUI scaffolding (#167) 2025-03-15 18:03:45 +01:00
Leendert de Borst
7954104dfc Update README.md 2025-03-14 17:54:51 +01:00
Leendert de Borst
4c7b44c04a Bump version to 0.14.0 (#688) 2025-03-14 14:17:26 +01:00
Leendert de Borst
b41449f892 Remove Microsoft.IdentityModel packages from API which caused method not found bug (#668) 2025-03-14 13:13:36 +01:00
dependabot[bot]
934d0d9e56 Bump Microsoft.IdentityModel.Tokens from 8.6.0 to 8.6.1
Bumps [Microsoft.IdentityModel.Tokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 8.6.0 to 8.6.1.
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.6.0...8.6.1)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.Tokens
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-14 13:13:36 +01:00
Leendert de Borst
99d0da1119 Update docs and README.md (#680) 2025-03-13 15:10:01 +01:00
Leendert de Borst
c74e05d400 Improve create credential popup page title extraction (#686) 2025-03-13 15:09:21 +01:00
dependabot[bot]
844bdab92f Bump MailKit from 4.10.0 to 4.11.0
Bumps [MailKit](https://github.com/jstedfast/MailKit) from 4.10.0 to 4.11.0.
- [Changelog](https://github.com/jstedfast/MailKit/blob/master/ReleaseNotes.md)
- [Commits](https://github.com/jstedfast/MailKit/compare/4.10.0...4.11.0)

---
updated-dependencies:
- dependency-name: MailKit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-13 14:13:02 +01:00
dependabot[bot]
1345e3c657 Bump MimeKit from 4.10.0 to 4.11.0
Bumps [MimeKit](https://github.com/jstedfast/MimeKit) from 4.10.0 to 4.11.0.
- [Changelog](https://github.com/jstedfast/MimeKit/blob/master/ReleaseNotes.md)
- [Commits](https://github.com/jstedfast/MimeKit/compare/4.10.0...4.11.0)

---
updated-dependencies:
- dependency-name: MimeKit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-13 14:12:55 +01:00
Leendert de Borst
4fdf7ce92c Show autofill popup dismiss button when vault is locked (#682) 2025-03-13 14:12:43 +01:00
Leendert de Borst
852d9b5e98 Update tests to wait until all password chars have been entered (#684) 2025-03-13 13:47:39 +01:00
Leendert de Borst
3c72fa3fde Update password autofill mechanism to simulate user typing behavior (#684) 2025-03-13 13:47:39 +01:00
Leendert de Borst
b61b747e4b Add default font-family (#680) 2025-03-13 13:29:57 +01:00
Leendert de Borst
1b4389c7d7 Show manual instructions if opening preferences fails (#680) 2025-03-13 13:29:57 +01:00
Leendert de Borst
499d2759ce Add Safari extension docs (#680) 2025-03-13 13:29:57 +01:00
Leendert de Borst
d0140a8ddb Fix MacOS wrapper app links and content (#680) 2025-03-13 13:29:57 +01:00
Leendert de Borst
76dc465032 Refactor (#678) 2025-03-12 22:02:11 +01:00
Leendert de Borst
84420104ee Iframe and position tweaks (#678) 2025-03-12 22:02:11 +01:00
Leendert de Borst
1109bde521 Refactor all inline styles to separate style.css (#678) 2025-03-12 22:02:11 +01:00
Leendert de Borst
134a173148 Import stylesheet for contentScript (#678) 2025-03-12 22:02:11 +01:00
Leendert de Borst
83be492b3a Refactor injectIcon (#678) 2025-03-12 22:02:11 +01:00
Leendert de Borst
fac72e5a11 Refactor content script to use shadowroot UI (#678) 2025-03-12 22:02:11 +01:00
Leendert de Borst
5eb885da20 Refactor (#661) 2025-03-12 16:07:16 +01:00
Leendert de Borst
da4f286757 Add download links for Firefox, Edge, Safari and Brave (#661) 2025-03-12 16:07:16 +01:00
Leendert de Borst
f6db447ad4 Add Safari extension XCode project scaffolding (#661) 2025-03-12 16:07:16 +01:00
Leendert de Borst
b472ba749c Fix padding issue with search field in Safari (#661) 2025-03-12 16:07:16 +01:00
Leendert de Borst
ef68b3b265 Fix scroll issue for Safari browser (#661) 2025-03-12 16:07:16 +01:00
Leendert de Borst
08d4a8b656 Add light/dark mode toggle to browser extension settings (#661) 2025-03-12 16:07:16 +01:00
Leendert de Borst
93ac131508 Refactor expanded mode check to be called from React (#661) 2025-03-12 16:07:16 +01:00
Leendert de Borst
a7d1536140 Refactor and tweak UI (#672) 2025-03-11 16:59:12 +01:00
Leendert de Borst
4fa3fedea2 Add TotpViewer component (#672) 2025-03-11 16:59:12 +01:00
Leendert de Borst
038e8babb1 Update TotpViewer.razor (#672) 2025-03-11 16:59:12 +01:00
Leendert de Borst
0845477041 Add private vs public email domain documentation (#673) 2025-03-11 11:17:23 +01:00
Leendert de Borst
90156dd1f8 Refactor (#181) 2025-03-11 10:29:25 +01:00
Leendert de Borst
fe4b11cf4d Add TOTP E2E tests (#181) 2025-03-11 10:29:25 +01:00
Leendert de Borst
2cbf234d05 Refactor (#181) 2025-03-11 10:29:25 +01:00
Leendert de Borst
a53575b4bf Add click to copy and form validation (#181) 2025-03-11 10:29:25 +01:00
Leendert de Borst
697abc6828 Refactor TOTP code to work view AddEdit/View mode (#181) 2025-03-11 10:29:25 +01:00
Leendert de Borst
e96cfa3940 Update UX (#181) 2025-03-11 10:29:25 +01:00
Leendert de Borst
61a88e6715 Add credentials TOTP code scaffolding (#181) 2025-03-11 10:29:25 +01:00
Leendert de Borst
e07a35b214 Add firefox addon link to docs (#665) 2025-03-11 09:59:07 +01:00
Leendert de Borst
4a79fafbb9 Update README.md 2025-03-09 21:32:02 +01:00
Leendert de Borst
02b9bff64e Update browser-extension-build.yml (#665) 2025-03-09 20:46:50 +01:00
Leendert de Borst
55e02478b4 Merge pull request #666 from lanedirt/665-prepare-0130-release
Bump version to 0.13.0
2025-03-09 20:25:25 +01:00
Leendert de Borst
a576908ae2 Add edge extension store link (#665) 2025-03-09 19:55:21 +01:00
Leendert de Borst
95510f793b Unzip before uploading files to artifact (#665) 2025-03-09 16:39:53 +01:00
Leendert de Borst
20a4a82b1b Add compression level to prevent re-compressing (#665) 2025-03-09 16:28:50 +01:00
Leendert de Borst
61ba6e1a3c Store less vault revisions to reduce history filesize (#663) 2025-03-08 00:36:37 +00:00
Leendert de Borst
f28f1f07b8 Bump version to 0.13.0 (#665) 2025-03-08 01:23:32 +01:00
Leendert de Borst
7f186f1345 Update browser-extension-build.yml use short git hash (#581) 2025-03-07 22:50:55 +01:00
Leendert de Borst
129b50afba Update browser-extension-build.yml artifact paths (#581) 2025-03-07 22:32:31 +01:00
Leendert de Borst
bad0f485a9 Update browser-extension-build.yml to make all filenames consistent (#581) 2025-03-07 18:35:06 +01:00
Leendert de Borst
5d9ae7d189 Update browser-extension-build.yml firefox glob pattern (#581) 2025-03-07 18:30:58 +01:00
Leendert de Borst
ef8ab63b66 Add full paths to browser-extension-build.yml (#581) 2025-03-07 18:22:01 +01:00
dependabot[bot]
469466995c Bump NUglify from 1.21.12 to 1.21.13
Bumps [NUglify](https://github.com/trullock/NUglify) from 1.21.12 to 1.21.13.
- [Release notes](https://github.com/trullock/NUglify/releases)
- [Changelog](https://github.com/trullock/NUglify/blob/master/changelog.md)
- [Commits](https://github.com/trullock/NUglify/compare/v1.21.12...v1.21.13)

---
updated-dependencies:
- dependency-name: NUglify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-07 17:16:18 +00:00
dependabot[bot]
62c5edc7dc Bump Swashbuckle.AspNetCore from 7.2.0 to 7.3.1
Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 7.2.0 to 7.3.1.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v7.2.0...v7.3.1)

---
updated-dependencies:
- dependency-name: Swashbuckle.AspNetCore
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-07 17:16:08 +00:00
dependabot[bot]
ba625a30ea Bump NUnit3TestAdapter from 4.6.0 to 5.0.0
Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 4.6.0 to 5.0.0.
- [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases)
- [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V4.6.0...V5.0.0)

---
updated-dependencies:
- dependency-name: NUnit3TestAdapter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-07 17:15:57 +00:00
dependabot[bot]
bcdcbef912 Bump HtmlAgilityPack from 1.11.72 to 1.11.74
Bumps [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) from 1.11.72 to 1.11.74.
- [Release notes](https://github.com/zzzprojects/html-agility-pack/releases)
- [Commits](https://github.com/zzzprojects/html-agility-pack/compare/v1.11.72...v1.11.74)

---
updated-dependencies:
- dependency-name: HtmlAgilityPack
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-07 17:15:49 +00:00
Leendert de Borst
a64ed4817a Add returning users and email aliases cards to admin dashboard (#640) 2025-03-07 17:15:39 +00:00
Leendert de Borst
919a33defb Add total amount of records to admin page lists (#640) 2025-03-07 17:15:39 +00:00
Leendert de Borst
7e08f64175 Update MS edge browser extension docs (#581) 2025-03-07 17:18:38 +01:00
Leendert de Borst
e525bd1c2d Merge pull request #660 from lanedirt/581-feature-request-add-firefox-browser-extension
Add Firefox and Edge browser extension
2025-03-07 16:14:32 +00:00
Leendert de Borst
7298f8914d Add MS Edge as browser extension build target (#581) 2025-03-07 17:00:14 +01:00
Leendert de Borst
c476c53101 Update browser extension dictionaries folder load (#581) 2025-03-07 16:35:56 +01:00
Leendert de Borst
b6c7e88000 Refactor stop words to lang file (#581) 2025-03-07 15:34:24 +01:00
Leendert de Borst
26624e165a Update supported browser extension list in API (#581) 2025-03-07 15:28:07 +01:00
Leendert de Borst
c079b830b5 Add browser specific client name (#581) 2025-03-07 15:16:36 +01:00
Leendert de Borst
165a89e946 Use style.css instead of inline styles (#581) 2025-03-07 15:14:04 +01:00
Leendert de Borst
5042e1b696 Fix lint (#581) 2025-03-07 15:00:52 +01:00
Leendert de Borst
472a79a12b Update npm cache path (#581) 2025-03-07 14:58:23 +01:00
Leendert de Borst
97730cd721 Remove old browser extensions dir (#581) 2025-03-07 14:48:07 +01:00
Leendert de Borst
d5400faf95 Refactor chrome specific API, set font-size to 75% for all browsers (#581) 2025-03-07 14:47:12 +01:00
Leendert de Borst
9b8da64858 Refactor react entrypoint (#581) 2025-03-07 13:30:27 +01:00
Leendert de Borst
9ce776be2b Update docs for firefox browser extension (#581) 2025-03-07 13:05:22 +01:00
Leendert de Borst
d674c77216 Add firefox as browser extension target (#581) 2025-03-07 12:42:29 +01:00
Leendert de Borst
e41c4b3213 Update E2E tests (#581) 2025-03-07 12:18:40 +01:00
Leendert de Borst
f88670787f Update readme (#581) 2025-03-07 12:18:29 +01:00
Leendert de Borst
261be3ab34 Update feature_request.md 2025-03-07 12:01:52 +01:00
Leendert de Borst
0bace49e95 Update browser extension output path (#581) 2025-03-07 11:33:27 +01:00
Leendert de Borst
bb82952c74 Update github browser extension workflow for new path (#581) 2025-03-07 11:22:59 +01:00
Leendert de Borst
fd5244a686 Fix all linting issues (#581) 2025-03-07 01:18:14 +01:00
Leendert de Borst
09bc4286d9 Add linting packages (#581) 2025-03-07 00:49:47 +01:00
Leendert de Borst
4c45047d23 Add identity generator dict loader and test packages (#581) 2025-03-07 00:27:20 +01:00
Leendert de Borst
5251ea53ca Refactor contextmenu to use wxt browser api (#581) 2025-03-06 23:37:45 +01:00
Leendert de Borst
2da9955213 Refactor popup settings to use wxt browser (#581) 2025-03-06 23:29:05 +01:00
Leendert de Borst
fab12daacf Change index.html to popup.html paths (#581) 2025-03-06 19:32:23 +01:00
Leendert de Borst
9ba467479a Refactor messaging to use webext-bridge (#581) 2025-03-06 19:07:12 +01:00
Leendert de Borst
8e698a21fa Add all dependencies, refactor messaging (#581) 2025-03-06 18:47:16 +01:00
Leendert de Borst
28a0c7eb1f Wrap browser extension in wxt for multi-browser compilation (#581) 2025-03-06 16:17:14 +01:00
Leendert de Borst
fcbe8da1e6 Add minimum height to credential table view to not obstruct settings popup (#656) 2025-03-06 13:06:56 +00:00
Leendert de Borst
a0a3a2e14a Hide browser extension autofill injected icon on key press (#653) 2025-03-06 11:27:50 +00:00
Leendert de Borst
4fff14480b Add troubleshooting guide to docs (#655) 2025-03-06 11:11:15 +00:00
Leendert de Borst
c7ad42a63e Update PULL_REQUEST_TEMPLATE.md 2025-03-06 11:32:51 +01:00
Leendert de Borst
6df3c03682 Add less severe log message for email received for orphaned user email claim (#651) 2025-03-06 10:27:49 +00:00
Leendert de Borst
7da5557b98 Refactor favicon fetch to separate method (#649) 2025-03-06 09:41:52 +00:00
Leendert de Borst
38399e00cb Add favicon extract resize and compression (#649) 2025-03-06 09:41:52 +00:00
Leendert de Borst
b30338de37 Add extension version to settings page (#647) 2025-03-06 09:41:41 +00:00
Leendert de Borst
ceaa7731fe Update bottomnav to update selected item on path change (#647) 2025-03-06 09:41:41 +00:00
Leendert de Borst
b66c41e4c9 Add manual merge button, fix db upgrade test revision number (#643) 2025-03-05 19:40:31 +00:00
Leendert de Borst
9e478c94f9 Add browser extension vault outdate check, fix db create wait flow (#643) 2025-03-05 19:40:31 +00:00
Leendert de Borst
b415043b4e Add E2E test for browser extension credential create flow (#643) 2025-03-05 19:40:31 +00:00
dependabot[bot]
10f6525e94 Bump the npm_and_yarn group across 1 directory with 2 updates
Bumps the npm_and_yarn group with 2 updates in the /browser-extensions/chrome directory: [esbuild](https://github.com/evanw/esbuild) and [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `esbuild` from 0.24.2 to 0.25.0
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2024.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.24.2...v0.25.0)

Updates `vite` from 6.0.11 to 6.2.0
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@6.2.0/packages/vite)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: vite
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-05 19:29:21 +00:00
dependabot[bot]
5fb12f26fe Bump uri in /docs in the bundler group across 1 directory
Bumps the bundler group with 1 update in the /docs directory: [uri](https://github.com/ruby/uri).


Updates `uri` from 1.0.2 to 1.0.3
- [Release notes](https://github.com/ruby/uri/releases)
- [Commits](https://github.com/ruby/uri/compare/v1.0.2...v1.0.3)

---
updated-dependencies:
- dependency-name: uri
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-05 16:21:51 +00:00
Leendert de Borst
6047c8f80d Update ConversionUtility.tsx (#638) 2025-03-05 12:15:39 +00:00
Leendert de Borst
1b6e220c5a Update TestUtils.ts (#638) 2025-03-05 12:15:39 +00:00
Leendert de Borst
b2093b5892 Refactor birthdate and gender field fill methods (#638) 2025-03-05 12:15:39 +00:00
Leendert de Borst
b81eabc583 Add locale specific formfiller tests and refactor all locale parts (#638) 2025-03-05 12:15:39 +00:00
Leendert de Borst
0c4be1398d Add FormFiller unit tests (#638) 2025-03-05 12:15:39 +00:00
Leendert de Borst
4aa0e5f8a1 Refactor form fill logic to its own class (#638) 2025-03-05 12:15:39 +00:00
Leendert de Borst
63c737b6cc Update tests (#628) 2025-03-04 17:43:06 +00:00
Leendert de Borst
44c2331b42 Refactor (#628) 2025-03-04 17:43:06 +00:00
Leendert de Borst
8f9058e1b8 Tweak tutorial with browser extension dl links (#628) 2025-03-04 17:43:06 +00:00
Leendert de Borst
613fb7db12 Refactor browser extension info to shared constants (#628) 2025-03-04 17:43:06 +00:00
Leendert de Borst
c4738637f1 Upload empty vault directly as part of creation step (#628) 2025-03-04 17:43:06 +00:00
Jack Bayliss
151cb19de8 Update README.md (#634) 2025-03-04 14:33:52 +01:00
Leendert de Borst
b0c53ca7b4 Add screenshots to README.md (#633)
* Update README.md

* Update README.md

* Update README.md
2025-03-03 13:43:27 +01:00
Leendert de Borst
586285c5e8 Update README.md 2025-03-03 12:09:24 +01:00
Leendert de Borst
5ca8fb92c8 Update README.md 2025-03-03 11:50:49 +01:00
Leendert de Borst
206254574a Bump version to 0.12.3 (#626) 2025-02-28 19:01:36 +01:00
Leendert de Borst
9a9fb12d73 Merge pull request #625 from lanedirt/622-make-browser-extension-autofill-popup-more-robust
Make browser extension autofill popup more robust
2025-02-28 18:39:04 +01:00
Leendert de Borst
5d0540ee2b Autofill form directly after creating new credential (#622) 2025-02-28 18:15:37 +01:00
Leendert de Borst
59726d87e8 Add full name form detection test (#622) 2025-02-28 13:30:35 +01:00
Leendert de Borst
7dccb6443a Improve firstname/lastname detection (#624) 2025-02-28 12:41:33 +01:00
Leendert de Borst
451fe98102 Add full name to form detector (#622) 2025-02-28 12:40:17 +01:00
Leendert de Borst
a82b7d7ce5 Update tailwind css (#622) 2025-02-28 12:12:23 +01:00
Leendert de Borst
9cbaf51778 Merge branch 'main' into 622-make-browser-extension-autofill-popup-more-robust 2025-02-28 12:00:04 +01:00
Leendert de Borst
1847293162 Merge pull request #621 from lanedirt/620-add-browser-extension-download-links-to-client
Add browser extension page and download links
2025-02-27 22:22:38 +01:00
Leendert de Borst
e5a174443d Merge branch 'main' into 620-add-browser-extension-download-links-to-client 2025-02-27 22:22:01 +01:00
Leendert de Borst
2382ee6592 Update brave detection and responsive design (#620) 2025-02-27 20:23:13 +01:00
Leendert de Borst
7253d1fee2 Do all logout actions via webapi which calls authcontext too (#622) 2025-02-27 17:53:48 +01:00
Leendert de Borst
bc16167293 Refactor (#622) 2025-02-27 17:53:48 +01:00
Leendert de Borst
eb587e3496 Add webapi logout call to all places (#622) 2025-02-27 17:53:48 +01:00
Leendert de Borst
6d0352923a Simplify main logout flow to use page redirect (#622) 2025-02-27 17:53:48 +01:00
Leendert de Borst
6d33f99d62 Update favicon display in client to handle SVG (#622) 2025-02-27 17:53:48 +01:00
Leendert de Borst
9fbdb2efbb Update form detection and popup icon display (#622) 2025-02-27 17:53:48 +01:00
Leendert de Borst
50817b65d3 Make popup create button more robust (#622) 2025-02-27 17:53:48 +01:00
Leendert de Borst
5750eef248 Add client header to webapi token refresh call (#618) 2025-02-27 17:52:01 +01:00
Leendert de Borst
5cd5efca4a Do all logout actions via webapi which calls authcontext too (#622) 2025-02-27 17:35:28 +01:00
Leendert de Borst
7ce841b4b5 Refactor (#622) 2025-02-27 17:19:33 +01:00
Leendert de Borst
5e1c79610f Add webapi logout call to all places (#622) 2025-02-27 16:54:54 +01:00
Leendert de Borst
a2ccee984b Simplify main logout flow to use page redirect (#622) 2025-02-27 16:39:33 +01:00
Leendert de Borst
f9977fb29e Update favicon display in client to handle SVG (#622) 2025-02-27 16:11:23 +01:00
Leendert de Borst
f8ea8fc7ce Update form detection and popup icon display (#622) 2025-02-27 15:48:56 +01:00
Leendert de Borst
4ab5be17c0 Make popup create button more robust (#622) 2025-02-27 15:24:54 +01:00
Leendert de Borst
ad8f13928e Make browser extension highlight/other dynamic (#620) 2025-02-27 14:12:00 +01:00
Leendert de Borst
29af7c2196 Add browser extension page and download links (#620) 2025-02-27 12:24:51 +01:00
Leendert de Borst
b25f6580cd Update README.md 2025-02-26 17:17:20 +01:00
Leendert de Borst
71ae5d0904 Update browser-extension-tests.yml 2025-02-25 13:50:34 +01:00
Leendert de Borst
5baede08a7 Bump version to 0.12.2 (#616) 2025-02-25 13:41:55 +01:00
Leendert de Borst
34995fe801 Fix cueck if client or api url are empty (#612) 2025-02-25 12:48:53 +01:00
Leendert de Borst
92a2511d9d Fix bug in browser extension emails list if credential has no email address (#612) 2025-02-25 12:48:53 +01:00
Leendert de Borst
41486c940c Update max nginx upload filesize to 25MB (#613) 2025-02-25 12:48:37 +01:00
Leendert de Borst
47c77ade02 Update install.sh to set default ip_logging value (#610) 2025-02-25 12:48:13 +01:00
Leendert de Borst
a51621970d Update browser-extension-tests.yml 2025-02-24 21:46:42 +01:00
Leendert de Borst
39f339b659 Bump version to 0.12.1 (#608) 2025-02-24 21:28:08 +01:00
Leendert de Borst
65d1ca1564 Add try catch for incorrect status login call (#601) 2025-02-24 21:27:57 +01:00
Leendert de Borst
5c010cd873 Add private/public email validation before showing recent emails (#602) 2025-02-24 21:20:21 +01:00
Leendert de Borst
88ba57ce88 Fix chrome extension API URL switching (#600) 2025-02-24 21:20:12 +01:00
Leendert de Borst
4d266beb0d Add anchor tag conversion to open in new tab in email display (#603) 2025-02-24 21:20:02 +01:00
Leendert de Borst
536688d110 Enable manual workflow dispatch for release archive logic 2025-02-24 18:16:10 +01:00
Leendert de Borst
e343b48fe7 Update browser-extension-tests.yml 2025-02-24 18:10:54 +01:00
Leendert de Borst
9d02737516 Reduce credential table margins (#578) 2025-02-24 17:59:27 +01:00
Leendert de Borst
4a1583a7ff Bump version to 0.12.0 (#598) 2025-02-24 16:46:50 +01:00
Leendert de Borst
4f8125ddb0 Ignore BrowserWasmTests as it no longer works in Chrome (#593) 2025-02-24 15:58:19 +01:00
Leendert de Borst
972505c174 Refactor close popup (#578) 2025-02-24 14:10:48 +01:00
Leendert de Borst
d5e83d2319 Update credentials table sort logic (#578) 2025-02-24 14:10:48 +01:00
Leendert de Borst
9daac83768 Add credentials table view and configure asc/desc sort (#578) 2025-02-24 14:10:48 +01:00
Leendert de Borst
bb477e6f91 Bump all Microsoft dependencies to .NET 9.0.2 (#593) 2025-02-24 14:02:50 +01:00
Leendert de Borst
b216a9d2a9 Bump dependencies across projects (#593) 2025-02-24 13:48:25 +01:00
dependabot[bot]
b66bcefdde Bump Microsoft.Extensions.Configuration from 9.0.1 to 9.0.2
Bumps [Microsoft.Extensions.Configuration](https://github.com/dotnet/runtime) from 9.0.1 to 9.0.2.
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v9.0.1...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.Extensions.Configuration
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 13:42:04 +01:00
Leendert de Borst
6fdb9a7c3e Merge pull request #593 from lanedirt/dependabot/nuget/main/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore-9.0.2
Bump Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore from 9.0.1 to 9.0.2
2025-02-24 13:34:32 +01:00
Leendert de Borst
411b2262e1 Merge branch 'main' into dependabot/nuget/main/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore-9.0.2 2025-02-24 13:34:23 +01:00
Leendert de Borst
72b82671f9 Merge pull request #591 from lanedirt/dependabot/nuget/main/multi-7c78ffaa07
Bump Microsoft.EntityFrameworkCore and Microsoft.EntityFrameworkCore.Design
2025-02-24 13:33:51 +01:00
Leendert de Borst
713c21b60c Merge branch 'main' into dependabot/nuget/main/multi-7c78ffaa07 2025-02-24 13:33:29 +01:00
dependabot[bot]
84b592df7b Bump Microsoft.AspNetCore.Authorization and Microsoft.AspNetCore.Components.WebAssembly.Authentication
Bumps [Microsoft.AspNetCore.Authorization](https://github.com/dotnet/aspnetcore) and [Microsoft.AspNetCore.Components.WebAssembly.Authentication](https://github.com/dotnet/aspnetcore). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Authorization` from 9.0.1 to 9.0.2
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.2)

Updates `Microsoft.AspNetCore.Components.WebAssembly.Authentication` from 9.0.1 to 9.0.2
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authorization
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.AspNetCore.Components.WebAssembly.Authentication
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 13:20:06 +01:00
dependabot[bot]
8420f2d42e Bump Microsoft.AspNetCore.Authorization and Microsoft.AspNetCore.Components.Web
Bumps [Microsoft.AspNetCore.Authorization](https://github.com/dotnet/aspnetcore) and [Microsoft.AspNetCore.Components.Web](https://github.com/dotnet/aspnetcore). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Authorization` from 9.0.1 to 9.0.2
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.2)

Updates `Microsoft.AspNetCore.Components.Web` from 9.0.1 to 9.0.2
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authorization
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.AspNetCore.Components.Web
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 13:19:58 +01:00
dependabot[bot]
58ed0bbf4a Bump Microsoft.EntityFrameworkCore and Microsoft.EntityFrameworkCore.Proxies
Bumps [Microsoft.EntityFrameworkCore](https://github.com/dotnet/efcore) and [Microsoft.EntityFrameworkCore.Proxies](https://github.com/dotnet/efcore). These dependencies needed to be updated together.

Updates `Microsoft.EntityFrameworkCore` from 9.0.0 to 9.0.2
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.0...v9.0.2)

Updates `Microsoft.EntityFrameworkCore.Proxies` from 9.0.0 to 9.0.2
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.0...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.EntityFrameworkCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.EntityFrameworkCore.Proxies
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 13:19:44 +01:00
dependabot[bot]
153e10fcd0 Bump Microsoft.EntityFrameworkCore.Tools from 9.0.1 to 9.0.2
Bumps [Microsoft.EntityFrameworkCore.Tools](https://github.com/dotnet/efcore) from 9.0.1 to 9.0.2.
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.1...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.EntityFrameworkCore.Tools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 13:19:36 +01:00
dependabot[bot]
717dec329b Bump NUglify from 1.21.11 to 1.21.12
Bumps [NUglify](https://github.com/trullock/NUglify) from 1.21.11 to 1.21.12.
- [Release notes](https://github.com/trullock/NUglify/releases)
- [Changelog](https://github.com/trullock/NUglify/blob/master/changelog.md)
- [Commits](https://github.com/trullock/NUglify/compare/v1.21.11...v1.21.12)

---
updated-dependencies:
- dependency-name: NUglify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 13:19:28 +01:00
dependabot[bot]
0bd25e70f5 Bump Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Tokens
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) and [Microsoft.IdentityModel.Tokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet). These dependencies needed to be updated together.

Updates `Microsoft.IdentityModel.JsonWebTokens` from 8.3.1 to 8.6.0
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.3.1...8.6.0)

Updates `Microsoft.IdentityModel.Tokens` from 8.3.1 to 8.6.0
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.3.1...8.6.0)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: Microsoft.IdentityModel.Tokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 13:19:21 +01:00
dependabot[bot]
920c1bdebe Bump Microsoft.AspNetCore.DataProtection from 9.0.1 to 9.0.2
Bumps [Microsoft.AspNetCore.DataProtection](https://github.com/dotnet/aspnetcore) from 9.0.1 to 9.0.2.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.DataProtection
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 13:19:13 +01:00
dependabot[bot]
6506b57d9f Bump Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Bumps [Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore](https://github.com/dotnet/aspnetcore) from 9.0.1 to 9.0.2.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 10:47:56 +00:00
dependabot[bot]
aea98a51a9 Bump Microsoft.EntityFrameworkCore and Microsoft.EntityFrameworkCore.Design
Bumps [Microsoft.EntityFrameworkCore](https://github.com/dotnet/efcore) and [Microsoft.EntityFrameworkCore.Design](https://github.com/dotnet/efcore). These dependencies needed to be updated together.

Updates `Microsoft.EntityFrameworkCore` from 9.0.0 to 9.0.2
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.0...v9.0.2)

Updates `Microsoft.EntityFrameworkCore.Design` from 9.0.0 to 9.0.2
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.0...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.EntityFrameworkCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.EntityFrameworkCore.Design
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 10:43:30 +00:00
Leendert de Borst
7f28001f7e Merge pull request #585 from lanedirt/571-feature-request-make-ip-address-logging-optional
Make ip address logging optional
2025-02-24 10:42:44 +01:00
Leendert de Borst
d1d6bfb957 Add ip logging info to install docs (#571) 2025-02-24 10:42:24 +01:00
Leendert de Borst
a3b1fc0a21 Add E2E tests for ip logging enable/disable (#571) 2025-02-23 17:24:22 +01:00
Leendert de Borst
38ac1f731a Add IP_LOGGING_ENABLED flag (#571) 2025-02-23 16:51:10 +01:00
Leendert de Borst
c7d0013b9f Merge pull request #584 from lanedirt/579-bug-admin-server-settings-page-margins-are-too-wide
Admin and client UI tweaks
2025-02-23 16:04:46 +01:00
Leendert de Borst
1634721474 Update create new identity widget positioning (#579) 2025-02-22 10:08:16 +01:00
Leendert de Borst
f227725778 Do not show trailing dots for short email subjects (#579) 2025-02-22 09:54:25 +01:00
Leendert de Borst
912bdfbe7d Fix margin on credential delete page (#579) 2025-02-22 09:34:15 +01:00
Leendert de Borst
c82e9a9517 Fix margin on admin server settings page (#579) 2025-02-22 09:29:55 +01:00
Leendert de Borst
d765978e63 Add account delete E2E test (#373) 2025-02-21 21:11:47 +01:00
Leendert de Borst
3d819dce2a Add account self-delete option to client (#373) 2025-02-21 21:11:47 +01:00
dependabot[bot]
23bbc7eedb Bump vitest
Bumps the npm_and_yarn group with 1 update in the /browser-extensions/chrome directory: [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `vitest` from 3.0.4 to 3.0.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v3.0.5/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 21:11:19 +01:00
Leendert de Borst
26b9d07e7c Update browser-extension-tests.yml for branch names (#541) 2025-02-21 20:55:06 +01:00
Leendert de Borst
89a24ead1a Update browser-extension-tests.yml for main branch (#541) 2025-02-21 18:10:50 +01:00
dependabot[bot]
10e2787b4f Bump nokogiri in /docs in the bundler group across 1 directory
Bumps the bundler group with 1 update in the /docs directory: [nokogiri](https://github.com/sparklemotion/nokogiri).


Updates `nokogiri` from 1.16.7 to 1.18.3
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/v1.18.3/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.16.7...v1.18.3)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
  dependency-group: bundler
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:06:12 +01:00
dependabot[bot]
d93a6c603d Bump Microsoft.Extensions.Http from 9.0.0 to 9.0.2
Bumps [Microsoft.Extensions.Http](https://github.com/dotnet/runtime) from 9.0.0 to 9.0.2.
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v9.0.0...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.Extensions.Http
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:06:06 +01:00
dependabot[bot]
7bc1ccdb7b Bump Microsoft.AspNetCore.Identity.EntityFrameworkCore and Microsoft.EntityFrameworkCore
Bumps [Microsoft.AspNetCore.Identity.EntityFrameworkCore](https://github.com/dotnet/aspnetcore) and [Microsoft.EntityFrameworkCore](https://github.com/dotnet/efcore). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Identity.EntityFrameworkCore` from 9.0.0 to 9.0.2
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.2)

Updates `Microsoft.EntityFrameworkCore` from 9.0.0 to 9.0.2
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.0...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Identity.EntityFrameworkCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.EntityFrameworkCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:05:55 +01:00
dependabot[bot]
f30b3895ba Bump Microsoft.AspNetCore.Authentication.JwtBearer, Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Tokens
Bumps [Microsoft.AspNetCore.Authentication.JwtBearer](https://github.com/dotnet/aspnetcore), [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) and [Microsoft.IdentityModel.Tokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Authentication.JwtBearer` from 9.0.1 to 9.0.2
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.2)

Updates `Microsoft.IdentityModel.JsonWebTokens` from 8.3.1 to 8.0.1
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.3.1...8.0.1)

Updates `Microsoft.IdentityModel.Tokens` from 8.3.1 to 8.0.1
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.3.1...8.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authentication.JwtBearer
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: Microsoft.IdentityModel.Tokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:05:49 +01:00
dependabot[bot]
ef8c61c6c9 Bump Microsoft.AspNetCore.Components.WebAssembly.Server
Bumps [Microsoft.AspNetCore.Components.WebAssembly.Server](https://github.com/dotnet/aspnetcore) from 9.0.0 to 9.0.2.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.2)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Components.WebAssembly.Server
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:05:37 +01:00
dependabot[bot]
7c65247162 Bump MimeKit from 4.9.0 to 4.10.0
Bumps [MimeKit](https://github.com/jstedfast/MimeKit) from 4.9.0 to 4.10.0.
- [Changelog](https://github.com/jstedfast/MimeKit/blob/master/ReleaseNotes.md)
- [Commits](https://github.com/jstedfast/MimeKit/compare/4.9.0...4.10.0)

---
updated-dependencies:
- dependency-name: MimeKit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:05:31 +01:00
dependabot[bot]
af166c27fd Bump Microsoft.AspNetCore.Authorization and Microsoft.AspNetCore.Components.WebAssembly
Bumps [Microsoft.AspNetCore.Authorization](https://github.com/dotnet/aspnetcore) and [Microsoft.AspNetCore.Components.WebAssembly](https://github.com/dotnet/aspnetcore). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Authorization` from 9.0.1 to 9.0.1
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.1)

Updates `Microsoft.AspNetCore.Components.WebAssembly` from 9.0.0 to 9.0.1
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authorization
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.AspNetCore.Components.WebAssembly
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:05:24 +01:00
dependabot[bot]
90b1d0ae09 Bump Microsoft.EntityFrameworkCore.Tools from 9.0.0 to 9.0.1
Bumps [Microsoft.EntityFrameworkCore.Tools](https://github.com/dotnet/efcore) from 9.0.0 to 9.0.1.
- [Release notes](https://github.com/dotnet/efcore/releases)
- [Commits](https://github.com/dotnet/efcore/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.EntityFrameworkCore.Tools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:05:15 +01:00
dependabot[bot]
b4c84d9894 Bump Microsoft.AspNetCore.Authorization and Microsoft.AspNetCore.Components.Web
Bumps [Microsoft.AspNetCore.Authorization](https://github.com/dotnet/aspnetcore) and [Microsoft.AspNetCore.Components.Web](https://github.com/dotnet/aspnetcore). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Authorization` from 9.0.1 to 9.0.1
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.1...v9.0.1)

Updates `Microsoft.AspNetCore.Components.Web` from 9.0.0 to 9.0.1
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authorization
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.AspNetCore.Components.Web
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:05:09 +01:00
dependabot[bot]
bce4327f2d Bump coverlet.msbuild from 6.0.3 to 6.0.4
Bumps [coverlet.msbuild](https://github.com/coverlet-coverage/coverlet) from 6.0.3 to 6.0.4.
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/compare/v6.0.3...v6.0.4)

---
updated-dependencies:
- dependency-name: coverlet.msbuild
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:05:01 +01:00
dependabot[bot]
1fe967624f Bump MailKit from 4.9.0 to 4.10.0
Bumps [MailKit](https://github.com/jstedfast/MailKit) from 4.9.0 to 4.10.0.
- [Changelog](https://github.com/jstedfast/MailKit/blob/master/ReleaseNotes.md)
- [Commits](https://github.com/jstedfast/MailKit/compare/4.9.0...4.10.0)

---
updated-dependencies:
- dependency-name: MailKit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-21 18:04:51 +01:00
Leendert de Borst
1ee02a3d22 Merge pull request #568 from lanedirt/541-add-browser-extensions-with-auto-fill-mechanism
Add Chrome browser extension
2025-02-21 18:04:09 +01:00
Leendert de Borst
ac7b6facd6 Fix bug in base64 encode which didnt work for large icons (#541) 2025-02-21 17:21:47 +01:00
Leendert de Borst
58e294b509 Fix duplicate credential popup issue (#541) 2025-02-21 17:04:39 +01:00
Leendert de Borst
e8314f91dc Update credentials list to properly refresh with new vault (#541) 2025-02-21 16:31:30 +01:00
Leendert de Borst
977acf84c5 Email UI tweaks (#541) 2025-02-21 15:34:08 +01:00
Leendert de Borst
aa9619efad Performance tweaks (#541) 2025-02-21 14:21:09 +01:00
Leendert de Borst
e6ccea1c59 Update README.md (#541) 2025-02-21 13:16:47 +01:00
Leendert de Borst
f691056db6 Update login screen (#541) 2025-02-21 13:07:20 +01:00
Leendert de Borst
08d7013f75 Add browser extension assets to GH release (#541) 2025-02-21 12:54:57 +01:00
Leendert de Borst
067a949c49 Refactor vaultstate to chrome.storage.session (#541) 2025-02-21 12:47:52 +01:00
Leendert de Borst
38ee886be2 Show target API endpoint on login form (#541) 2025-02-21 12:18:16 +01:00
Leendert de Borst
9ae5e994bd Add browser extension docs (#541) 2025-02-21 11:22:20 +01:00
Leendert de Borst
42573bf1fc Fix redirect when opening extension popup externally (#541) 2025-02-20 23:57:23 +01:00
Leendert de Borst
59e99153c3 Update create new release docs (#541) 2025-02-20 23:17:03 +01:00
Leendert de Borst
d2c24792fe Simplify form detector password confirm (#541) 2025-02-20 23:16:49 +01:00
Leendert de Borst
d674563275 Update docs (#541) 2025-02-20 22:13:54 +01:00
Leendert de Borst
e153dc6d2a Refactor (#541) 2025-02-20 17:23:18 +01:00
Leendert de Borst
fdbf3db6bb Refactor formdetector to separate localization params (#541) 2025-02-20 16:58:46 +01:00
Leendert de Borst
a6529d67fa Refactoring (#541) 2025-02-20 16:05:08 +01:00
Leendert de Borst
45f748e247 Add server version check (#541) 2025-02-20 15:22:30 +01:00
Leendert de Borst
57673b5ee0 Update auth login flow (#541) 2025-02-20 13:54:49 +01:00
Leendert de Borst
8ea0273174 Improve credentials list mount logic (#541) 2025-02-20 11:38:35 +01:00
Leendert de Borst
a31c516fa5 Accessibility refactor (#541) 2025-02-20 11:04:28 +01:00
Leendert de Borst
bb9e986874 Add explicit autofill trigger to context menu (#541) 2025-02-19 13:54:30 +01:00
Leendert de Borst
533065c7d3 Add popup show debounce to prevent autofill from spamming popup (#541) 2025-02-19 13:31:38 +01:00
Leendert de Borst
16a22b6fa3 Update .gitignore (#541) 2025-02-19 12:56:20 +01:00
Leendert de Borst
4d42e7b32e Update form detection logic, update tests (#541) 2025-02-19 12:56:11 +01:00
Leendert de Borst
b50205b318 Fix link in docs (#541) 2025-02-19 00:34:22 +01:00
Leendert de Borst
196e19573d Sonarcloud refactoring (#541) 2025-02-19 00:30:05 +01:00
Leendert de Borst
9de7f81053 Refactor math.random (#541) 2025-02-18 21:46:19 +01:00
Leendert de Borst
75cf43aaba Fix extension E2E test (#541) 2025-02-18 21:28:20 +01:00
Leendert de Borst
1d76597ee2 Update light mode style (#541) 2025-02-18 21:28:08 +01:00
Leendert de Borst
887e91f4c6 Refactor (#541) 2025-02-18 12:52:15 +01:00
Leendert de Borst
c4afb9eeb2 Update Settings.tsx (#541) 2025-02-18 11:58:09 +01:00
Leendert de Borst
9151e504bc Fix EmailDetails global loading state hide (#541) 2025-02-17 15:11:08 +01:00
Leendert de Borst
b20d330fdc Add global popup toggle to settings (#541) 2025-02-17 15:06:09 +01:00
Leendert de Borst
9c5f5fa5cd Improve popup visibility (#541) 2025-02-17 14:28:59 +01:00
Leendert de Borst
de85430998 Make extension work with iframes (#541) 2025-02-17 13:41:16 +01:00
Leendert de Borst
6df6bb071a Add search bar to credentials list (#541) 2025-02-17 12:39:12 +01:00
Leendert de Borst
1263639ca2 Update contentscript and inject icon logic (#541) 2025-02-17 11:25:14 +01:00
Leendert de Borst
ad52ec5db1 Improve favicon extraction (#541) 2025-02-16 14:26:13 +01:00
Leendert de Borst
665abcd894 Update popup style (#541) 2025-02-15 20:43:11 +01:00
Leendert de Borst
8b5cd28e4d Fix api date test to ignore rounding issue (#541) 2025-02-15 09:43:42 +01:00
Leendert de Borst
45a5d7fb20 Fix CSS style conflicts (#541) 2025-02-15 09:39:15 +01:00
Leendert de Borst
7fefe9f0bb Improve username field detection (#541) 2025-02-14 23:53:53 +01:00
Leendert de Borst
3fe5fbd981 Update formdetector for name fields (#541) 2025-02-14 22:41:19 +01:00
Leendert de Borst
c13e0571ab Fix date select field detection and fill (#541) 2025-02-14 22:16:37 +01:00
Leendert de Borst
fbf7f5b4e4 Update password field extraction (#541) 2025-02-14 21:31:31 +01:00
Leendert de Borst
8c132f30fb Improve email detection (#541) 2025-02-14 17:00:21 +01:00
Leendert de Borst
7def472df5 Improve form detection for gender fields (#541) 2025-02-14 16:36:11 +01:00
Leendert de Borst
0069b8cfc6 Add date field recognition with slashes (#541) 2025-02-14 16:10:45 +01:00
Leendert de Borst
53246a3d99 Update popup styling to be more explicit (#541) 2025-02-14 15:45:00 +01:00
Leendert de Borst
11a33d5ea7 Refactor formdetector to focus on focused elements parent form (#541) 2025-02-14 15:04:14 +01:00
Leendert de Borst
f5fb69e756 Do not include querystring when copying url for new credential (#541) 2025-02-14 14:29:35 +01:00
Leendert de Borst
519bd0801d Update SearchWidget.razor (#541) 2025-02-14 14:13:37 +01:00
Leendert de Borst
cba4a6d3ec Add email attachment download (#541) 2025-02-14 14:06:29 +01:00
Leendert de Borst
5daa95a876 Reduce size of popup (#541) 2025-02-14 11:44:17 +01:00
Leendert de Borst
b81613b785 Fix popup links (#541) 2025-02-13 17:11:51 +01:00
Leendert de Borst
2013f48ddd Improve logout reset (#541) 2025-02-13 16:27:19 +01:00
Leendert de Borst
867b37ab79 Improve icon inject (#541) 2025-02-13 16:16:46 +01:00
Leendert de Borst
390c77448e Return all credentials on search (#541) 2025-02-13 15:07:48 +01:00
Leendert de Borst
7f23c4820c Update popup style (#541) 2025-02-13 14:56:54 +01:00
Leendert de Borst
d6c3bd5cc1 Update autofill popup UI (#541) 2025-02-13 13:49:43 +01:00
Leendert de Borst
ccdb62762e Fix date handling timezone bug with PostgreSQL (#541) 2025-02-13 13:02:42 +01:00
Leendert de Borst
e5552e80e6 Tweak loading states (#541) 2025-02-13 12:09:36 +01:00
Leendert de Borst
47201b5433 Add status call to unlock page, fix redirect bug (#541) 2025-02-12 11:27:03 +01:00
Leendert de Borst
0862aa64cb Add vault status check before generating new credential (#541) 2025-02-11 17:16:42 +01:00
Leendert de Borst
bd833414ad Improve loading UX (#541) 2025-02-11 15:00:59 +01:00
Leendert de Borst
a3d8242dc4 Add status call to credential list page (#541) 2025-02-11 13:33:33 +01:00
Leendert de Borst
6ea4a9724f Fix redirect issue (#541) 2025-02-11 12:19:21 +01:00
Leendert de Borst
84d3a25304 Add client version check and vault revision number to status endpoint (#541) 2025-02-10 17:17:14 +01:00
Leendert de Borst
a9044e95ca Log client in vault metadata (#541) 2025-02-10 14:22:55 +01:00
Leendert de Borst
9eaf8fb369 Refactor (#541) 2025-02-10 13:01:59 +01:00
Leendert de Borst
c2d035510a Update client name and lint fixes (#541) 2025-02-10 12:35:17 +01:00
Leendert de Borst
117da9dfc8 Fix build issues (#541) 2025-02-10 12:33:24 +01:00
Leendert de Borst
0633bc2943 Add AV and SpamOK client headers (#541) 2025-02-10 11:46:16 +01:00
Leendert de Borst
e153dc6fe7 Add client to auth logs in api and wasm client (#541) 2025-02-10 11:32:39 +01:00
Leendert de Borst
1ed74874e5 Add global state change handler to detect logout (#541) 2025-02-10 10:38:28 +01:00
Leendert de Borst
620aeaf941 Add generic vault validate method (#541) 2025-02-09 22:42:21 +01:00
Leendert de Borst
d298748b10 Add min vault version check (#541) 2025-02-09 19:29:41 +01:00
Leendert de Borst
c46e836c28 Add empty vault check to login (#541) 2025-02-09 19:13:48 +01:00
Leendert de Borst
2bcf0c9914 Update login page (#541) 2025-02-08 18:37:26 +01:00
Leendert de Borst
0e275a3e6f Update settings text (#541) 2025-02-08 15:41:30 +01:00
Leendert de Borst
0d6878e5c7 Tweak bg color (#541) 2025-02-08 15:08:26 +01:00
Leendert de Borst
24d9999fde Linting refactor (#541) 2025-02-07 17:26:26 +01:00
Leendert de Borst
5594c1ad2f Add settings page to control popup enable/disable (#541) 2025-02-07 17:18:12 +01:00
Leendert de Borst
20c44ec737 Keep icon visible after click (#541) 2025-02-07 16:37:47 +01:00
Leendert de Borst
b46637f8a0 Tweak autofill and add animation (#541) 2025-02-07 16:12:38 +01:00
Leendert de Borst
a22dbc59ac Fix inline unlock mode (#541) 2025-02-07 15:24:01 +01:00
Leendert de Borst
06d6693752 Add OOBE text (#541) 2025-02-07 15:08:28 +01:00
Leendert de Borst
c28f6f05b2 Implement 2FA for login flow (#541) 2025-02-07 13:51:34 +01:00
Leendert de Borst
10f9d5e2b1 Refactor email decryption to util method (#541) 2025-02-07 12:57:49 +01:00
Leendert de Borst
f30789f906 Add popout and public email support to credential view (#541) 2025-02-07 12:34:45 +01:00
Leendert de Borst
b66c0580cf Update tests (#541) 2025-02-06 21:51:45 +01:00
Leendert de Borst
5db8c99b74 Update vite.config.js (#541) 2025-02-06 21:44:25 +01:00
Leendert de Borst
92c042450f Add email preview to credential detail page (#541) 2025-02-06 21:40:10 +01:00
Leendert de Borst
4c60a3efa1 Remove paging params from email list (#541) 2025-02-06 20:12:21 +01:00
Leendert de Borst
51af2838d9 Fix contentScript rename capital case folder name (#541) 2025-02-06 19:27:18 +01:00
Leendert de Borst
70cad70766 Add go-edit and go-delete keyboard shortcuts to client (#541) 2025-02-06 19:26:40 +01:00
Leendert de Borst
d78214393a Add database version extraction and update revision number (#541) 2025-02-06 14:44:14 +01:00
Leendert de Borst
e62dcd5327 Add vault version check to webapi to prevent conflicts (#541) 2025-02-06 14:02:31 +01:00
Leendert de Borst
87ec52223a Add settings retrieval from vault (#541) 2025-02-06 13:36:30 +01:00
Leendert de Borst
562abb6641 Remove obsolete vault state params (#541) 2025-02-06 12:39:38 +01:00
Leendert de Borst
f894476e0e Add single credential retrieve query (#541) 2025-02-06 12:15:08 +01:00
Leendert de Borst
826037d499 Refactor db initialize (#541) 2025-02-06 11:57:17 +01:00
Leendert de Borst
b1ef958976 Make index.html be included with npm run watch (#541) 2025-02-06 11:16:16 +01:00
Leendert de Borst
5d03c617c0 Tweak folder structure (#541) 2025-02-06 10:22:02 +01:00
Leendert de Borst
0996375c5e Eslint refactoring (#541) 2025-02-06 09:38:53 +01:00
Leendert de Borst
d927640136 Require jsdoc descriptions to be non-empty (#541) 2025-02-05 17:59:56 +01:00
Leendert de Borst
1d59548df0 Linting fixes (#541) 2025-02-05 17:58:49 +01:00
Leendert de Borst
b8a5233a06 Refactor background.ts to separate files (#541) 2025-02-05 17:22:33 +01:00
Leendert de Borst
908efadcec Refactor code and enforce 2 space indents (#541) 2025-02-05 16:45:21 +01:00
Leendert de Borst
3f5f752a2f Refactor contentscript to individual files (#541) 2025-02-05 16:30:03 +01:00
Leendert de Borst
7fdbe812d3 Refactor contentScript.ts (#541) 2025-02-05 15:46:40 +01:00
Leendert de Borst
df71d7e3f0 Improve icon inject mechanism (#541) 2025-02-05 14:52:27 +01:00
Leendert de Borst
c97b049ed0 Refactor folder structure to prevent having src output dir (#541) 2025-02-05 13:57:49 +01:00
Leendert de Borst
267cd6e9f6 Refactor vite config to fix import conflicts (#541) 2025-02-05 13:44:00 +01:00
Leendert de Borst
ef41018ac1 Add context menu with password generator (#541) 2025-02-05 11:16:53 +01:00
Leendert de Borst
54f891548b Fix search results and UI tweaks (#541) 2025-02-05 10:53:55 +01:00
Leendert de Borst
b92f5a5971 Revert to original search results on removing search term (#541) 2025-02-04 16:34:36 +01:00
Leendert de Borst
8415331eee Show loading animation when creating new alias (#541) 2025-02-04 16:30:33 +01:00
Leendert de Borst
afd686f81b Update credential row UI (#541) 2025-02-04 16:26:30 +01:00
Leendert de Borst
413c300904 Add popout icon for every autofill match (#541) 2025-02-04 15:57:29 +01:00
Leendert de Borst
bc4fb0ad21 Add birthdate format detection (#541) 2025-02-04 15:02:01 +01:00
Leendert de Borst
2193c4d6e3 Attach autofill icon to first element based on dom order (#541) 2025-02-04 14:52:12 +01:00
Leendert de Borst
33fe0b74ae Add email confirm field detect (#541) 2025-02-04 14:38:47 +01:00
Leendert de Borst
738f93b882 Update formdetector to detect more variations (#541) 2025-02-04 14:01:06 +01:00
Leendert de Borst
b875fcad4e Add additional formdetector test (#541) 2025-02-04 13:35:44 +01:00
Leendert de Borst
c56dbba687 Simulate proper input events for birthdate and gender fields (#541) 2025-02-04 10:42:19 +01:00
Leendert de Borst
44783bbeb0 Add birthdate and gender form field detection (#541) 2025-02-04 10:29:22 +01:00
Leendert de Borst
3428291c54 Add second form detector test (#541) 2025-02-04 10:02:30 +01:00
Leendert de Borst
fa221e3ae5 Refactor formdetector and make it testable (#541) 2025-02-04 09:51:58 +01:00
Leendert de Borst
cc23f50edf Add UX improvements (#541) 2025-02-04 09:21:25 +01:00
Leendert de Borst
f811a028cd Show newest credentials on top (#541) 2025-02-03 19:46:45 +01:00
Leendert de Borst
ff0d2cf390 Add vault upload mechanism (#541) 2025-02-03 19:25:38 +01:00
Leendert de Borst
c47aa4e182 Add loading indicator to contentscript (#541) 2025-02-03 17:30:33 +01:00
Leendert de Borst
1d119aad62 Add favicon extraction (#541) 2025-02-03 17:06:40 +01:00
Leendert de Borst
254b9c0a49 Add credential create scaffolding (#541) 2025-02-03 16:15:05 +01:00
Leendert de Borst
e760c236bc Add public/private email domain persist from API (#541) 2025-02-03 15:21:17 +01:00
Leendert de Borst
01f32af6a1 Update client vault model with new optional values (#541)
Save public and private email domains locally in vault (#541)

Update dockerfile for private email domains (#541)

Update tests (#541)

Revert "Update dockerfile for private email domains (#541)"

This reverts commit 016200c4f413502634925183db3a6df421219a8f.

Revert "Save public and private email domains locally in vault (#541)"

This reverts commit 549c3cce83fe7d051f828008917c6b320e9058ab.
2025-02-02 15:44:58 +01:00
Leendert de Borst
66b59ce94b Add private and public email to vault response in API (#541) 2025-02-02 13:51:41 +01:00
Leendert de Borst
69c9a4bdd0 Move identity generator dictionaries to root for reuse (#541) 2025-02-01 19:58:21 +01:00
Leendert de Borst
e5ead966e9 Add dictionary loader vite plugin to inject identity generator dict content (#541) 2025-02-01 13:03:22 +01:00
Leendert de Borst
40b7ecd2fe Refactor tests (#541) 2025-02-01 12:20:16 +01:00
Leendert de Borst
f6c66a9964 Separate build and lint for better insight in status (#541) 2025-02-01 12:10:22 +01:00
Leendert de Borst
698d96780a Add github workflow for testing browser extensions (#541) 2025-02-01 12:07:42 +01:00
Leendert de Borst
b250bc0795 Add identity generator implementations and dicts (#541) 2025-02-01 12:07:14 +01:00
Leendert de Borst
b229740315 Port .NET identity generation to Typescript (#541) 2025-02-01 11:51:34 +01:00
Leendert de Borst
a1ecc49065 Show aliasvault icon inline with form autofill (#541) 2025-02-01 11:09:09 +01:00
Leendert de Borst
bc96d30bf4 Add email details page (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
48b6acb174 Add popout button to credential details page (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
d6651001fc Add all fields to credential detail page (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
4c9376612e Add copy to clipboard for credential details (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
c89f0e6fae Fix client open in new tab URL (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
d3caa2d0a9 Add reload button to credential and email pages (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
c05a47587b Add email to credential details (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
10651d1d0f Refactor WIP to use react router (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
4e7aee0634 Update EmailsList.tsx (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
1065c687bc Implement email decryption (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
0a39857d12 Add email retrieval logic (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
72a3975a58 Add bottom navigation bar (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
06d35aac0f Add contentscript autofill filter (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
ebc671f32f Add open client button and url setting (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
ea7cb5e323 Add inline unlock page mode with confirm message (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
b1ab983333 Open popup from locked vault notice (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
57cbedf701 Add notice when vault is locked (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
6298cff1a3 Make content script use the width of the input field (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
a975c4d2c5 Revoke token on logout (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
7c3f360a34 Close autofill on mouseclick outside (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
2a76fbc5a3 Add vault reload button (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
0f58424c73 Add user and settings menu button (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
aa1df77400 Refactor (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
acd26ee67b Add generic loading spinner context (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
11cacf9c0b Add loading animation when opening popup (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
351548df7c Update todos (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
322b5da793 Add common credentials query (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
d6c1f38ce4 Replace base64encode with buffer (#541) 2025-02-01 11:09:08 +01:00
Leendert de Borst
f8194708a0 Add E2E test in .NET that tests the chrome extension (#541)
Remove github action as headless = true is not supported for chrome extensions (#541)

Remove default watch from vite.config.js (#541)

Add GitHub action for extension tests (#541)
2025-02-01 11:09:08 +01:00
Leendert de Borst
c1ec6cb95d Update WebApiService.ts (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
59627ebe32 Remove console.log (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
e5641108ea Add more eslint checks and refactoring (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
636e996a17 Fix all eslint issues (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
bfbde5cdf4 Add eslint (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
c9aa79abaf Refactor (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
cd8ad64a6d Fix update refresh token (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
00e37c2b25 Only show settings when logged out (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
3263a77f97 Rename popup to index (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
67bb96e245 Refactor project structure (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
eeff14597e Move credential list to separate component (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
86a65d7344 Add settings page to configure API (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
4f48005a49 Add WebApiService to handle generic access and refresh token logic (#541) 2025-02-01 11:08:58 +01:00
Leendert de Borst
f6d7ce4356 Fix image loading in contentscript, fix password fill (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
4c5517ae94 Add contentscript for autofill popup (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
51fb01aaf9 Add chrome background service worker and vault persist (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
7ea60a1fa6 Add vault unlock flow and credential print (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
31409d6e5b Add global auth context (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
483792ebb0 Add sqlite client (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
699b09c6c0 Add crypto methods (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
6bd2ec4a44 Refactor structure (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
6c0a0b463f Make full flow work when running in Chrome extension context (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
4e869bf2b0 Make argon2id and srp flow work in browser dev (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
3abc245751 Refactor (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
b156f72783 Fix Argon2id key derivation (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
6e8ff0104f Add basic argon2id flow (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
f2f8fbbfb6 Add argon2id and SRP modules (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
33d0b24260 Add sample button component (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
cb66bcd665 Add tailwind boilerplate (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
5a1db38eed Add react and vite boilerplate (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
0a565c67dd Add boilerplate chrome extension hello world (#541) 2025-02-01 11:08:57 +01:00
Leendert de Borst
b047ce3019 Bump upload-artifact to v4 (#569) 2025-01-31 17:32:35 +01:00
Leendert de Borst
acfed81e10 Update roadmap 2025-01-24 11:12:47 +01:00
Leendert de Borst
581d1dac5a Merge pull request #558 from lanedirt/557-prepare-0111-release
Bump version to 0.11.1
2025-01-22 12:18:20 +01:00
Leendert de Borst
50b3872ae0 Bump version to 0.11.1 (#557) 2025-01-22 12:17:29 +01:00
Leendert de Borst
2ea2526858 Merge pull request #554 from lanedirt/553-bug-menu-dropdown-does-not-align-correctly-on-very-wide-screens
Update mobile menu position in client and admin
2025-01-22 12:13:28 +01:00
Leendert de Borst
2d9b6f38b0 Merge pull request #556 from lanedirt/555-use-relative-url-to-access-api-instead-of-requiring-hostname-in-env
Simplify installation by using relative url for API instead of requiring hostname in env file
2025-01-22 12:13:11 +01:00
Leendert de Borst
a941ffa837 Update install.sh (#555) 2025-01-22 12:06:15 +01:00
Leendert de Borst
e2da05ac2c Update manual setup docs (#555) 2025-01-22 11:26:03 +01:00
Leendert de Borst
dd8108c974 Update install to only require hostname for SSL configuration (#555) 2025-01-22 11:19:09 +01:00
Leendert de Borst
206f8fc2b1 Remove explicit API URL for Docker environments (#555) 2025-01-22 11:01:54 +01:00
Leendert de Borst
5a432e4ab5 Update client to make API URL optional (#555) 2025-01-22 11:01:27 +01:00
Leendert de Borst
83ba9222bd Update mobile menu position in client and admin (#553) 2025-01-21 11:09:53 +01:00
Leendert de Borst
7e7a8b04ef Update README.md 2025-01-20 18:30:23 +01:00
dependabot[bot]
a28b5012d6 Bump Microsoft.AspNetCore.Components.WebAssembly.DevServer
Bumps [Microsoft.AspNetCore.Components.WebAssembly.DevServer](https://github.com/dotnet/aspnetcore) from 9.0.0 to 9.0.1.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Components.WebAssembly.DevServer
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 12:14:17 +01:00
dependabot[bot]
85218a8fd1 Bump Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Tokens
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) and [Microsoft.IdentityModel.Tokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet). These dependencies needed to be updated together.

Updates `Microsoft.IdentityModel.JsonWebTokens` from 8.3.0 to 8.3.1
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/8.3.1/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.3.0...8.3.1)

Updates `Microsoft.IdentityModel.Tokens` from 8.3.0 to 8.3.1
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/8.3.1/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.3.0...8.3.1)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.IdentityModel.Tokens
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 12:14:09 +01:00
dependabot[bot]
590454b69e Bump Microsoft.AspNetCore.Mvc.Testing from 9.0.0 to 9.0.1
Bumps [Microsoft.AspNetCore.Mvc.Testing](https://github.com/dotnet/aspnetcore) from 9.0.0 to 9.0.1.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Mvc.Testing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 11:49:43 +01:00
dependabot[bot]
d81d48ee16 Bump Microsoft.Extensions.Configuration and Microsoft.Extensions.Configuration.FileExtensions
Bumps [Microsoft.Extensions.Configuration](https://github.com/dotnet/runtime) and [Microsoft.Extensions.Configuration.FileExtensions](https://github.com/dotnet/runtime). These dependencies needed to be updated together.

Updates `Microsoft.Extensions.Configuration` from 9.0.0 to 9.0.1
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v9.0.0...v9.0.1)

Updates `Microsoft.Extensions.Configuration.FileExtensions` from 9.0.0 to 9.0.1
- [Release notes](https://github.com/dotnet/runtime/releases)
- [Commits](https://github.com/dotnet/runtime/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.Extensions.Configuration
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.Extensions.Configuration.FileExtensions
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 11:40:02 +01:00
dependabot[bot]
b72217eb04 Bump coverlet.collector from 6.0.3 to 6.0.4
Bumps [coverlet.collector](https://github.com/coverlet-coverage/coverlet) from 6.0.3 to 6.0.4.
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/compare/v6.0.3...v6.0.4)

---
updated-dependencies:
- dependency-name: coverlet.collector
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 11:39:53 +01:00
dependabot[bot]
8942795e76 Bump Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Bumps [Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore](https://github.com/dotnet/aspnetcore) from 9.0.0 to 9.0.1.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 11:39:46 +01:00
dependabot[bot]
08290e1fa5 Bump Microsoft.AspNetCore.Authorization and Microsoft.AspNetCore.Components.WebAssembly.Authentication
Bumps [Microsoft.AspNetCore.Authorization](https://github.com/dotnet/aspnetcore) and [Microsoft.AspNetCore.Components.WebAssembly.Authentication](https://github.com/dotnet/aspnetcore). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Authorization` from 9.0.0 to 9.0.1
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

Updates `Microsoft.AspNetCore.Components.WebAssembly.Authentication` from 9.0.0 to 9.0.1
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authorization
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.AspNetCore.Components.WebAssembly.Authentication
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 11:39:38 +01:00
dependabot[bot]
7b45b44735 Bump Microsoft.AspNetCore.DataProtection from 9.0.0 to 9.0.1
Bumps [Microsoft.AspNetCore.DataProtection](https://github.com/dotnet/aspnetcore) from 9.0.0 to 9.0.1.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.DataProtection
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 11:39:30 +01:00
dependabot[bot]
ae6913a8e0 Bump Microsoft.AspNetCore.Authentication.JwtBearer, Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Tokens
Bumps [Microsoft.AspNetCore.Authentication.JwtBearer](https://github.com/dotnet/aspnetcore), [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) and [Microsoft.IdentityModel.Tokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet). These dependencies needed to be updated together.

Updates `Microsoft.AspNetCore.Authentication.JwtBearer` from 9.0.0 to 9.0.1
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v9.0.0...v9.0.1)

Updates `Microsoft.IdentityModel.JsonWebTokens` from 8.3.0 to 8.0.1
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.3.0...8.0.1)

Updates `Microsoft.IdentityModel.Tokens` from 8.3.0 to 8.0.1
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.3.0...8.0.1)

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authentication.JwtBearer
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: Microsoft.IdentityModel.Tokens
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 11:39:24 +01:00
Leendert de Borst
7470ac9e16 Update README.md tech stack 2025-01-16 13:45:54 +01:00
Leendert de Borst
521d10da19 Update roadmap 2025-01-15 18:40:15 +01:00
Leendert de Borst
98aee7bb35 Delete .github/ISSUE_TEMPLATE/security_issue.md 2025-01-15 18:28:53 +01:00
Leendert de Borst
d62f2c4450 Merge pull request #540 from lanedirt/539-add-github-issue-templates
Add GitHub issue templates
2025-01-15 17:27:50 +00:00
Leendert de Borst
95edcc3042 Add GitHub issue templates (#539) 2025-01-15 18:27:14 +01:00
Leendert de Borst
1bce686121 Create CODE_OF_CONDUCT.md 2025-01-15 18:19:18 +01:00
Leendert de Borst
742417d405 Update README.md 2025-01-15 18:00:22 +01:00
Leendert de Borst
2cfc8d528d Merge pull request #538 from lanedirt/537-prepare-0110-release
Bump version to 0.11.0
2025-01-14 13:51:15 +00:00
Leendert de Borst
7a4e1721c8 Bump version to 0.11.0 (#537) 2025-01-14 14:42:56 +01:00
Leendert de Borst
11d79c4874 Merge pull request #536 from lanedirt/535-make-application-warning-logs-more-readable
Make duplicate email warning log more readable
2025-01-14 13:32:16 +00:00
Leendert de Borst
7cd35b0a92 Make duplicate email warning log more readable (#535) 2025-01-14 12:30:36 +01:00
Leendert de Borst
d0f62a26c0 Merge pull request #534 from lanedirt/530-update-sonarcloud-github-action-to-work-with-pr-from-forks
Update sonarcloud-code-analysis so it works for main and PRs (#530)
2025-01-14 11:20:41 +00:00
Leendert de Borst
01198502a3 Update sonarcloud-code-analysis so it works for main and PRs (#530) 2025-01-14 12:20:14 +01:00
Leendert de Borst
229ad109a7 Merge pull request #533 from lanedirt/530-update-sonarcloud-github-action-to-work-with-pr-from-forks
Add pullrequest key to sonarcloud analysis
2025-01-14 10:49:48 +00:00
Leendert de Borst
837b16d971 Add pullrequest key to sonarcloud analysis (#530) 2025-01-14 11:49:04 +01:00
Leendert de Borst
4010d1b93f Merge pull request #531 from lanedirt/530-update-sonarcloud-github-action-to-work-with-pr-from-forks
Update sonarcloud-code-analysis.yml to work with PR's from forks
2025-01-14 10:28:48 +00:00
Leendert de Borst
f7ce60ae68 Update sonarcloud-code-analysis.yml to work with PR's from forks (#530) 2025-01-14 11:26:37 +01:00
Leendert de Borst
5e61bd5db2 Merge pull request #527 from lanedirt/525-prevent-email-address-collision-from-occuring
Prevent email address collision from occurring during identity generation
2025-01-13 14:09:54 +00:00
dependabot[bot]
a2e8a438de Bump NUnit.Analyzers from 4.5.0 to 4.6.0
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.md)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/4.5.0...4.6.0)

---
updated-dependencies:
- dependency-name: NUnit.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-13 14:09:38 +00:00
Leendert de Borst
92904dcf55 Refactor email prefix exists check (#525) 2025-01-12 15:29:15 +00:00
Leendert de Borst
e4f2ca630b Add server side email prefix generation method (#525) 2025-01-12 14:01:48 +00:00
Leendert de Borst
ed80ad24c1 Add more names to identity generator dictionary to prevent collisions (#525) 2025-01-12 13:02:22 +00:00
Leendert de Borst
0c368ab84b Merge pull request #524 from lanedirt/151-make-email-attachments-visible-in-ui-and-allow-for-downloading-attachments-through-client
Add email attachment support
2025-01-11 16:15:49 +00:00
Leendert de Borst
dee2044ed6 Refactor (#151) 2025-01-11 16:05:32 +00:00
dependabot[bot]
f6f6072b3f Bump coverlet.msbuild from 6.0.2 to 6.0.3
Bumps [coverlet.msbuild](https://github.com/coverlet-coverage/coverlet) from 6.0.2 to 6.0.3.
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/compare/v6.0.2...v6.0.3)

---
updated-dependencies:
- dependency-name: coverlet.msbuild
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-11 15:57:26 +00:00
dependabot[bot]
4bfe72d750 Bump coverlet.collector from 6.0.2 to 6.0.3
Bumps [coverlet.collector](https://github.com/coverlet-coverage/coverlet) from 6.0.2 to 6.0.3.
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/compare/v6.0.2...v6.0.3)

---
updated-dependencies:
- dependency-name: coverlet.collector
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-11 15:56:56 +00:00
Leendert de Borst
330f59dc10 Add email decryption test with and without attachments (#151) 2025-01-11 15:45:54 +00:00
Leendert de Borst
a20d981427 Add full attachment download flow to email decryption test (#151) 2025-01-11 13:10:26 +00:00
Leendert de Borst
bd2274db75 Add support for download attachments from SpamOK (#151) 2025-01-11 12:58:40 +00:00
Leendert de Borst
6cfa6f4ef5 Add email attachment retrieval and decryption to client (#151) 2025-01-11 12:49:35 +00:00
Leendert de Borst
8a40d2b1b9 Add attachment encryption assert to test (#151) 2025-01-10 21:35:22 +00:00
Leendert de Borst
237958ba0f Show attachment metadata in email modal popup (#151) 2025-01-10 19:13:18 +00:00
Leendert de Borst
79db3a54c7 Tweak client z-index to show emailmodal on top (#151) 2025-01-10 19:12:45 +00:00
Leendert de Borst
2029745f8b Fix tablet view for credential view page width (#151) 2025-01-10 18:54:51 +00:00
Leendert de Borst
ea4d498502 Update sendEmailCLI.sh to support sending attachments (#151) 2025-01-10 15:05:17 +00:00
Leendert de Borst
05838f5dca Add attachment indicator E2E test on email page (#151) 2025-01-10 14:55:45 +00:00
Leendert de Borst
79872163e2 Add attachment indicator to email page (#151) 2025-01-10 14:55:27 +00:00
Leendert de Borst
35d0f77dd6 Add HasAttachments to mailbox api model (#151) 2025-01-10 14:29:17 +00:00
Leendert de Borst
6660cd20bd Update docker-compose-pull.yml (#522) 2025-01-08 14:28:34 +00:00
Ikko Eltociear Ashimine
e236ba454f chore: update UserEmailClaim.cs (#521)
adress -> address
2025-01-08 14:13:14 +00:00
Leendert de Borst
6ec66e4d64 Merge pull request #517 from lanedirt/516-optimize-local-build-for-arm-devices
Add support for arm64 to docker images and install.sh local build
2025-01-04 09:37:00 +01:00
Leendert de Borst
14898c0c83 Refactor Dockerfile for readability (#516) 2025-01-04 09:24:05 +01:00
Leendert de Borst
d08bec9df7 Bump version to 0.10.3 (#516) 2025-01-04 01:31:07 +01:00
Leendert de Borst
9107dfa789 Update Docker images to also build for linux/arm64 (#516) 2025-01-04 01:04:57 +01:00
Leendert de Borst
351f6f4d16 Update install.sh (#516) 2025-01-03 23:55:51 +01:00
Leendert de Borst
aca607e579 Merge pull request #515 from lanedirt/514-prepare-0102-release
Bump version to 0.10.2
2025-01-03 22:30:47 +01:00
Leendert de Borst
ed053422ba Update StatusHostedService.cs (#512) 2025-01-03 22:15:27 +01:00
Leendert de Borst
955b8638ce Bump version (#514) 2025-01-03 21:50:14 +01:00
Leendert de Borst
1d8883cc94 Merge pull request #513 from lanedirt/512-task-runner-cleanup-jobs-do-not-run
Maintenance tasks do not run after migration to PostgreSQL
2025-01-03 21:45:04 +01:00
Leendert de Borst
48281f92e6 Refactor to reduce complexity (#512) 2025-01-03 21:29:42 +01:00
Leendert de Borst
f19db2c010 Refactor StatusWorker to prevent race conditions and improve stability (#512) 2025-01-03 20:38:13 +01:00
Leendert de Borst
f0d397c8af Add cancellation token check to worker start and stop wait (#512) 2025-01-03 16:18:37 +01:00
Leendert de Borst
fafa51d787 Update integration tests (#512) 2025-01-03 16:08:09 +01:00
Leendert de Borst
202151e4f1 Update SmtpServer TestHostBuilder to be compatible with integration and E2E tests (#512) 2025-01-03 15:36:09 +01:00
Leendert de Borst
c123edccd4 Refactor integration test TestHostBuilder setup to shared abstract class (#512) 2025-01-03 15:22:47 +01:00
Leendert de Borst
50cab3a2f3 Show full error when maintenance task fails to start (#512) 2025-01-03 12:44:55 +01:00
Leendert de Borst
0184e32e6d Update migration to reset task runner job sequence (#512) 2025-01-03 12:44:40 +01:00
Leendert de Borst
d73d4e90e0 Make admin password for dev always override existing password (#512) 2025-01-03 11:58:33 +01:00
Leendert de Borst
06d38842f5 Add dev database import/export support (#512) 2025-01-03 11:56:55 +01:00
Leendert de Borst
b0748316ff Merge pull request #511 from lanedirt/510-admin-password-hash-method-in-installcli-does-not-pass-required-arguments
Admin password hash method in installcli does not pass required arguments
2025-01-01 16:18:36 +01:00
Leendert de Borst
8f8b4af3c9 Update install.sh (#510) 2025-01-01 16:18:15 +01:00
Leendert de Borst
11bf183cbb Update install.sh (#510) 2025-01-01 16:17:41 +01:00
Leendert de Borst
ac64dba715 Merge pull request #509 from lanedirt/508-prepare-0100-release
Prepare 0.10.0 release
2025-01-01 15:43:28 +01:00
Leendert de Borst
d2f9b225d0 Start services again after db migration (#508) 2025-01-01 15:01:13 +01:00
Leendert de Borst
d7f1df3252 Update AppInfo bump version (#508) 2025-01-01 14:56:28 +01:00
Leendert de Borst
fdce8bddd1 Bump install.sh version (#508) 2025-01-01 14:56:15 +01:00
Leendert de Borst
be4a105709 Update docs (#508) 2025-01-01 14:56:02 +01:00
Leendert de Borst
dfa2f84570 Merge pull request #507 from lanedirt/506-add-postgresql-database-import-and-export-commands-to-installsh
Add postgresql database import and export commands to install.sh
2024-12-31 21:40:49 +01:00
Leendert de Borst
450ca6a6f4 Update db-import command (#506) 2024-12-31 21:34:23 +01:00
Leendert de Borst
4c31912d73 Add db import and export commands to install.sh (#506) 2024-12-31 21:18:44 +01:00
dependabot[bot]
367be5a409 Bump NUnit from 4.3.1 to 4.3.2
Bumps [NUnit](https://github.com/nunit/nunit) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/4.3.1...4.3.2)

---
updated-dependencies:
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-31 17:57:22 +01:00
dependabot[bot]
b6cf46ab91 Bump HtmlAgilityPack from 1.11.71 to 1.11.72
Bumps [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) from 1.11.71 to 1.11.72.
- [Release notes](https://github.com/zzzprojects/html-agility-pack/releases)
- [Commits](https://github.com/zzzprojects/html-agility-pack/compare/v1.11.71...v1.11.72)

---
updated-dependencies:
- dependency-name: HtmlAgilityPack
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-31 17:57:14 +01:00
Leendert de Borst
0da0bd0b17 Merge pull request #505 from lanedirt/503-searching-in-admin-table-pages-defocuses-search-field-after-every-character-typed
Do not show loading indicator when refreshing in admin
2024-12-31 17:56:01 +01:00
Leendert de Borst
d8ccaad806 Merge pull request #504 from lanedirt/493-fix-dataprotection-api-errors-when-running-a-clean-docker-install
Do not log dataprotection warnings to database log
2024-12-31 17:50:07 +01:00
Leendert de Borst
656210e4f6 Do not show loading indicator when refreshing in admin (#503) 2024-12-31 17:48:29 +01:00
Leendert de Borst
c3c85bc10e Do not log dataprotection warnings to database log but keep for filelog (#493) 2024-12-31 17:37:17 +01:00
Leendert de Borst
693ad0b581 Update CONTRIBUTING.md 2024-12-31 15:29:32 +01:00
Leendert de Borst
94ad51059e Merge pull request #500 from lanedirt/491-link-from-contributindmd-to-the-official-docs-page
Update contributing documentation
2024-12-30 11:51:12 +01:00
Leendert de Borst
9374780a5b Update CONTRIBUTING.md (#491) 2024-12-29 12:30:34 +01:00
Leendert de Borst
3263360be5 Merge pull request #492 from lanedirt/190-add-postgresql-as-database-option-to-prevent-concurrency-locking-due-to-sqlite-limitations
Switch SQLite to PostgreSQL database engine
2024-12-29 12:15:32 +01:00
Leendert de Borst
1151089d59 Fix merge conflict (#190) 2024-12-28 17:06:50 +01:00
Leendert de Borst
d39ecf69e8 Merge pull request #499 from lanedirt/498-make-user-refreshtoken-lifetime-configurable-via-server-settings
Make UserRefreshToken lifetime configurable via admin
2024-12-28 16:58:29 +01:00
Leendert de Borst
9caea03460 Update AuthTests.cs (#498) 2024-12-28 16:45:06 +01:00
Leendert de Borst
32879e09a8 Make UserRefreshToken lifetime configurable via admin (#498) 2024-12-28 16:35:21 +01:00
Leendert de Borst
d3518eca6c Update install.sh add install.sh version check to install command itself (#190) 2024-12-28 15:52:33 +01:00
Leendert de Borst
329ae185ad Update docs (#190) 2024-12-28 14:28:09 +01:00
dependabot[bot]
888054e8ed Bump NUnit.Analyzers from 4.4.0 to 4.5.0
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.md)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/4.4.0...4.5.0)

---
updated-dependencies:
- dependency-name: NUnit.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-27 17:46:07 +01:00
dependabot[bot]
0d141e2c7c Bump NUnit from 4.3.0 to 4.3.1
Bumps [NUnit](https://github.com/nunit/nunit) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/4.3.0...4.3.1)

---
updated-dependencies:
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-27 17:29:08 +01:00
Leendert de Borst
33b930b58a Merge pull request #497 from lanedirt/495-improve-2fa-login-flow-to-automatically-submit-when-6-digits-have-been-entered
Auto submit login form when 2fa code is entered
2024-12-27 17:26:39 +01:00
Leendert de Borst
ad9eb79e9e Update CodeLockoutTests.cs (#495) 2024-12-27 16:56:20 +01:00
Leendert de Borst
cd46578576 Auto submit login form when 2fa code is entered (#495) 2024-12-27 10:43:04 +01:00
Leendert de Borst
e577d6fee4 Print warnring but do not exit on image pull fail (#190) 2024-12-26 01:30:32 +01:00
Leendert de Borst
9d1923d3ea Refactor dev db start (#190) 2024-12-26 01:26:43 +01:00
Leendert de Borst
d77c28184c Refactor (#190) 2024-12-26 01:13:40 +01:00
Leendert de Borst
180de219c8 Update installer to look at latest release instead of main (#190) 2024-12-26 00:41:58 +01:00
Leendert de Borst
17e4f614d8 Refactor postgres docker setup and update docs (#190) 2024-12-26 00:39:19 +01:00
Leendert de Borst
747e0910cb Update SQLite ef model (#190) 2024-12-25 23:10:24 +01:00
Leendert de Borst
fc85f34218 Update useremailclaims setnull to be compatible with PostgreSQL (#190) 2024-12-25 23:01:54 +01:00
Leendert de Borst
f0e0e9c03e Add TaskRunnerJobs to migration (#190) 2024-12-25 22:55:10 +01:00
Leendert de Borst
2631a1f0b1 Update migration (#190) 2024-12-25 22:47:44 +01:00
Leendert de Borst
254104e12d Update migration logging (#190) 2024-12-25 22:46:08 +01:00
Leendert de Borst
a75d5c7a34 Update migration add data truncation if source data exceeds length (#190) 2024-12-25 22:41:56 +01:00
Leendert de Borst
bf40539e92 Update dockerignore to ignore data directories during build (#190) 2024-12-25 22:41:40 +01:00
Leendert de Borst
cb330219ab Refactor postgres db folder creation (#190) 2024-12-25 22:26:58 +01:00
Leendert de Borst
4f5e822722 Include postgres empty dir in git to ensure correct permissions (#190) 2024-12-25 22:23:43 +01:00
Leendert de Borst
96997c7d8d Update docs (#190) 2024-12-25 22:21:19 +01:00
Leendert de Borst
f959b7dc91 Update install.sh (#190) 2024-12-25 22:21:13 +01:00
Leendert de Borst
59599f43a3 Update docs (#190) 2024-12-25 16:53:30 +01:00
Leendert de Borst
b5e575051c Update migration logic to reset auto increment id (#190) 2024-12-25 16:45:17 +01:00
Leendert de Borst
433664d85d Fix admin redirect absolute URL bug (#190) 2024-12-25 14:40:44 +01:00
Leendert de Borst
82b2b75127 Update docs with new update instructions (#190) 2024-12-25 14:24:31 +01:00
Leendert de Borst
577e02d761 Update install script (#190) 2024-12-25 14:24:16 +01:00
Leendert de Borst
26b1c4e044 Load security page components async (#190) 2024-12-25 12:11:17 +01:00
Leendert de Borst
3872678039 Sanitize email when retrieving emails for emailbox (#190) 2024-12-24 22:20:44 +01:00
Leendert de Borst
80cc72eb22 Fix RecentEmails.razor dispose bug (#190) 2024-12-24 22:20:12 +01:00
Leendert de Borst
141a291ace Fix bug in db sync tests (#190) 2024-12-24 20:49:38 +01:00
Leendert de Borst
3b5e944417 Refactor (#190) 2024-12-24 15:48:34 +01:00
Leendert de Borst
65553e0918 Update postgresql date column types to improve compatiblity (#190) 2024-12-24 15:27:04 +01:00
Leendert de Borst
a7502d42e4 Fix migration tool params called from install.sh (#190) 2024-12-24 14:56:37 +01:00
Leendert de Borst
4d43acb53f Add build container start/stop/restart commands (#190) 2024-12-24 13:50:49 +01:00
Leendert de Borst
14ac94b78a Add migrate-db command to install.sh (#190) 2024-12-24 13:08:48 +01:00
Leendert de Borst
361f4b8817 Added migration logic from sqlite to postgresql (#190) 2024-12-24 12:53:22 +01:00
Leendert de Borst
7a62ddcf6a Enable postgresql legacy timestamp behavior (#190) 2024-12-24 12:39:57 +01:00
Leendert de Borst
6b59200df2 Fix migrations (#190) 2024-12-24 11:59:37 +01:00
Leendert de Borst
6a0699318c Add sqlite migrations to be in sync with postgresql model (#190) 2024-12-23 21:41:25 +01:00
Leendert de Borst
f6e2648a53 Update GitHub actions for postgresql (#190) 2024-12-23 20:52:39 +01:00
Leendert de Borst
4b8e4c907e Refactor WebApplicationFactoryFixture (#190) 2024-12-23 20:10:47 +01:00
Leendert de Borst
30804cc973 Update DataProtectionExtensions.cs (#190) 2024-12-23 18:00:47 +01:00
Leendert de Borst
8edfc3d0d6 Update Logout.razor (#190) 2024-12-23 17:11:30 +01:00
Leendert de Borst
4fb5087c82 Add local postgresql dev database (#190) 2024-12-23 16:31:02 +01:00
Leendert de Borst
cf454d2bb8 Add postgres healthcheck to docker-compose.yml (#190) 2024-12-23 16:03:59 +01:00
Leendert de Borst
0a577873ee Update install.sh to create postgres credentials (#190) 2024-12-23 15:40:00 +01:00
Leendert de Borst
32c8e48d45 Update Dockerfile (#190) 2024-12-23 15:25:18 +01:00
Leendert de Borst
564ae54de8 Update postgresql factory to support env vars if available (#190) 2024-12-23 15:11:34 +01:00
Leendert de Borst
d9f4f8d121 Update Dockerfile (#190) 2024-12-23 14:38:07 +01:00
Leendert de Borst
728b20b489 Update install.sh (#190) 2024-12-23 14:18:47 +01:00
Leendert de Borst
219f0bc9cc Update db configuration (#190) 2024-12-23 14:17:17 +01:00
Leendert de Borst
9735df0436 Update install.sh to generate postgresql credentials (#190) 2024-12-23 13:57:01 +01:00
Leendert de Borst
78a872a67d Refactor smtpserver and taskrunner so all tests pass (#190) 2024-12-23 12:58:07 +01:00
Leendert de Borst
77a48ea4e9 Refactor admin so all tests pass (#190) 2024-12-23 12:16:05 +01:00
Leendert de Borst
22538ae000 Refactor datetime to always use UTC (#190) 2024-12-22 21:36:01 +01:00
Leendert de Borst
db632c3edb Refactor SmtpService to use new dbcontextfactory (#190) 2024-12-22 20:05:05 +01:00
Leendert de Borst
1c53addcaa Refactor WebApi to use new dbcontextfactory (#190) 2024-12-22 18:58:24 +01:00
Leendert de Borst
817404cd08 Refactor UserService delete unused methods causing concurrency issues (#190) 2024-12-22 14:10:30 +01:00
Leendert de Borst
9062cdc701 Refactor admin project to use dbcontextfactory (#190) 2024-12-22 11:53:22 +01:00
Leendert de Borst
e45866fa67 Update EF models to not use driver specific fields (#190) 2024-12-22 11:26:16 +01:00
Leendert de Borst
8fbd10caaa Update admin project to use new IAliasServerDbContextFactory (#190) 2024-12-22 00:37:13 +01:00
Leendert de Borst
54d54f28b4 Move migrations for db engines to their respective folders (#190) 2024-12-22 00:07:31 +01:00
Leendert de Borst
3116aa5a1f Update postgresql.conf (#190) 2024-12-21 12:17:17 +01:00
Leendert de Borst
eb45358532 Update gitignore for db files (#190) 2024-12-21 12:09:43 +01:00
Leendert de Borst
03fd047cb4 Add postgresql docker container scaffolding (#190) 2024-12-21 11:56:08 +01:00
Leendert de Borst
6a7fc9c5ba Merge pull request #488 from lanedirt/343-add-option-to-disable-new-user-registration-via-installsh
Update install.sh
2024-12-20 20:23:06 +01:00
Leendert de Borst
62700de9ad Update install.sh (#343) 2024-12-20 20:22:43 +01:00
Leendert de Borst
edeaa77299 Merge pull request #487 from lanedirt/342-add-option-to-block-existing-user-in-admin
Add option to block existing user in admin
2024-12-20 19:57:39 +01:00
Leendert de Borst
84b93924f5 Add user block checks to api and add tests (#342) 2024-12-20 19:47:12 +01:00
Leendert de Borst
400e702753 Add user blocked status toggle to admin (#342) 2024-12-20 18:53:28 +01:00
Leendert de Borst
147f8db5d1 Add Blocked column to users table (#342) 2024-12-20 18:53:01 +01:00
Leendert de Borst
8e1470bc1b Merge pull request #486 from lanedirt/343-add-option-to-disable-new-user-registration-via-installsh
Add option to disable new user registration via install.sh
2024-12-20 18:24:50 +01:00
Leendert de Borst
50853bf011 Update tests (#343) 2024-12-20 17:30:28 +01:00
Leendert de Borst
07dd90a705 Add public registration enabled check to client (#343) 2024-12-20 16:52:05 +01:00
Leendert de Borst
a7a7d6d82b Rename public registration enabled flag (#343) 2024-12-20 16:51:51 +01:00
Leendert de Borst
249efe54b0 Add public registration env flag check to api (#343) 2024-12-20 16:06:15 +01:00
Leendert de Borst
20eb3e5ff4 Add public registration setting to install.sh (#343) 2024-12-20 15:56:30 +01:00
Leendert de Borst
ba15c446d9 Merge pull request #484 from lanedirt/483-dark-mode-text-readability-tweaks
Dark mode text readability tweaks
2024-12-19 15:54:55 +01:00
Leendert de Borst
5ea9f4ee08 Merge pull request #482 from lanedirt/481-add-username-sanity-check-on-vault-save-to-prevent-db-corruption-between-user-sessions
Add username sanity check to vault save to prevent potential vault collision/corruption
2024-12-19 15:54:47 +01:00
Leendert de Borst
1e7b7b172a Update tests to work with changed notifications (#481) 2024-12-19 15:39:22 +01:00
Leendert de Borst
35f6565c8b Update DbService.cs to fix merge return status (#481) 2024-12-19 15:16:28 +01:00
Leendert de Borst
8cb99c997d Update Logo.razor (#483) 2024-12-19 15:03:48 +01:00
Leendert de Borst
16cf528b7f Add dark mode tweaks to admin error page (#483) 2024-12-19 14:55:25 +01:00
Leendert de Borst
8ad3eb9bd5 Add dark mode tweaks to client two factor code page (#483) 2024-12-19 14:55:14 +01:00
Leendert de Borst
2d59c40e24 Refactor username sanity check to associate with vault load instead of login (#481) 2024-12-19 14:39:05 +01:00
Leendert de Borst
33283e07be Set username on unlock (#481) 2024-12-19 13:34:14 +01:00
Leendert de Borst
fbf5880370 Add username sanity check to vault save (#481) 2024-12-19 12:14:06 +01:00
Leendert de Borst
be4a74ef3c Update README.md 2024-12-18 10:54:09 +01:00
Leendert de Borst
a759091755 Update AppInfo.cs (#479) 2024-12-16 16:55:58 +01:00
dependabot[bot]
8dc99c09a8 Bump Swashbuckle.AspNetCore from 7.1.0 to 7.2.0
Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 7.1.0 to 7.2.0.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v7.1.0...v7.2.0)

---
updated-dependencies:
- dependency-name: Swashbuckle.AspNetCore
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 12:19:17 +01:00
dependabot[bot]
b9ec4baf66 Bump NUglify from 1.21.10 to 1.21.11
Bumps [NUglify](https://github.com/trullock/NUglify) from 1.21.10 to 1.21.11.
- [Release notes](https://github.com/trullock/NUglify/releases)
- [Changelog](https://github.com/trullock/NUglify/blob/master/changelog.md)
- [Commits](https://github.com/trullock/NUglify/compare/v1.21.10...v1.21.11)

---
updated-dependencies:
- dependency-name: NUglify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 12:19:10 +01:00
Leendert de Borst
71ed62cdcb Merge pull request #478 from lanedirt/469-webassembly-required-error-not-visible-in-client-app
Add E2E test for browser with WASM disabled
2024-12-16 12:19:00 +01:00
dependabot[bot]
2bbad8c75c Bump NUnit from 4.2.2 to 4.3.0
Bumps [NUnit](https://github.com/nunit/nunit) from 4.2.2 to 4.3.0.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/4.2.2...4.3.0)

---
updated-dependencies:
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 11:24:59 +01:00
dependabot[bot]
f02b841eea Bump Serilog and Serilog.Settings.Configuration
Bumps [Serilog](https://github.com/serilog/serilog) and [Serilog.Settings.Configuration](https://github.com/serilog/serilog-settings-configuration). These dependencies needed to be updated together.

Updates `Serilog` from 4.2.0 to 4.2.0
- [Release notes](https://github.com/serilog/serilog/releases)
- [Commits](https://github.com/serilog/serilog/compare/v4.2.0...v4.2.0)

Updates `Serilog.Settings.Configuration` from 8.0.4 to 9.0.0
- [Release notes](https://github.com/serilog/serilog-settings-configuration/releases)
- [Changelog](https://github.com/serilog/serilog-settings-configuration/blob/dev/CHANGES.md)
- [Commits](https://github.com/serilog/serilog-settings-configuration/compare/v8.0.4...v9.0.0)

---
updated-dependencies:
- dependency-name: Serilog
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Serilog.Settings.Configuration
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 11:24:36 +01:00
dependabot[bot]
f6fc5af8ac Bump MailKit from 4.8.0 to 4.9.0
Bumps [MailKit](https://github.com/jstedfast/MailKit) from 4.8.0 to 4.9.0.
- [Changelog](https://github.com/jstedfast/MailKit/blob/master/ReleaseNotes.md)
- [Commits](https://github.com/jstedfast/MailKit/compare/4.8.0...4.9.0)

---
updated-dependencies:
- dependency-name: MailKit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 11:24:30 +01:00
dependabot[bot]
1d1155bf0e Bump MimeKit from 4.8.0 to 4.9.0
Bumps [MimeKit](https://github.com/jstedfast/MimeKit) from 4.8.0 to 4.9.0.
- [Changelog](https://github.com/jstedfast/MimeKit/blob/master/ReleaseNotes.md)
- [Commits](https://github.com/jstedfast/MimeKit/compare/4.8.0...4.9.0)

---
updated-dependencies:
- dependency-name: MimeKit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 11:24:24 +01:00
Leendert de Borst
2632211af6 Merge pull request #470 from lanedirt/469-webassembly-required-error-not-visible-in-client-app
Show error if client does not support WebAssembly
2024-12-16 10:34:20 +01:00
Leendert de Borst
05cca6998e Merge pull request #468 from lanedirt/467-task-runner-jobs-do-not-always-run-at-configured-time
Add task runner job table for tracking task runner historic runs
2024-12-16 10:18:13 +01:00
Leendert de Borst
c4a8a20a62 Add E2E test for browser with WASM disabled (#469) 2024-12-15 17:05:31 +01:00
Leendert de Borst
f2c6af9ccb Update install.sh URL comment (#469) 2024-12-15 16:43:48 +01:00
Leendert de Borst
e94201acda Tweak logo on mobile view auth area (#469) 2024-12-15 16:28:57 +01:00
Leendert de Borst
9e03473208 Show error message when client does not support WebAssembly (#469) 2024-12-15 16:28:41 +01:00
Leendert de Borst
0c5b2fb1da Add task runner job table and manual start button (#467) 2024-12-15 15:59:51 +01:00
Leendert de Borst
a5c4a7618d Update AliasServerDbContext.cs so pragma settings are applied correctly (#467) 2024-12-15 14:53:33 +01:00
1351 changed files with 127770 additions and 25168 deletions

View File

@@ -22,4 +22,17 @@
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
README.md
# Exclude AliasVault data directories
database/
logs/
certificates/
# Exclude git directory
.git/
# Exclude development files
*.log
*.env
*.env.*

View File

@@ -1,8 +1,106 @@
# ----------------------------------------------------------------------------
# AliasVault configuration file.
#
# Note: we recommend using the provided install.sh script to install and
# configure AliasVault, as this will automatically set all of the following
# variables for you and allow you to easily change them later via the CLI.
# It also allows for easily updating AliasVault to a newer version in the
# future.
#
# However if you still wish to manually install or configure AliasVault,
# you can do so below.
#
# After changing settings here, make sure to restart all AliasVault
# Docker containers to apply the changes.
# ----------------------------------------------------------------------------
# Set the ports that your AliasVault will be accessible at.
# These are the default ports that will be used by the `reverse-proxy` and `smtp` containers.
# You can change these to any other ports that are available on your system.
HTTP_PORT=80
HTTPS_PORT=443
SMTP_PORT=25
SMTP_TLS_PORT=587
# Set the hostname that your AliasVault will be accessible at.
# E.g. `aliasvault.mydomain.com` or if you're running it on your local machine, choose `localhost`.
HOSTNAME=
# Set a random 32 character string for the JWT key.
# This can be generated using the following command:
# $ openssl rand -base64 32
JWT_KEY=
# Set the password for the data protection certificate.
# This can be generated using the following command:
# $ openssl rand -base64 32
DATA_PROTECTION_CERT_PASS=
# ----------------------------------------------------------------------------
# Database configuration
# ----------------------------------------------------------------------------
# These are the credentials that are used by the PostgreSQL container
# on startup to create the database and user, and for the application to
# connect to the database.
POSTGRES_DB=aliasvault
POSTGRES_USER=aliasvault
# Set the password for the database user.
# This can be generated using the following command:
# $ openssl rand -base64 32
POSTGRES_PASSWORD=
# Note: in order to change the password for an existing installation
# refer to https://docs.aliasvault.net/misc/dev/database-operations.html
# ----------------------------------------------------------------------------
# Admin user configuration
# ----------------------------------------------------------------------------
# Set the password for the admin user. This is an encrypted hash that needs
# to be generated using the `aliasvault-cli` tool. This allows you to login
# to the admin panel at https://your-hostname/admin.
#
# For example:
# docker run --rm ghcr.io/lanedirt/aliasvault-installcli:latest hash-password "my-password"
#
# Then copy the output and paste it into the ADMIN_PASSWORD_HASH variable below.
# When changing the hash, update the ADMIN_PASSWORD_GENERATED variable to the current date and time
# and then restart the AliasVault docker containers to apply the changes.
ADMIN_PASSWORD_HASH=
# Set the date and time the admin password was last generated. When changing the
# admin password hash manually, make sure to increase this value so the system
# knows that the password has been changed and should be overwritten with the new hash.
ADMIN_PASSWORD_GENERATED=2024-01-01T00:00:00Z
PRIVATE_EMAIL_DOMAINS=
# ----------------------------------------------------------------------------
# Email server configuration for email aliases
# ----------------------------------------------------------------------------
# In order to use AliasVault's private email domains feature, you need to configure
# your DNS. Please refer to the full documentation for more instructions on DNS:
# https://docs.aliasvault.net/installation/install.html#3-email-server-setup
#
# Set the private email domains below that are allowed to be used (comma separated values).
# Example: PRIVATE_EMAIL_DOMAINS=example.com,example2.org
# To disable the private email domains feature, set this to "DISABLED.TLD"
PRIVATE_EMAIL_DOMAINS=DISABLED.TLD
# Set whether TLS is enabled for SMTP.
SMTP_TLS_ENABLED=false
# ----------------------------------------------------------------------------
# Let's Encrypt configuration
# ----------------------------------------------------------------------------
# Set whether Let's Encrypt is enabled. This is only supported through
# the install.sh script.
LETSENCRYPT_ENABLED=false
# ----------------------------------------------------------------------------
# Optional configuration settings
# ----------------------------------------------------------------------------
PUBLIC_REGISTRATION_ENABLED=true
IP_LOGGING_ENABLED=true
# Set the support email address which is shown to users in the main web app.
# Keep this blank if you don't want to show a support email.
SUPPORT_EMAIL=

31
.gitattributes vendored
View File

@@ -1,2 +1,31 @@
# Auto detect text files and perform LF normalization
# Set default behavior to automatically normalize line endings
* text=auto
# Common files should always use LF (Unix-style) line endings
*.sh text eol=lf
*.cs text eol=lf
*.razor text eol=lf
*.css text eol=lf
*.html text eol=lf
*.js text eol=lf
*.json text eol=lf
*.xml text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
# Docker files should use LF
Dockerfile text eol=lf
docker-compose*.yml text eol=lf
# Config files should use LF
*.conf text eol=lf
*.config text eol=lf
.env* text eol=lf
# Batch scripts should always use CRLF (Windows-style) line endings
*.bat text eol=crlf
*.cmd text eol=crlf
# Documentation should be normalized
*.md text
*.txt text

2
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
# These are supported funding model platforms
buy_me_a_coffee: lanedirt

27
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,27 @@
---
name: Bug report
about: Report a bug or unexpected behavior.
title: "[BUG] "
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for AliasVault
title: '[Feature Request] '
labels: '⚡️ enhancement'
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

15
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,15 @@
## Description
- [ ] Bug fix
- [ ] Feature enhancement
- [ ] Documentation update
- [ ] Other (please describe):
## Related Issues
Fixes #[issue-number]
## Checklist
- [ ] Code adheres to project standards and guidelines.
- [ ] Documentation has been updated where applicable.
## Additional Information
Add any additional context, screenshots, or explanations here.

View File

@@ -1,10 +0,0 @@
#!/bin/bash
# Commit-msg hook to check commit messages for issue number in format "(#123)"
commit_message=$(cat "$1")
if ! grep -q "(\#[0-9]\+)" <<< "$commit_message"; then
echo "Error: Commit message must contain an issue number in the format \"(#123)\""
exit 1
fi

View File

@@ -0,0 +1,219 @@
name: Browser Extension Build
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-shared-libraries:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Build and distribute shared libraries
run: |
cd ./shared
chmod +x build-and-distribute.sh
./build-and-distribute.sh
- name: Verify shared library distribution
run: |
# Check if files exist and were recently modified
TARGET_DIRS=(
"apps/browser-extension/src/utils/shared/identity-generator"
"apps/browser-extension/src/utils/shared/password-generator"
)
for dir in "${TARGET_DIRS[@]}"; do
if [ ! -d "$dir" ]; then
echo "❌ Directory $dir does not exist"
exit 1
fi
# Check for required files
REQUIRED_FILES=("index.js" "index.mjs" "index.d.ts" "index.js.map" "index.mjs.map")
for file in "${REQUIRED_FILES[@]}"; do
if [ ! -f "$dir/$file" ]; then
echo "❌ Required file $dir/$file does not exist"
exit 1
fi
done
# Check if files were modified in the last 5 minutes
find "$dir" -type f -mmin -5 | grep -q . || {
echo "❌ Files in $dir were not recently modified"
exit 1
}
done
echo "✅ Shared library distribution verified"
build-chrome-extension:
needs: build-shared-libraries
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/browser-extension
steps:
- uses: actions/checkout@v4
- name: Get short SHA
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/browser-extension/package-lock.json
- name: Install dependencies
run: npm ci
- name: Build extension
run: npm run build:chrome
- name: Run tests
run: npm run test
- name: Run linting
run: npm run lint
- name: Zip Chrome Extension
run: npm run zip:chrome
- name: Unzip for artifact
run: |
mkdir -p dist/chrome-unpacked
unzip dist/aliasvault-browser-extension-*-chrome.zip -d dist/chrome-unpacked
- name: Upload dist artifact Chrome
uses: actions/upload-artifact@v4
with:
name: aliasvault-browser-extension-${{ github.event_name == 'release' && github.ref_name || (github.ref_name == 'main' && format('main-{0}', steps.vars.outputs.sha_short) || steps.vars.outputs.sha_short) }}-chrome
path: apps/browser-extension/dist/chrome-unpacked
outputs:
sha_short: ${{ steps.vars.outputs.sha_short }}
build-firefox-extension:
needs: build-shared-libraries
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/browser-extension
steps:
- uses: actions/checkout@v4
- name: Get short SHA
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/browser-extension/package-lock.json
- name: Install dependencies
run: npm ci
- name: Build extension
run: npm run build:firefox
- name: Run tests
run: npm run test
- name: Run linting
run: npm run lint
- name: Zip Firefox Extension
run: npm run zip:firefox
- name: Unzip for artifact
run: |
mkdir -p dist/firefox-unpacked
unzip dist/aliasvault-browser-extension-*-firefox.zip -d dist/firefox-unpacked
mkdir -p dist/sources-unpacked
unzip dist/aliasvault-browser-extension-*-sources.zip -d dist/sources-unpacked
- name: Upload dist artifact Firefox
uses: actions/upload-artifact@v4
with:
name: aliasvault-browser-extension-${{ github.event_name == 'release' && github.ref_name || (github.ref_name == 'main' && format('main-{0}', steps.vars.outputs.sha_short) || steps.vars.outputs.sha_short) }}-firefox
path: apps/browser-extension/dist/firefox-unpacked
- name: Upload dist artifact Firefox sources
uses: actions/upload-artifact@v4
with:
name: aliasvault-browser-extension-${{ github.event_name == 'release' && github.ref_name || (github.ref_name == 'main' && format('main-{0}', steps.vars.outputs.sha_short) || steps.vars.outputs.sha_short) }}-sources
path: apps/browser-extension/dist/sources-unpacked
outputs:
sha_short: ${{ steps.vars.outputs.sha_short }}
build-edge-extension:
needs: build-shared-libraries
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/browser-extension
steps:
- uses: actions/checkout@v4
- name: Get short SHA
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/browser-extension/package-lock.json
- name: Install dependencies
run: npm ci
- name: Build extension
run: npm run build:edge
- name: Run tests
run: npm run test
- name: Run linting
run: npm run lint
- name: Zip Edge Extension
run: npm run zip:edge
- name: Unzip for artifact
run: |
mkdir -p dist/edge-unpacked
unzip dist/aliasvault-browser-extension-*-edge.zip -d dist/edge-unpacked
- name: Upload dist artifact Edge
uses: actions/upload-artifact@v4
with:
name: aliasvault-browser-extension-${{ github.event_name == 'release' && github.ref_name || (github.ref_name == 'main' && format('main-{0}', steps.vars.outputs.sha_short) || steps.vars.outputs.sha_short) }}-edge
path: apps/browser-extension/dist/edge-unpacked
outputs:
sha_short: ${{ steps.vars.outputs.sha_short }}

205
.github/workflows/docker-build.yml vendored Normal file
View File

@@ -0,0 +1,205 @@
name: Docker Pull and Build
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
docker-compose-pull:
name: Docker Compose Pull Test
runs-on: ubuntu-latest
services:
docker:
image: docker:26.0.0
options: --privileged
steps:
- name: Get repository and branch information
id: repo-info
run: |
if [ "${{ github.event_name }}" = "pull_request" ] && [ "${{ github.event.pull_request.head.repo.fork }}" = "true" ]; then
echo "REPO_FULL_NAME=lanedirt/AliasVault" >> $GITHUB_ENV
echo "BRANCH_NAME=main" >> $GITHUB_ENV
else
echo "REPO_FULL_NAME=${GITHUB_REPOSITORY}" >> $GITHUB_ENV
echo "BRANCH_NAME=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_ENV
fi
- name: Download install script from current branch
run: |
INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/$REPO_FULL_NAME/$BRANCH_NAME/install.sh"
echo "Downloading install script from: $INSTALL_SCRIPT_URL"
curl -f -o install.sh "$INSTALL_SCRIPT_URL"
- name: Create .env file with custom SMTP port
run: echo "SMTP_PORT=2525" > .env
- name: Set permissions and run install.sh (install)
id: install_script
run: |
chmod +x install.sh
{
./install.sh install --verbose
exit_code=$?
if [ $exit_code -eq 2 ]; then
echo "skip_remaining=true" >> $GITHUB_OUTPUT
true
elif [ $exit_code -ne 0 ]; then
false
fi
} || {
if [ $exit_code -eq 2 ]; then
echo "skip_remaining=true" >> $GITHUB_OUTPUT
true
else
exit $exit_code
fi
}
- name: Run docker compose up
if: ${{ !steps.install_script.outputs.skip_remaining }}
run: docker compose -f docker-compose.yml up -d
- name: Wait for services
if: ${{ !steps.install_script.outputs.skip_remaining }}
run: sleep 10
- name: Test WASM App
if: ${{ !steps.install_script.outputs.skip_remaining }}
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443)
if [ "$http_code" -ne 200 ]; then
echo "WASM app failed with $http_code"
exit 1
fi
- name: Test WebApi
if: ${{ !steps.install_script.outputs.skip_remaining }}
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/api)
if [ "$http_code" -ne 200 ]; then
echo "WebApi failed with $http_code"
exit 1
fi
- name: Test Admin App
if: ${{ !steps.install_script.outputs.skip_remaining }}
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/admin/user/login)
if [ "$http_code" -ne 200 ]; then
echo "Admin app failed with $http_code"
exit 1
fi
- name: Test SMTP
if: ${{ !steps.install_script.outputs.skip_remaining }}
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
if ! nc -zv localhost 2525 2>&1 | grep -q 'succeeded'; then
echo "SMTP failed"
exit 1
fi
- name: Test reset-admin-password output
if: ${{ !steps.install_script.outputs.skip_remaining }}
run: |
output=$(./install.sh reset-admin-password)
if ! echo "$output" | grep -E '.*New admin password: [A-Za-z0-9+/=]{8,}.*'; then
echo "Invalid reset-admin-password output"
exit 1
fi
docker-compose-build:
name: Docker Compose Build Test
runs-on: ubuntu-latest
services:
docker:
image: docker:26.0.0
options: --privileged
steps:
- uses: actions/checkout@v2
- name: Create .env file with custom SMTP port
run: echo "SMTP_PORT=2525" > .env
- name: Set permissions and run install.sh build
run: |
chmod +x install.sh
./install.sh build --verbose
- name: Test services are responding
uses: nick-fields/retry@v3
with:
timeout_minutes: 5
max_attempts: 5
command: |
sleep 15
declare -A endpoints=(
["WASM"]="https://localhost:443"
["WebApi"]="https://localhost:443/api"
["Admin"]="https://localhost:443/admin/user/login"
)
failed=false
for name in "${!endpoints[@]}"; do
url="${endpoints[$name]}"
echo "Testing $name at $url"
response=$(curl -k -s -w "\nHTTP_CODE=%{http_code}" "$url")
http_code=$(echo "$response" | grep "HTTP_CODE=" | cut -d= -f2)
if [ "$http_code" -ne 200 ]; then
echo "❌ $name failed with $http_code"
failed=true
else
echo "✅ $name passed"
fi
done
echo "Testing SMTP on port 2525"
if ! nc -zv localhost 2525 2>&1 | grep -q 'succeeded'; then
echo "❌ SMTP failed"
failed=true
else
echo "✅ SMTP passed"
fi
if [ "$failed" = true ]; then
echo "Dumping logs"
docker compose logs admin
docker compose logs api
docker compose logs client
docker compose logs smtp
docker compose logs reverse-proxy
docker compose restart
exit 1
fi
- name: Test reset-admin-password output
run: |
output=$(./install.sh reset-admin-password)
if ! echo "$output" | grep -E '.*New admin password: [A-Za-z0-9+/=]{8,}.*'; then
echo "Invalid reset-admin-password output"
exit 1
fi

View File

@@ -1,103 +0,0 @@
name: Docker Compose Build
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
test-docker:
runs-on: ubuntu-latest
services:
docker:
image: docker:26.0.0
options: --privileged
steps:
- uses: actions/checkout@v2
- name: Create .env file with custom SMTP port as port 25 is not allowed in GitHub Actions
run: |
echo "SMTP_PORT=2525" > .env
- name: Set permissions and run install.sh
run: |
chmod +x install.sh
./install.sh build --verbose
- name: Test if services are responding
uses: nick-fields/retry@v3
with:
timeout_minutes: 5
max_attempts: 5
command: |
sleep 15
# Array of endpoints to test
declare -A endpoints=(
["WASM"]="https://localhost:443"
["WebApi"]="https://localhost:443/api"
["Admin"]="https://localhost:443/admin/user/login"
)
failed=false
# Test HTTP endpoints
for name in "${!endpoints[@]}"; do
url="${endpoints[$name]}"
echo "Testing $name at $url"
# Store both response body and HTTP code
response=$(curl -k -s -w "\nHTTP_CODE=%{http_code}" "$url")
http_code=$(echo "$response" | grep "HTTP_CODE=" | cut -d= -f2)
body=$(echo "$response" | sed '$d') # Remove the last line (HTTP_CODE)
if [ "$http_code" -ne 200 ]; then
echo "❌ $name failed with HTTP $http_code at $url"
echo "Response body:"
echo "$body"
failed=true
else
echo "✅ $name responded with HTTP 200"
fi
done
# Test SMTP
echo "Testing SmtpService at localhost:2525"
if ! nc -zv localhost 2525 2>&1 | grep -q 'succeeded'; then
echo "❌ SmtpService failed to respond on port 2525"
failed=true
else
echo "✅ SmtpService responded successfully"
fi
# Exit with error if any service failed
if [ "$failed" = true ]; then
# Get container logs
echo "Container Logs admin:"
docker compose logs admin
echo "Container Logs api:"
docker compose logs api
echo "Container Logs client:"
docker compose logs client
echo "Container Logs smtp:"
docker compose logs smtp
echo "Container Logs reverse-proxy:"
docker compose logs reverse-proxy
# Restart containers for next test in case of failure
docker compose restart
exit 1
fi
- name: Test install.sh reset-password output
run: |
output=$(./install.sh reset-password)
if ! echo "$output" | grep -E '.*New admin password: [A-Za-z0-9+/=]{8,}.*'; then
echo "Password reset output format is incorrect"
echo "Expected: 'New admin password: <at least 8 base64 chars>'"
echo "Actual: $output"
exit 1
fi

View File

@@ -1,112 +0,0 @@
# This workflow will test if pulling the latest Docker Compose containers from the registry works.
name: Docker Compose Pull
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
test-docker:
runs-on: ubuntu-latest
services:
docker:
image: docker:26.0.0
options: --privileged
steps:
- name: Get repository and branch information
id: repo-info
run: |
echo "REPO_FULL_NAME=${GITHUB_REPOSITORY}" >> $GITHUB_ENV
echo "BRANCH_NAME=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_ENV
- name: Download install script from current branch
run: |
INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/$REPO_FULL_NAME/$BRANCH_NAME/install.sh"
echo "Downloading install script from: $INSTALL_SCRIPT_URL"
curl -f -o install.sh "$INSTALL_SCRIPT_URL"
- name: Create .env file with custom SMTP port as port 25 is not allowed in GitHub Actions
run: |
echo "SMTP_PORT=2525" > .env
- name: Set permissions and run install.sh
run: |
chmod +x install.sh
./install.sh install --verbose
- name: Set up Docker Compose
run: docker compose -f docker-compose.yml up -d
- name: Wait for services to be up
run: |
# Wait for a few seconds
sleep 10
- name: Test if localhost:443 (WASM app) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with 200 OK. Check if client app and/or nginx is configured correctly."
exit 1
else
echo "Service responded with 200 OK"
fi
- name: Test if localhost:443/api (WebApi) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/api)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with expected 200 OK. Check if WebApi and/or nginx is configured correctly."
exit 1
else
echo "Service responded with $http_code"
fi
- name: Test if localhost:443/admin (Admin) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/admin/user/login)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with expected 200 OK. Check if admin app and/or nginx is configured correctly."
exit 1
else
echo "Service responded with $http_code"
fi
- name: Test if localhost:2525 (SmtpService) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
if ! nc -zv localhost 2525 2>&1 | grep -q 'succeeded'; then
echo "SmtpService did not respond on port 2525. Check if the SmtpService service is running."
exit 1
else
echo "SmtpService responded on port 2525"
fi
- name: Test install.sh reset-password output
run: |
output=$(./install.sh reset-password)
if ! echo "$output" | grep -E '.*New admin password: [A-Za-z0-9+/=]{8,}.*'; then
echo "Password reset output format is incorrect. Expected format: 'New admin password: <at least 8 base64 chars>'"
echo "Actual output: $output"
exit 1
else
echo "Password reset output format is correct"
fi

View File

@@ -1,43 +0,0 @@
# This workflow will test if running the E2E Admin tests via Playwright CLI works.
name: .NET E2E Admin Tests (Playwright)
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
admin-tests:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Install dependencies
run: dotnet workload install wasm-tools
- name: Build
run: dotnet build
- name: Ensure browsers are installed
run: pwsh src/Tests/AliasVault.E2ETests/bin/Debug/net9.0/playwright.ps1 install --with-deps
- name: Run AdminTests with retry
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
max_attempts: 3
command: dotnet test src/Tests/AliasVault.E2ETests --no-build --verbosity normal --filter "Category=AdminTests"
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v3
with:
name: admin-test-results
path: TestResults-Admin.xml

View File

@@ -1,40 +0,0 @@
# This workflow will test if running the E2E Client tests via Playwright CLI works.
name: .NET E2E Client Tests (Playwright with Sharding)
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
client-tests:
timeout-minutes: 60
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Install dependencies
run: dotnet workload install wasm-tools
- name: Build
run: dotnet build
- name: Ensure browsers are installed
run: pwsh src/Tests/AliasVault.E2ETests/bin/Debug/net9.0/playwright.ps1 install --with-deps
- name: Run ClientTests with retry (Shard ${{ matrix.shard }})
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
max_attempts: 3
command: dotnet test src/Tests/AliasVault.E2ETests --no-build --verbosity normal --filter "FullyQualifiedName~.E2ETests.Tests.Client.Shard${{ matrix.shard }}."

View File

@@ -1,43 +0,0 @@
# This workflow will test if running the E2E Misc tests via Playwright CLI works.
name: .NET E2E Misc Tests (Playwright)
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
misc-tests:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Install dependencies
run: dotnet workload install wasm-tools
- name: Build
run: dotnet build
- name: Ensure browsers are installed
run: pwsh src/Tests/AliasVault.E2ETests/bin/Debug/net9.0/playwright.ps1 install --with-deps
- name: Run remaining tests with retry
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
max_attempts: 3
command: dotnet test src/Tests/AliasVault.E2ETests --no-build --verbosity normal --filter "Category!=AdminTests&Category!=ClientTests"
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v3
with:
name: misc-test-results
path: TestResults-Misc.xml

88
.github/workflows/dotnet-e2e-tests.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
# This workflow will test if running the e2e tests works.
name: E2E Tests
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
admin-tests:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Install dependencies
run: dotnet workload install wasm-tools
- name: Build
working-directory: apps/server
run: dotnet build
- name: Start dev database
run: ./install.sh configure-dev-db start
- name: Ensure browsers are installed
working-directory: apps/server
run: pwsh Tests/AliasVault.E2ETests/bin/Debug/net9.0/playwright.ps1 install --with-deps
- name: Run AdminTests with retry
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
max_attempts: 3
command: cd apps/server && dotnet test Tests/AliasVault.E2ETests --no-build --verbosity normal --filter "Category=AdminTests"
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v4
with:
name: admin-test-results
path: TestResults-Admin.xml
client-tests:
timeout-minutes: 60
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Install dependencies
run: dotnet workload install wasm-tools
- name: Build
working-directory: apps/server
run: dotnet build
- name: Start dev database
run: ./install.sh configure-dev-db start
- name: Ensure browsers are installed
working-directory: apps/server
run: pwsh Tests/AliasVault.E2ETests/bin/Debug/net9.0/playwright.ps1 install --with-deps
- name: Run ClientTests with retry (Shard ${{ matrix.shard }})
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
max_attempts: 3
command: cd apps/server && dotnet test Tests/AliasVault.E2ETests --no-build --verbosity normal --filter "FullyQualifiedName~.E2ETests.Tests.Client.Shard${{ matrix.shard }}."

View File

@@ -1,5 +1,5 @@
# This workflow will test if running the integration tests works.
name: .NET Integration Tests
name: Integration Tests
on:
push:
@@ -7,6 +7,10 @@ on:
pull_request:
branches: [ "main" ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
timeout-minutes: 60
@@ -23,7 +27,12 @@ jobs:
run: dotnet workload install wasm-tools
- name: Build
working-directory: apps/server
run: dotnet build
- name: Start dev database
run: ./install.sh configure-dev-db start
- name: Run integration tests
run: dotnet test src/Tests/AliasVault.IntegrationTests --no-build --verbosity normal
working-directory: apps/server
run: dotnet test Tests/AliasVault.IntegrationTests --no-build --verbosity normal

View File

@@ -1,5 +1,5 @@
# This workflow will test if running the unit tests works.
name: .NET Unit Tests
name: Unit Tests
on:
push:
@@ -7,6 +7,10 @@ on:
pull_request:
branches: [ "main" ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
@@ -22,10 +26,13 @@ jobs:
run: dotnet workload install wasm-tools
- name: Restore dependencies
working-directory: apps/server
run: dotnet restore
- name: Build
working-directory: apps/server
run: dotnet build --no-restore
- name: Run unittests
run: dotnet test src/Tests/AliasVault.UnitTests --no-build --verbosity normal
working-directory: apps/server
run: dotnet test Tests/AliasVault.UnitTests --no-build --verbosity normal

301
.github/workflows/mobile-app-build.yml vendored Normal file
View File

@@ -0,0 +1,301 @@
name: Mobile App Build
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_dispatch:
inputs:
build_android_signed:
description: 'Build signed Android APK/AAB'
required: true
type: boolean
default: false
build_ios_signed:
description: 'Build signed iOS IPA'
required: true
type: boolean
default: false
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
setup:
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/mobile-app
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/mobile-app/package-lock.json
- name: Build and distribute shared libraries
run: |
cd ../../shared
chmod +x build-and-distribute.sh
./build-and-distribute.sh
- name: Verify shared library distribution
run: |
# Check if files exist and were recently modified
TARGET_DIRS=(
"utils/shared/identity-generator"
"utils/shared/password-generator"
)
for dir in "${TARGET_DIRS[@]}"; do
if [ ! -d "$dir" ]; then
echo "❌ Directory $dir does not exist"
exit 1
fi
# Check for required files
REQUIRED_FILES=("index.js" "index.mjs" "index.d.ts" "index.js.map" "index.mjs.map")
for file in "${REQUIRED_FILES[@]}"; do
if [ ! -f "$dir/$file" ]; then
echo "❌ Required file $dir/$file does not exist"
exit 1
fi
done
# Check if files were modified in the last 5 minutes
find "$dir" -type f -mmin -5 | grep -q . || {
echo "❌ Files in $dir were not recently modified"
exit 1
}
done
echo "✅ Shared library distribution verified"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test
- name: Run linting
run: npm run lint
build-ios:
needs: setup
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/mobile-app
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/mobile-app/package-lock.json
- name: Install dependencies
run: npm ci
- name: Build JS bundle (iOS - Expo)
run: |
mkdir -p build
npx expo export \
--dev \
--output-dir ./build \
--platform ios
build-android:
needs: setup
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/mobile-app
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/mobile-app/package-lock.json
- name: Install dependencies
run: npm ci
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Build JS bundle (Android - Expo)
run: |
mkdir -p build
npx expo export \
--dev \
--output-dir ./build \
--platform android
- name: Run Android Unit Tests
run: |
cd android
./gradlew :app:testDebugUnitTest --tests "net.aliasvault.app.*"
- name: Upload Android Test Reports
if: always()
uses: actions/upload-artifact@v4
with:
name: android-test-reports
path: apps/mobile-app/android/app/build/reports/tests/testDebugUnitTest/
retention-days: 7
build-android-signed:
needs: setup
if: github.event_name == 'workflow_dispatch' && github.event.inputs.build_android_signed == 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/mobile-app
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/mobile-app/package-lock.json
- name: Install dependencies
run: npm ci
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Decode keystore
run: |
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > android/app/keystore.jks
- name: Configure signing
run: |
cat >> android/gradle.properties <<EOF
ALIASVAULT_UPLOAD_STORE_FILE=keystore.jks
ALIASVAULT_UPLOAD_KEY_ALIAS=${{ secrets.ANDROID_KEY_ALIAS }}
ALIASVAULT_UPLOAD_STORE_PASSWORD=${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ALIASVAULT_UPLOAD_KEY_PASSWORD=${{ secrets.ANDROID_KEY_PASSWORD }}
EOF
- name: Build Signed APK & AAB
run: |
cd android
./gradlew bundleRelease
./gradlew assembleRelease
- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: signed-apk
path: apps/mobile-app/android/app/build/outputs/apk/release/app-release.apk
retention-days: 14
- name: Upload AAB
uses: actions/upload-artifact@v4
with:
name: signed-aab
path: apps/mobile-app/android/app/build/outputs/bundle/release/app-release.aab
retention-days: 14
build-ios-signed:
needs: setup
if: github.event_name == 'workflow_dispatch' && github.event.inputs.build_ios_signed == 'true'
runs-on: macos-15
defaults:
run:
working-directory: apps/mobile-app
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/mobile-app/package-lock.json
- name: Install dependencies
run: npm ci
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Install Fastlane
run: gem install fastlane
- name: Create ASC private key file
run: |
mkdir -p $RUNNER_TEMP/asc
echo "${{ secrets.ASC_PRIVATE_KEY_BASE64 }}" | base64 --decode > $RUNNER_TEMP/asc/AuthKey.p8
- name: Install CocoaPods
run: |
cd ios
pod install
- name: Build iOS IPA
env:
IDEFileSystemSynchronizedGroupsAreEnabled: NO
XCODE_WORKSPACE: AliasVault.xcworkspace
XCODE_SCHEME: AliasVault
XCODE_CONFIGURATION: Release
XCODE_ARCHIVE_PATH: AliasVault.xcarchive
XCODE_EXPORT_PATH: ./build
XCODE_SKIP_FILESYSTEM_SYNC: true
run: |
cd ios
xcodebuild clean -workspace "$XCODE_WORKSPACE" \
-scheme "$XCODE_SCHEME" \
-configuration "$XCODE_CONFIGURATION"
xcodebuild -workspace "$XCODE_WORKSPACE" \
-scheme "$XCODE_SCHEME" \
-configuration "$XCODE_CONFIGURATION" \
-archivePath "$XCODE_ARCHIVE_PATH" \
-destination 'generic/platform=iOS' \
-allowProvisioningUpdates \
-authenticationKeyPath $RUNNER_TEMP/asc/AuthKey.p8 \
-authenticationKeyID ${{ secrets.ASC_KEY_ID }} \
-authenticationKeyIssuerID ${{ secrets.ASC_ISSUER_ID }} \
archive
xcodebuild -exportArchive \
-archivePath "$XCODE_ARCHIVE_PATH" \
-exportOptionsPlist ../exportOptions.plist \
-exportPath "$XCODE_EXPORT_PATH"
- name: Upload IPA
uses: actions/upload-artifact@v4
with:
name: signed-ipa
path: apps/mobile-app/ios/build/AliasVault.ipa
retention-days: 14

View File

@@ -1,95 +0,0 @@
# This workflow will publish new Docker images to the GitHub Container Registry when a new release is published.
name: Publish Docker Images
on:
release:
types: [published]
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Convert repository name to lowercase
run: |
echo "REPO_LOWER=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}
- name: Build and push API image
uses: docker/build-push-action@v5
with:
context: .
file: src/AliasVault.Api/Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-api:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-api:${{ github.ref_name }}
- name: Build and push Client image
uses: docker/build-push-action@v5
with:
context: .
file: src/AliasVault.Client/Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-client:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-client:${{ github.ref_name }}
- name: Build and push Admin image
uses: docker/build-push-action@v5
with:
context: .
file: src/AliasVault.Admin/Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-admin:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-admin:${{ github.ref_name }}
- name: Build and push SMTP image
uses: docker/build-push-action@v5
with:
context: .
file: src/Services/AliasVault.SmtpService/Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-smtp:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-smtp:${{ github.ref_name }}
- name: Build and push TaskRunner image
uses: docker/build-push-action@v5
with:
context: .
file: src/Services/AliasVault.TaskRunner/Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-task-runner:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-task-runner:${{ github.ref_name }}
- name: Build and push Reverse Proxy image
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-reverse-proxy:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-reverse-proxy:${{ github.ref_name }}
- name: Build and push InstallCli image
uses: docker/build-push-action@v5
with:
context: .
file: src/Utilities/AliasVault.InstallCli/Dockerfile
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-installcli:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-installcli:${{ github.ref_name }}

230
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,230 @@
name: Release
on:
release:
types: [published]
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
upload-install-script:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Upload install.sh to release
uses: softprops/action-gh-release@v2
with:
files: install.sh
token: ${{ secrets.GITHUB_TOKEN }}
package-browser-extensions:
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/browser-extension
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/browser-extension/package-lock.json
- name: Install dependencies
run: npm ci
- name: Zip extensions
run: |
npm run zip:chrome
npm run zip:firefox
npm run zip:edge
- name: Upload extensions to release
uses: softprops/action-gh-release@v2
with:
files: |
apps/browser-extension/dist/aliasvault-browser-extension-*-chrome.zip
apps/browser-extension/dist/aliasvault-browser-extension-*-firefox.zip
apps/browser-extension/dist/aliasvault-browser-extension-*-edge.zip
apps/browser-extension/dist/aliasvault-browser-extension-*-sources.zip
token: ${{ secrets.GITHUB_TOKEN }}
build-android-release:
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/mobile-app
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/mobile-app/package-lock.json
- name: Install dependencies
run: npm ci
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Decode keystore
run: |
echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > android/app/keystore.jks
- name: Configure signing
run: |
cat >> android/gradle.properties <<EOF
ALIASVAULT_UPLOAD_STORE_FILE=keystore.jks
ALIASVAULT_UPLOAD_KEY_ALIAS=${{ secrets.ANDROID_KEY_ALIAS }}
ALIASVAULT_UPLOAD_STORE_PASSWORD=${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ALIASVAULT_UPLOAD_KEY_PASSWORD=${{ secrets.ANDROID_KEY_PASSWORD }}
EOF
- name: Build JS bundle (Android - Expo)
run: |
mkdir -p build
npx expo export \
--dev \
--output-dir ./build \
--platform android
- name: Build Signed APK & AAB
run: |
cd android
./gradlew bundleRelease
./gradlew assembleRelease
- name: Upload APK to release
uses: softprops/action-gh-release@v2
with:
files: android/app/build/outputs/apk/release/app-release.apk
token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload AAB to release
uses: softprops/action-gh-release@v2
with:
files: android/app/build/outputs/bundle/release/app-release.aab
token: ${{ secrets.GITHUB_TOKEN }}
build-and-push-docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Convert repository name to lowercase
run: |
echo "REPO_LOWER=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}
- name: Build and push Postgres image
uses: docker/build-push-action@v5
with:
context: .
file: apps/server/Databases/AliasServerDb/Dockerfile
platforms: linux/amd64,linux/arm64/v8
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-postgres:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-postgres:${{ github.ref_name }}
- name: Build and push API image
uses: docker/build-push-action@v5
with:
context: .
file: apps/server/AliasVault.Api/Dockerfile
platforms: linux/amd64,linux/arm64/v8
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-api:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-api:${{ github.ref_name }}
- name: Build and push Client image
uses: docker/build-push-action@v5
with:
context: .
file: apps/server/AliasVault.Client/Dockerfile
platforms: linux/amd64,linux/arm64/v8
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-client:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-client:${{ github.ref_name }}
- name: Build and push Admin image
uses: docker/build-push-action@v5
with:
context: .
file: apps/server/AliasVault.Admin/Dockerfile
platforms: linux/amd64,linux/arm64/v8
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-admin:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-admin:${{ github.ref_name }}
- name: Build and push Reverse Proxy image
uses: docker/build-push-action@v5
with:
context: .
file: apps/server/Dockerfile
platforms: linux/amd64,linux/arm64/v8
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-reverse-proxy:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-reverse-proxy:${{ github.ref_name }}
- name: Build and push SMTP image
uses: docker/build-push-action@v5
with:
context: .
file: apps/server/Services/AliasVault.SmtpService/Dockerfile
platforms: linux/amd64,linux/arm64/v8
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-smtp:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-smtp:${{ github.ref_name }}
- name: Build and push TaskRunner image
uses: docker/build-push-action@v5
with:
context: .
file: apps/server/Services/AliasVault.TaskRunner/Dockerfile
platforms: linux/amd64,linux/arm64/v8
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-task-runner:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-task-runner:${{ github.ref_name }}
- name: Build and push InstallCli image
uses: docker/build-push-action@v5
with:
context: .
file: apps/server/Utilities/AliasVault.InstallCli/Dockerfile
platforms: linux/amd64,linux/arm64/v8
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-installcli:latest,${{ env.REGISTRY }}/${{ env.REPO_LOWER }}-installcli:${{ github.ref_name }}

View File

@@ -1,11 +1,15 @@
# This workflow will perform a SonarCloud code analysis on every push to the main branch or when a pull request is opened, synchronized, or reopened.
# This workflow will perform a SonarCloud code analysis on every push to the main branch or
# when a pull request is opened, synchronized, or reopened. The "pull_request_target" event is
# used to ensure that the analysis is done on the source branch of the pull request which has
# access to the SonarCloud token secret.
name: SonarCloud code analysis
on:
push:
branches:
- main
pull_request:
pull_request_target:
types: [opened, synchronize, reopened]
jobs:
build:
name: Build and analyze
@@ -23,11 +27,13 @@ jobs:
uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'zulu' # Alternative distribution options are available.
distribution: 'zulu'
- uses: actions/checkout@v3
- name: Checkout code of PR branch
uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Cache SonarCloud packages
uses: actions/cache@v3
@@ -52,12 +58,18 @@ jobs:
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
- name: Build and analyze
working-directory: apps/server
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
shell: powershell
run: |
.\.sonar\scanner\dotnet-sonarscanner begin /k:"lanedirt_AliasVault" /o:"lanedirt" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" /d:sonar.coverage.exclusions="**Tests*.cs"
$scanner = "${{ github.workspace }}\.sonar\scanner\dotnet-sonarscanner"
if ('${{ github.event_name }}' -eq 'pull_request_target') {
& $scanner begin /k:"lanedirt_AliasVault" /o:"lanedirt" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.pullrequest.key=${{ github.event.pull_request.number }} /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" /d:sonar.coverage.exclusions="**Tests*.cs" /d:sonar.exclusions="**/__tests__/test-forms/*.html"
} else {
& $scanner begin /k:"lanedirt_AliasVault" /o:"lanedirt" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" /d:sonar.coverage.exclusions="**Tests*.cs" /d:sonar.exclusions="**/__tests__/test-forms/*.html"
}
dotnet build
dotnet test -c Release /p:CollectCoverage=true /p:CoverletOutput=coverage /p:CoverletOutputFormat=opencover --filter 'FullyQualifiedName!~AliasVault.E2ETests'
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
& $scanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"

43
.gitignore vendored
View File

@@ -196,12 +196,7 @@ PublishScripts/
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
@@ -272,6 +267,10 @@ ServiceFabricBackup/
*.sqlite-shm
*.sqlite-wal
# SQL files
*.sql
*.sql.gz
# Business Intelligence projects
*.rdl.data
*.bim.layout
@@ -372,20 +371,16 @@ FodyWeavers.xsd
.idea
*.licenseheader
# Junie JetBrains plugin
.junie
.output.txt
# Codebuddy Rider plugin
.codebuddy
# -------------------
# AliasVault specifics
# -------------------
# index.html is generated by the build process from index.template.html and therefore should be ignored
src/AliasVault.Client/wwwroot/index.html
# appsettings.Development.json is generated by the build process from appsettings.Development.template.json and therefore should be ignored
src/AliasVault.Client/wwwroot/appsettings.Development.json
# appsettings.Development.json is added manually if needed, it should not be committed.
src/Tests/AliasVault.E2ETests/appsettings.Development.json
# .env is generated by install.sh and therefore should be ignored
.env
@@ -396,6 +391,10 @@ install.sh.backup
# Draw.io diagram temp files
*.drawio.*
# Dist files
packages/**/dist/
*.tsbuildinfo
# Certificates
certificates/**/*.crt
certificates/**/*.key
@@ -407,3 +406,19 @@ certificates/letsencrypt/**
docs/_site
docs/vendor
docs/.bundle
# Database files
database/postgres
database/postgres-dev
# Temp files
temp
# Don't check in .js.map or .mjs.map files. These are generated by the build process in the shared
# libraries and copied to the application so they can be used for debugging, but we don't need
# to check them in as it's not needed for the applications to actually run.
**/*.js.map
**/*.mjs.map
# Android keystore file (for publishing to Google Play)
*.keystore

24
.vscode/AliasVault.code-workspace vendored Normal file
View File

@@ -0,0 +1,24 @@
{
"folders": [
{
"name": "AliasVault",
"path": "../"
},
{
"name": "server",
"path": "../apps/server"
},
{
"name": "browser-extension",
"path": "../apps/browser-extension"
},
{
"name": "mobile-app",
"path": "../apps/mobile-app"
},
{
"path": "../docs"
}
],
"settings": {}
}

19
.vscode/launch.json vendored
View File

@@ -1,19 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "C#: AliasVault.WebApp [http]",
"type": "dotnet",
"request": "launch",
"projectPath": "${workspaceFolder}/src/AliasVault.WebApp/AliasVault.WebApp.csproj",
"launchConfigurationId": "TargetFramework=;http"
},
{
"name": "C#: AliasVault.Api [http]",
"type": "dotnet",
"request": "launch",
"projectPath": "${workspaceFolder}/src/AliasVault.Api/AliasVault.Api.csproj",
"launchConfigurationId": "TargetFramework=;http"
}
]
}

9
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,9 @@
{
"typescript.tsc.autoDetect": "off",
"npm.autoDetect": "off",
"grunt.autoDetect": "off",
"gulp.autoDetect": "off",
"jake.autoDetect": "off",
"task.autoDetect": "off",
"dotnet.autoDetect": "off"
}

185
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,185 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build and watch API",
"type": "shell",
"command": "dotnet watch",
"args": [],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceFolder}/apps/server/AliasVault.Api"
}
},
{
"label": "Build and watch Client",
"type": "shell",
"command": "dotnet watch",
"args": [],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceFolder}/apps/server/AliasVault.Client"
}
},
{
"label": "Build and watch Admin",
"type": "shell",
"command": "dotnet watch",
"args": [],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceFolder}/apps/server/AliasVault.Admin"
}
},
{
"label": "Build and watch Client CSS",
"type": "shell",
"command": "npm",
"args": ["run", "build:client-css"],
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/apps/server/AliasVault.Client"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Build and watch Admin CSS",
"type": "shell",
"command": "npm",
"args": ["run", "build:admin-css"],
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/apps/server/AliasVault.Admin"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Build and watch Client (API + Client + CSS)",
"dependsOn": [
"Build and watch API",
"Build and watch Client",
"Build and watch Client CSS"
],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Run Unit Tests",
"type": "shell",
"command": "dotnet",
"args": ["test"],
"problemMatcher": "$msCompile",
"options": {
"cwd": "${workspaceFolder}/apps/server/Tests/AliasVault.UnitTests"
},
"group": {
"kind": "test",
"isDefault": true
}
},
{
"label": "Run Browser Extension (Chrome Dev)",
"type": "shell",
"command": "npm",
"args": ["run", "dev:chrome"],
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/apps/browser-extension"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Run debug iOS App (simulator)",
"type": "shell",
"command": "npx",
"args": ["expo", "run:ios"],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceFolder}/apps/mobile-app"
}
},
{
"label": "Run debug iOS App (device)",
"type": "shell",
"command": "npx",
"args": ["expo", "run:ios", "--device"],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceFolder}/apps/mobile-app"
}
},
{
"label": "Run release iOS App (device)",
"type": "shell",
"command": "npx",
"args": ["expo", "run:ios", "--device", "--configuration", "Release"],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceFolder}/apps/mobile-app"
}
},
{
"label": "Run release Android App (device)",
"type": "shell",
"command": "npx",
"args": ["expo", "run:android", "--device", "--variant", "release"],
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceFolder}/apps/mobile-app"
}
},
{
"label": "Build and watch Docs",
"type": "shell",
"command": "docker compose up",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceFolder}/docs"
}
},
]
}

128
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
contact@support.aliasvault.net.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -1,101 +1,26 @@
# Contributing
This document is a work-in-progress and will be expanded as time goes on. If you have any questions feel free to open a issue on GitHub.
# Contributing to the source code
We welcome contributions to AliasVault. Please read the guidelines on the official AliasVault docs website on how to get your local development environment setup and the general contribution guidelines:
Note: all instructions below are based on MacOS. If you are using a different operating system, you may need to adjust the commands accordingly.
https://docs.aliasvault.net/misc/dev/
## Getting Started
In order to contribute to this project follow these instructions to setup your local environment:
> Tip: if the URL above is not available, the raw doc pages can also be found in the `docs` folder in this repository.
### 1. Clone the repository
## Contributing to the documentation
The docs are built using Jekyll and automatically deploy to GitHub Pages via GitHub Actions. You can build the docs locally by running `docker compose up` in the `./docs` folder.
```bash
git clone https://github.com/lanedirt/AliasVault.git
cd AliasVault
```
### 2. Copy pre-commit hook script to .git/hooks directory
**Important**: All commits in this repo are required to contain a reference to a GitHub issue in the format of "your commit message (#123)" where "123" references the GitHub issue number.
The pre-commit hook script below will check the commit message before allowing the commit to proceed. If the commit message is invalid, the commit will be aborted.
```bash
# Copy the commit-msg hook script to the .git/hooks directory
cp .github/hooks/commit-msg .git/hooks/commit-msg
# Make the script executable
chmod +x .git/hooks/commit-msg
```
### 3. Install the latest version of .NET SDK 8
```bash
# Install .NET SDK 8
# On MacOS via brew:
brew install --cask dotnet-sdk
# On Windows via winget
winget install Microsoft.DotNet.SDK.8
```
### 4. Install dotnet CLI EF Tools
```bash
# Install dotnet EF tools globally
dotnet tool install --global dotnet-ef
# Include dotnet tools in your PATH
nano ~/.zshrc
# Add the following line to your .zshrc file
export PATH="$PATH:$HOME/.dotnet/tools"
# Start a new terminal and test that this command works:
dotnet ef
```
### 5. Run Tailwind CSS compiler while changing HTML files to update compiled CSS
```bash
npm run build:css
```
### 6. Install Playwright in order to locally run NUnit E2E (end-to-end) tests
```bash
# First install PowerShell for Mac (if you don't have it already)
brew install powershell/tap/powershell
# Install Playwright
dotnet tool install --global Microsoft.Playwright.CLI
# Run Playwright install script to download local browsers
# Note: make sure the E2E test project has been built at least once so the bin dir exists.
pwsh src/Tests/AliasVault.E2ETests/bin/Debug/net8.0/playwright.ps1 install
```
### 7. Create AliasVault.Client appsettings.Development.json
The WASM client app supports a development specific appsettings.json file. This appsettings file is optional but can override various options to make debugging easier.
The docs site is based on the open-source template called Just The Docs. Find more information about how this template works in the [official docs](https://just-the-docs.github.io/just-the-docs/).
1. Copy `wwwroot/appsettings.json` to `wwwroot/appsettings.Development.json`
To make changes to the AliasVault documentation please make a PR that directly edits the `docs` markdown files in this repository.
Here is an example file with the various options explained:
## Contributor License Agreement (CLA)
Thank you for your interest in contributing to AliasVault (“Project”).
```
{
"ApiUrl": "http://localhost:5092",
"PrivateEmailDomains": ["example.tld"],
"SupportEmail": "support@example.tld",
"UseDebugEncryptionKey": "true",
"CryptographyOverrideType" : "Argon2Id",
"CryptographyOverrideSettings" : "{\"DegreeOfParallelism\":1,\"MemorySize\":1024,\"Iterations\":1}"
}
```
By submitting code, documentation, or other contributions to this Project, you agree to the following:
- UseDebugEncryptionKey
- This setting will use a static encryption key so that if you login as a user you can refresh the page without needing to unlock the database again. This speeds up development when changing things in the WebApp WASM project. Note: the project needs to be run in "Development" mode for this setting to be used.
1. You are legally entitled to grant this license (e.g., you are the author, or have permission).
2. You grant the Project maintainers a perpetual, worldwide, non-exclusive, royalty-free license to use, modify, distribute, and sublicense your contribution as part of the Project and any derivative works.
3. You understand that your contribution will be made public and licensed under the same terms as the Project (e.g., AGPLv3), or any later version the maintainers may release.
4. You are not expected to provide support or warranties for your contribution.
- CryptographyOverrideType
- This setting allows overriding the default encryption type (Argon2id) with a different encryption type. This is useful for testing different encryption types without having to change code.
- CryptographyOverrideSettings
- This setting allows overriding the default encryption settings (Argon2id) with different settings. This is useful for testing different encryption settings without having to change code. The default Argon2id settings
are defined in the project as `Utilities/Cryptography/Cryptography.Client/Defaults.cs`. These default settings
are focused on security but NOT performance. Normally for key derivation purposes the slower/heavier the algorithm
the better protection against attackers. For production builds this is what we want, however in case of automated testing or debugging extra performance can be gained by tweaking (lowering) these settings.
> All contributors must accept the CLA as a condition of contributing. By opening a pull request, you agree to these terms. We may enforce this automatically via GitHub if needed.

View File

@@ -1,21 +1,660 @@
MIT License
# GNU AFFERO GENERAL PUBLIC LICENSE
Copyright (c) 2024 lanedirt
Version 3, 19 November 2007
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Copyright (C) 2007 Free Software Foundation, Inc.
<https://fsf.org/>
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains
free software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing
under this license.
The precise terms and conditions for copying, distribution and
modification follow.
## TERMS AND CONDITIONS
### 0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public
License.
"Copyright" also means copyright-like laws that apply to other kinds
of works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of
an exact copy. The resulting work is called a "modified version" of
the earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user
through a computer network, with no transfer of a copy, is not
conveying.
An interactive user interface displays "Appropriate Legal Notices" to
the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
### 1. Source Code.
The "source code" for a work means the preferred form of the work for
making modifications to it. "Object code" means any non-source form of
a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users can
regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same
work.
### 2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey,
without conditions so long as your license otherwise remains in force.
You may convey covered works to others for the sole purpose of having
them make modifications exclusively for you, or provide you with
facilities for running those works, provided that you comply with the
terms of this License in conveying all material for which you do not
control copyright. Those thus making or running the covered works for
you must do so exclusively on your behalf, under your direction and
control, on terms that prohibit them from making any copies of your
copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the
conditions stated below. Sublicensing is not allowed; section 10 makes
it unnecessary.
### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such
circumvention is effected by exercising rights under this License with
respect to the covered work, and you disclaim any intention to limit
operation or modification of the work as a means of enforcing, against
the work's users, your or third parties' legal rights to forbid
circumvention of technological measures.
### 4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
### 5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these
conditions:
- a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
- b) The work must carry prominent notices stating that it is
released under this License and any conditions added under
section 7. This requirement modifies the requirement in section 4
to "keep intact all notices".
- c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
- d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
### 6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of
sections 4 and 5, provided that you also convey the machine-readable
Corresponding Source under the terms of this License, in one of these
ways:
- a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
- b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the Corresponding
Source from a network server at no charge.
- c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
- d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
- e) Convey the object code using peer-to-peer transmission,
provided you inform other peers where the object code and
Corresponding Source of the work are being offered to the general
public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal,
family, or household purposes, or (2) anything designed or sold for
incorporation into a dwelling. In determining whether a product is a
consumer product, doubtful cases shall be resolved in favor of
coverage. For a particular product received by a particular user,
"normally used" refers to a typical or common use of that class of
product, regardless of the status of the particular user or of the way
in which the particular user actually uses, or expects or is expected
to use, the product. A product is a consumer product regardless of
whether the product has substantial commercial, industrial or
non-consumer uses, unless such uses represent the only significant
mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to
install and execute modified versions of a covered work in that User
Product from a modified version of its Corresponding Source. The
information must suffice to ensure that the continued functioning of
the modified object code is in no case prevented or interfered with
solely because modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or
updates for a work that has been modified or installed by the
recipient, or for the User Product in which it has been modified or
installed. Access to a network may be denied when the modification
itself materially and adversely affects the operation of the network
or violates the rules and protocols for communication across the
network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
### 7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders
of that material) supplement the terms of this License with terms:
- a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
- b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
- c) Prohibiting misrepresentation of the origin of that material,
or requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
- d) Limiting the use for publicity purposes of names of licensors
or authors of the material; or
- e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
- f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions
of it) with contractual assumptions of liability to the recipient,
for any liability that these contractual assumptions directly
impose on those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions; the
above requirements apply either way.
### 8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your license
from a particular copyright holder is reinstated (a) provisionally,
unless and until the copyright holder explicitly and finally
terminates your license, and (b) permanently, if the copyright holder
fails to notify you of the violation by some reasonable means prior to
60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
### 9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run
a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
### 10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
### 11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims owned
or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within the
scope of its coverage, prohibits the exercise of, or is conditioned on
the non-exercise of one or more of the rights that are specifically
granted under this License. You may not convey a covered work if you
are a party to an arrangement with a third party that is in the
business of distributing software, under which you make payment to the
third party based on the extent of your activity of conveying the
work, and under which the third party grants, to any of the parties
who would receive the covered work from you, a discriminatory patent
license (a) in connection with copies of the covered work conveyed by
you (or copies made from those copies), or (b) primarily for and in
connection with specific products or compilations that contain the
covered work, unless you entered into that arrangement, or that patent
license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
### 12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under
this License and any other pertinent obligations, then as a
consequence you may not convey it at all. For example, if you agree to
terms that obligate you to collect a royalty for further conveying
from those to whom you convey the Program, the only way you could
satisfy both those terms and this License would be to refrain entirely
from conveying the Program.
### 13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your
version supports such interaction) an opportunity to receive the
Corresponding Source of your version by providing access to the
Corresponding Source from a network server at no charge, through some
standard or customary means of facilitating copying of software. This
Corresponding Source shall include the Corresponding Source for any
work covered by version 3 of the GNU General Public License that is
incorporated pursuant to the following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
### 14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Affero General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever
published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions
of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
### 15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
### 16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
### 17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
## How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively state
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper
mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for
the specific requirements.
You should also get your employer (if you work as a programmer) or
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. For more information on this, and how to apply and follow
the GNU AGPL, see <https://www.gnu.org/licenses/>.

141
README.md
View File

@@ -1,82 +1,88 @@
<div align="center">
# <img src="https://github.com/user-attachments/assets/933c8b45-a190-4df6-913e-b7c64ad9938b" width="35" alt="AliasVault"> AliasVault
End-to-end encrypted password manager with built-in alias and email generation — giving you full control over your online identity and safeguarding your privacy. AliasVault: the privacy toolbox that you control.
<h1><img src="https://github.com/user-attachments/assets/933c8b45-a190-4df6-913e-b7c64ad9938b" width="40" /> AliasVault</h1>
[<img src="https://img.shields.io/github/v/release/lanedirt/AliasVault?include_prereleases&logo=github&label=Release">](https://github.com/lanedirt/AliasVault/releases)
[![.NET E2E Tests (with Sharding)](https://github.com/lanedirt/AliasVault/actions/workflows/dotnet-e2e-tests.yml/badge.svg)](https://github.com/lanedirt/AliasVault/actions/workflows/dotnet-e2e-tests.yml)
[<img src="https://img.shields.io/sonar/quality_gate/lanedirt_AliasVault?server=https%3A%2F%2Fsonarcloud.io&label=Sonarcloud&logo=sonarcloud">](https://sonarcloud.io/summary/new_code?id=lanedirt_AliasVault)
[<img alt="Discord" src="https://img.shields.io/discord/1309300619026235422?logo=discord&logoColor=%237289da&label=Discord&color=%237289da">](https://discord.gg/DsaXMTEtpF)
<p align="center">
<a href="https://app.aliasvault.net">Live demo 🔥</a> • <a href="https://aliasvault.net?utm_source=gh-readme">Website 🌐</a> • <a href="https://docs.aliasvault.net?utm_source=gh-readme">Documentation 📚</a> • <a href="#installation">Installation ⚙️</a>
</p>
<a href="https://app.aliasvault.net">Try the cloud version 🔥</a> | <a href="https://aliasvault.net?utm_source=gh-readme">Website </a> | <a href="https://docs.aliasvault.net?utm_source=gh-readme">Documentation </a> | <a href="#self-hosting">Self-host instructions</a>
<p align="center">
<strong>Open-source password and alias manager</strong>
</p>
## About
AliasVault helps protect your privacy online by generating a unique password, identity, and email alias for every service you use. Everything is end-to-end encrypted and under your control — whether in the cloud or self-hosted.
[<img src="https://img.shields.io/github/v/release/lanedirt/AliasVault?include_prereleases&logo=github">](https://github.com/lanedirt/AliasVault/releases)
[<img src="https://img.shields.io/github/actions/workflow/status/lanedirt/AliasVault/docker-compose-build.yml?label=docker-compose%20build">](https://github.com/lanedirt/AliasVault/actions/workflows/docker-compose-build.yml)
[<img src="https://img.shields.io/github/actions/workflow/status/lanedirt/AliasVault/dotnet-unit-tests.yml?label=unit tests">](https://github.com/lanedirt/AliasVault/actions/workflows/dotnet-build-run-tests.yml)
[<img src="https://img.shields.io/github/actions/workflow/status/lanedirt/AliasVault/dotnet-integration-tests.yml?label=integration tests">](https://github.com/lanedirt/AliasVault/actions/workflows/dotnet-build-run-tests.yml)
[<img src="https://img.shields.io/github/actions/workflow/status/lanedirt/AliasVault/dotnet-e2e-client-tests.yml?label=e2e tests">](https://github.com/lanedirt/AliasVault/actions/workflows/dotnet-e2e-client-tests.yml)
[<img src="https://img.shields.io/sonar/coverage/lanedirt_AliasVault?server=https%3A%2F%2Fsonarcloud.io&label=test code coverage">](https://sonarcloud.io/summary/new_code?id=lanedirt_AliasVault)
[<img src="https://img.shields.io/sonar/quality_gate/lanedirt_AliasVault?server=https%3A%2F%2Fsonarcloud.io&label=sonarcloud&logo=sonarcloud">](https://sonarcloud.io/summary/new_code?id=lanedirt_AliasVault)
</div>
Built on 15 years of experience, AliasVault is open-source, self-hostable and community-driven. Its the response to a web that tracks everything: a way to take back control of your digital privacy and help you stay secure online.
<div align="center">
Leendert de Borst (@lanedirt), Creator of AliasVault
[<img alt="Discord" src="https://img.shields.io/discord/1309300619026235422?logo=discord&logoColor=%237289da&label=join%20discord%20chat&color=%237289da">](https://discord.gg/DsaXMTEtpF)
## Screenshots
</div>
<table>
<tr>
<th align="center">Responsive web app</th>
<th align="center">Browser extensions</th>
</tr>
<tr>
<td align="center">
<img src="https://github.com/user-attachments/assets/fa5bf64a-704d-4f09-b4e0-0310ab662204" alt="Responsive web app" />
</td>
<td align="center">
<img src="https://github.com/user-attachments/assets/b5218609-217b-4c8d-8d5d-8c71e19bf057"alt="Browser extensions" />
</td>
</tr>
<tr>
<th align="center">Native iOS & Android apps</th>
<th align="center">& much more</th>
</tr>
<tr>
<td align="center">
<img src="https://github.com/user-attachments/assets/5d09ad78-d145-48a1-b8da-c5a1dc708886" alt="Native iOS & Android Apps" />
</td>
<td align="center">
<img src="https://github.com/user-attachments/assets/34fe650d-f08d-4c92-92e0-4e750b7a662a" alt="Lots of features" />
</td>
</tr>
</table>
AliasVault is an end-to-end encrypted password and alias manager that protects your privacy by creating alternative identities, passwords and email addresses for every website you use. The core of AliasVault is built with C# ASP.NET Blazor WASM technology. AliasVault can be self-hosted on your own server with Docker.
## Cloud-hosted
Use the official cloud version of AliasVault at [app.aliasvault.net](https://app.aliasvault.net). This fully supported platform is always up to date with our latest release.
### What makes AliasVault unique:
- **Zero-knowledge architecture**: All data is end-to-end encrypted on the client and stored in encrypted state on the server. Your master password never leaves your device and the server never has access to your data.
- **Built-in email server**: AliasVault includes its own email server that allows you to generate virtual email addresses for each alias. Emails sent to these addresses are instantly visible in the AliasVault app.
- **Alias generation**: Generate aliases and assign them to a website, allowing you to use different email addresses and usernames for each website. Keeping your online identities separate and secure, making it harder for bad actors to link your accounts.
- **Open-source**: The source code is available on GitHub and can be self-hosted on your own server.
AliasVault is available on: [Web](https://app.aliasvault.net) | [iOS](https://apps.apple.com/app/id6745490915) | [Chrome](https://chromewebstore.google.com/detail/aliasvault/bmoggiinmnodjphdjnmpcnlleamkfedj) | [Firefox](https://addons.mozilla.org/en-US/firefox/addon/aliasvault/) | [Edge](https://microsoftedge.microsoft.com/addons/detail/aliasvault/kabaanafahnjkfkplbnllebdmppdemfo) | [Safari](https://apps.apple.com/app/id6743163173)
> Note: AliasVault is currently in active development and some features may not yet have been (fully) implemented. If you run into any issues, please create an issue on GitHub.
[<img width="700" alt="Screenshot of AliasVault" src="docs/assets/img/screenshot.png">](https://app.aliasvault.net)
## Live demo
A live demo of the app is available at the official website at [app.aliasvault.net](https://app.aliasvault.net) (up-to-date with `main` branch). You can create a free account to try it out yourself.
## Self-hosting
For full control over your own data you can self-host and install AliasVault on your own servers.
<img width="700" alt="Screenshot of AliasVault" src="docs/assets/img/screenshot.png">
## Installation
To install AliasVault, the easiest method is to use the provided install script. This will download the pre-built Docker images and start the containers.
### 1. Install using install script
### Install using install script
This method uses pre-built Docker images and works on minimal hardware specifications:
- Linux VM with root access (Ubuntu or RHEL based distros recommended)
- Linux VM with root access (Ubuntu/AlmaLinux recommended) or Raspberry Pi
- 1 vCPU
- 512MB RAM
- 1GB RAM
- 16GB disk space
- Docker installed
```bash
# Download install script
curl -o install.sh https://raw.githubusercontent.com/lanedirt/AliasVault/main/install.sh
# Download install script from latest stable release
curl -L -o install.sh https://github.com/lanedirt/AliasVault/releases/latest/download/install.sh
# Make install script executable and run it. This will create the .env file, pull the Docker images, and start the AliasVault containers.
chmod +x install.sh
./install.sh install
```
### 2. Post-Installation
The install script will output the URL where the app is available. By default this is:
- Client: https://localhost
- Admin portal: https://localhost/admin
> Note: If you want to change the default AliasVault ports you can do so in the `.env` file.
## Detailed documentation
For more detailed information about the installation process and other topics, please see the official documentation website:
## Technical documentation
For more information about the installation process, manual setup instructions and other topics, please see the official documentation website:
- [Documentation website (docs.aliasvault.net) 📚](https://docs.aliasvault.net)
Here you can also find step-by-step instructions on how to install AliasVault to e.g. Azure, AWS and other popular cloud providers.
## Security Architecture
<a href="https://docs.aliasvault.net/architecture"><img alt="AliasVault Security Architecture Diagram" src="docs/assets/diagrams/security-architecture/aliasvault-security-architecture-thumb.jpg" width="343"></a>
@@ -90,21 +96,36 @@ For detailed information about our encryption implementation and security archit
- [SECURITY.md](SECURITY.md)
- [Security Architecture Diagram](https://docs.aliasvault.net/architecture)
## Features & Roadmap
AliasVault is under active development, with a strong focus on usability, security, and cross-platform support.
The main focus is on ensuring robust usability for everyday tasks, including comprehensive autofill capabilities across all platforms.
## Tech stack / credits
The following technologies, frameworks and libraries are used in this project:
🛠️ Incremental releases are published every 23 weeks, with a strong emphasis on real-world testing and user feedback.
During this phase, AliasVault can safely be used in production as it maintains strict data integrity and automatic migration guarantees.
Core features that are being worked on:
- [x] Core password & alias management
- [x] Full end-to-end encryption
- [x] Built-in email server for aliases
- [x] Easy self-hosted installer
- [x] Browser extensions with autofill feature (Chrome, Firefox, Edge, Safari, Brave)
- [x] Built-in TOTP authenticator
- [x] Import passwords from traditional password managers
- [x] iOS native app
- [x] Android native app
- [ ] Data model and usability improvements (more flexible aliases and credential types, folder support, editing in browser extension, bulk selecting etc.)
- [ ] Support for FIDO2/WebAuthn hardware keys and passkeys
- [ ] Adding support for family/team sharing (organization features)
👉 [View the full AliasVault roadmap here](https://github.com/lanedirt/AliasVault/issues/731)
### Got feedback or ideas?
Feel free to open an issue or join our [Discord](https://discord.gg/DsaXMTEtpF)! Contributions are warmly welcomed—whether in feature development, testing, or spreading the word. Get in touch on Discord if you're interested in contributing.
### Support the mission
Your donation helps me dedicate more time and resources to improving AliasVault, making the internet safer for everyone!
<a href="https://www.buymeacoffee.com/lanedirt" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
- [C#](https://docs.microsoft.com/en-us/dotnet/csharp/) - A simple, modern, object-oriented, and type-safe programming language.
- [ASP.NET Core](https://dotnet.microsoft.com/apps/aspnet) - An open-source framework for building modern, cloud-based, internet-connected applications.
- [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) - A lightweight, extensible, open-source and cross-platform version of the popular Entity Framework data access technology.
- [Blazor WASM](https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor) - A framework for building interactive web UIs using C# instead of JavaScript. It's a single-page app framework that runs in the browser via WebAssembly.
- [Playwright](https://playwright.dev/) - A Node.js library to automate Chromium, Firefox and WebKit with a single API. Used for end-to-end testing.
- [Docker](https://www.docker.com/) - A platform for building, sharing, and running containerized applications.
- [SQLite](https://www.sqlite.org/index.html) - A C-language library that implements a small, fast, self-contained, high-reliability, full-featured, SQL database engine.
- [Tailwind CSS](https://tailwindcss.com/) - A utility-first CSS framework for rapidly building custom designs.
- [Flowbite](https://flowbite.com/) - A free and open-source UI component library based on Tailwind CSS.
- [Konscious.Security.Cryptography](https://github.com/kmaragon/Konscious.Security.Cryptography) - A .NET library that implements Argon2id, a memory-hard password hashing algorithm.
- [SRP.net](https://github.com/secure-remote-password/srp.net) - SRP6a Secure Remote Password protocol for secure password authentication.
- [SmtpServer](https://github.com/cosullivan/SmtpServer) - A SMTP server library for .NET that is used for the virtual email address feature.
- [MimeKit](https://github.com/jstedfast/MimeKit) - A .NET MIME creation and parser library used for the virtual email address feature.

View File

@@ -0,0 +1,28 @@
# Child EditorConfig file that enforces 2 space indent for Typescript projects
root = false
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
# TypeScript and JavaScript files
[*.{ts,tsx,js,jsx}]
indent_style = space
indent_size = 2
# JSON files
[*.json]
indent_style = space
indent_size = 2
# YAML files
[*.{yml,yaml}]
indent_style = space
indent_size = 2
# Markdown files
[*.md]
trim_trailing_whitespace = false

27
apps/browser-extension/.gitignore vendored Normal file
View File

@@ -0,0 +1,27 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.output
dist
stats.html
stats-*.json
.wxt
web-ext.config.ts
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,25 @@
This folder contains the source code for the browser extensions for AliasVault.
The browser extension is built using WXT and React:
- [WXT](https://wxt.dev/) is a build tool for browser extensions.
- [React](https://reactjs.org/) is a JavaScript library for building user interfaces.
To build the browser extension, run the following command in this directory:
### Build the browser extension
```bash
npm install
# Build the Chrome extension (saves in dist/chrome-mv3)
npm run zip:chrome
# Build the Firefox extension (creates two zip files in dist)
npm run zip:firefox
# Build the Edge extension (saves in dist/edge-mv3)
npm run zip:edge
# Build the Safari extension (saves in dist/safari-mv2 which is referenced by the dist/safari-xcode/AliasVault.xcodeproj project)
npm run build:safari
# Open the dist/safari-xcode/AliasVault.xcodeproj project in MacOS Xcode and run the project. This will install the extension to your Safari browser locally.
```

View File

@@ -0,0 +1,125 @@
import js from "@eslint/js";
import tsParser from "@typescript-eslint/parser";
import tsPlugin from "@typescript-eslint/eslint-plugin";
import reactPlugin from "eslint-plugin-react";
import reactHooksPlugin from "eslint-plugin-react-hooks";
import importPlugin from "eslint-plugin-import";
import jsdocPlugin from "eslint-plugin-jsdoc";
import globals from 'globals';
export default [
{
ignores: [
"dist/**",
"node_modules/**",
"src/utils/shared/**",
]
},
js.configs.recommended,
{
files: ["src/**/*.{ts,tsx}"],
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaFeatures: { jsx: true },
ecmaVersion: "latest",
sourceType: "module",
project: "./tsconfig.json",
tsconfigRootDir: ".",
},
},
plugins: {
"@typescript-eslint": tsPlugin,
"react": reactPlugin,
"react-hooks": reactHooksPlugin,
"import": importPlugin,
"jsdoc": jsdocPlugin,
},
rules: {
...tsPlugin.configs.recommended.rules,
...reactPlugin.configs.recommended.rules,
...reactHooksPlugin.configs.recommended.rules,
"curly": ["error", "all"],
"brace-style": ["error", "1tbs", { "allowSingleLine": false }],
"@typescript-eslint/await-thenable": "error",
"react/react-in-jsx-scope": "off",
"react/no-unused-prop-types": "error",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-unused-vars": ["error", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true,
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_"
}],
"indent": ["error", 2, {
"SwitchCase": 1,
"VariableDeclarator": 1,
"outerIIFEBody": 1,
"MemberExpression": 1,
"FunctionDeclaration": { "parameters": 1, "body": 1 },
"FunctionExpression": { "parameters": 1, "body": 1 },
"CallExpression": { "arguments": 1 },
"ArrayExpression": 1,
"ObjectExpression": 1,
"ImportDeclaration": 1,
"flatTernaryExpressions": false,
"ignoreComments": false
}],
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1, "maxBOF": 0 }],
"no-console": ["error", { allow: ["warn", "error", "info", "debug"] }],
"jsdoc/require-jsdoc": ["error", {
"require": {
"FunctionDeclaration": true,
"MethodDefinition": true,
"ClassDeclaration": true,
"ArrowFunctionExpression": true,
"FunctionExpression": true
}
}],
"jsdoc/require-description": ["error", {
"contexts": [
"FunctionDeclaration",
"MethodDefinition",
"ClassDeclaration",
"ArrowFunctionExpression",
"FunctionExpression"
]
}],
"spaced-comment": ["error", "always"],
"multiline-comment-style": ["error", "starred-block"],
"@typescript-eslint/explicit-member-accessibility": ["error"],
"@typescript-eslint/explicit-function-return-type": ["error"],
"@typescript-eslint/typedef": ["error"],
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "interface",
"format": ["PascalCase"],
"prefix": ["I"]
},
{
"selector": "class",
"format": ["PascalCase"]
}
],
"react-hooks/exhaustive-deps": "warn",
"react/jsx-no-constructed-context-values": "error",
},
settings: {
react: {
version: "detect",
},
},
},
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
NodeJS: true,
chrome: 'readonly',
}
}
}
];

13546
apps/browser-extension/package-lock.json generated Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
{
"name": "aliasvault-browser-extension",
"description": "AliasVault Browser Extension",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev:chrome": "wxt -b chrome",
"dev:firefox": "wxt -b firefox",
"dev:edge": "wxt -b edge",
"build:chrome": "wxt build -b chrome",
"build:firefox": "wxt build -b firefox",
"build:edge": "wxt build -b edge",
"build:safari": "wxt build -b safari",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"lint": "eslint src",
"lint:custom": "eslint",
"lint:fix": "eslint src --fix",
"zip": "wxt zip",
"zip:chrome": "wxt zip -b chrome",
"zip:firefox": "wxt zip -b firefox",
"zip:edge": "wxt zip -b edge",
"compile": "tsc --noEmit",
"postinstall": "wxt prepare"
},
"dependencies": {
"argon2-browser": "^1.18.0",
"buffer": "^6.0.3",
"globals": "^16.0.0",
"otpauth": "^9.3.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "^7.5.2",
"secure-remote-password": "github:LinusU/secure-remote-password#73e5f732b6ca0cdbdc19da1a0c5f48cdbad2cbf0",
"sql.js": "^1.12.0",
"vitest": "^3.0.8",
"webext-bridge": "^6.0.1",
"yup": "^1.6.1"
},
"devDependencies": {
"@types/chrome": "^0.0.280",
"@types/jsdom": "^21.1.7",
"@types/node": "^22.13.10",
"@types/react": "^19.0.7",
"@types/react-dom": "^19.0.3",
"@types/sql.js": "^1.4.9",
"@types/yup": "^0.29.14",
"@typescript-eslint/eslint-plugin": "^8.21.0",
"@typescript-eslint/parser": "^8.21.0",
"@vitest/coverage-v8": "^3.0.8",
"@wxt-dev/module-react": "^1.1.2",
"autoprefixer": "^10.4.20",
"eslint": "^9.19.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "^50.6.3",
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.1.0",
"jsdom": "^26.0.0",
"postcss": "^8.5.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.6.3",
"vite-plugin-static-copy": "^2.2.0",
"wxt": "^0.20.6"
}
}

View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 174 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -0,0 +1,62 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.Safari.web-extension</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).SafariWebExtensionHandler</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,35 @@
import SafariServices
import os.log
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
func beginRequest(with context: NSExtensionContext) {
let request = context.inputItems.first as? NSExtensionItem
let profile: UUID?
if #available(iOS 17.0, macOS 14.0, *) {
profile = request?.userInfo?[SFExtensionProfileKey] as? UUID
} else {
profile = request?.userInfo?["profile"] as? UUID
}
let message: Any?
if #available(iOS 15.0, macOS 11.0, *) {
message = request?.userInfo?[SFExtensionMessageKey]
} else {
message = request?.userInfo?["message"]
}
os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@ (profile: %@)", String(describing: message), profile?.uuidString ?? "none")
let response = NSExtensionItem()
if #available(iOS 15.0, macOS 11.0, *) {
response.userInfo = [ SFExtensionMessageKey: [ "echo": message ] ]
} else {
response.userInfo = [ "message": [ "echo": message ] ]
}
context.completeRequest(returningItems: [ response ], completionHandler: nil)
}
}

View File

@@ -0,0 +1,619 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
CE0CAFA72D81A9F7006174AB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CAFA62D81A9F7006174AB /* AppDelegate.swift */; };
CE0CAFAB2D81A9F7006174AB /* Base in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFAA2D81A9F7006174AB /* Base */; };
CE0CAFAD2D81A9F7006174AB /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFAC2D81A9F7006174AB /* Icon.png */; };
CE0CAFAF2D81A9F7006174AB /* Style.css in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFAE2D81A9F7006174AB /* Style.css */; };
CE0CAFB12D81A9F7006174AB /* Script.js in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFB02D81A9F7006174AB /* Script.js */; };
CE0CAFB32D81A9F7006174AB /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CAFB22D81A9F7006174AB /* ViewController.swift */; };
CE0CAFB62D81A9F7006174AB /* Base in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFB52D81A9F7006174AB /* Base */; };
CE0CAFB82D81A9F8006174AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFB72D81A9F8006174AB /* Assets.xcassets */; };
CE0CAFC12D81A9F8006174AB /* AliasVault Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = CE0CAFC02D81A9F8006174AB /* AliasVault Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
CE0CAFC62D81A9F8006174AB /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CAFC52D81A9F8006174AB /* SafariWebExtensionHandler.swift */; };
CE0CAFDB2D81A9F8006174AB /* background.js in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFD32D81A9F8006174AB /* background.js */; };
CE0CAFDC2D81A9F8006174AB /* popup.html in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFD42D81A9F8006174AB /* popup.html */; };
CE0CAFDD2D81A9F8006174AB /* chunks in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFD52D81A9F8006174AB /* chunks */; };
CE0CAFDE2D81A9F8006174AB /* content-scripts in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFD62D81A9F8006174AB /* content-scripts */; };
CE0CAFDF2D81A9F8006174AB /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFD72D81A9F8006174AB /* manifest.json */; };
CE0CAFE02D81A9F8006174AB /* icon in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFD82D81A9F8006174AB /* icon */; };
CE0CAFE12D81A9F8006174AB /* assets in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFD92D81A9F8006174AB /* assets */; };
CE0CAFE22D81A9F8006174AB /* src in Resources */ = {isa = PBXBuildFile; fileRef = CE0CAFDA2D81A9F8006174AB /* src */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
CE0CAFC22D81A9F8006174AB /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = CE0CAF9B2D81A9F7006174AB /* Project object */;
proxyType = 1;
remoteGlobalIDString = CE0CAFBF2D81A9F8006174AB;
remoteInfo = "AliasVault Extension";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
CE0CAFCE2D81A9F8006174AB /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
CE0CAFC12D81A9F8006174AB /* AliasVault Extension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
CE0CAFA32D81A9F7006174AB /* AliasVault.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AliasVault.app; sourceTree = BUILT_PRODUCTS_DIR; };
CE0CAFA62D81A9F7006174AB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
CE0CAFAA2D81A9F7006174AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = Base; path = ../Base.lproj/Main.html; sourceTree = "<group>"; };
CE0CAFAC2D81A9F7006174AB /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; };
CE0CAFAE2D81A9F7006174AB /* Style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = Style.css; sourceTree = "<group>"; };
CE0CAFB02D81A9F7006174AB /* Script.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Script.js; sourceTree = "<group>"; };
CE0CAFB22D81A9F7006174AB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
CE0CAFB52D81A9F7006174AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
CE0CAFB72D81A9F8006174AB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
CE0CAFB92D81A9F8006174AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CE0CAFBA2D81A9F8006174AB /* AliasVault.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AliasVault.entitlements; sourceTree = "<group>"; };
CE0CAFBB2D81A9F8006174AB /* AliasVault.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AliasVault.entitlements; sourceTree = "<group>"; };
CE0CAFC02D81A9F8006174AB /* AliasVault Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "AliasVault Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
CE0CAFC52D81A9F8006174AB /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = "<group>"; };
CE0CAFC72D81A9F8006174AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CE0CAFC82D81A9F8006174AB /* AliasVault_Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AliasVault_Extension.entitlements; sourceTree = "<group>"; };
CE0CAFD32D81A9F8006174AB /* background.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = background.js; path = "../../../dist/safari-mv2/background.js"; sourceTree = "<group>"; };
CE0CAFD42D81A9F8006174AB /* popup.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = popup.html; path = "../../../dist/safari-mv2/popup.html"; sourceTree = "<group>"; };
CE0CAFD52D81A9F8006174AB /* chunks */ = {isa = PBXFileReference; lastKnownFileType = folder; name = chunks; path = "../../../dist/safari-mv2/chunks"; sourceTree = "<group>"; };
CE0CAFD62D81A9F8006174AB /* content-scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "content-scripts"; path = "../../../dist/safari-mv2/content-scripts"; sourceTree = "<group>"; };
CE0CAFD72D81A9F8006174AB /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = manifest.json; path = "../../../dist/safari-mv2/manifest.json"; sourceTree = "<group>"; };
CE0CAFD82D81A9F8006174AB /* icon */ = {isa = PBXFileReference; lastKnownFileType = folder; name = icon; path = "../../../dist/safari-mv2/icon"; sourceTree = "<group>"; };
CE0CAFD92D81A9F8006174AB /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = assets; path = "../../../dist/safari-mv2/assets"; sourceTree = "<group>"; };
CE0CAFDA2D81A9F8006174AB /* src */ = {isa = PBXFileReference; lastKnownFileType = folder; name = src; path = "../../../dist/safari-mv2/src"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
CE0CAFA02D81A9F7006174AB /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
CE0CAFBD2D81A9F8006174AB /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
CE0CAF9A2D81A9F7006174AB = {
isa = PBXGroup;
children = (
CE0CAFA52D81A9F7006174AB /* AliasVault */,
CE0CAFC42D81A9F8006174AB /* AliasVault Extension */,
CE0CAFA42D81A9F7006174AB /* Products */,
);
sourceTree = "<group>";
};
CE0CAFA42D81A9F7006174AB /* Products */ = {
isa = PBXGroup;
children = (
CE0CAFA32D81A9F7006174AB /* AliasVault.app */,
CE0CAFC02D81A9F8006174AB /* AliasVault Extension.appex */,
);
name = Products;
sourceTree = "<group>";
};
CE0CAFA52D81A9F7006174AB /* AliasVault */ = {
isa = PBXGroup;
children = (
CE0CAFA62D81A9F7006174AB /* AppDelegate.swift */,
CE0CAFB22D81A9F7006174AB /* ViewController.swift */,
CE0CAFB42D81A9F7006174AB /* Main.storyboard */,
CE0CAFB72D81A9F8006174AB /* Assets.xcassets */,
CE0CAFB92D81A9F8006174AB /* Info.plist */,
CE0CAFBA2D81A9F8006174AB /* AliasVault.entitlements */,
CE0CAFBB2D81A9F8006174AB /* AliasVault.entitlements */,
CE0CAFA82D81A9F7006174AB /* Resources */,
);
path = AliasVault;
sourceTree = "<group>";
};
CE0CAFA82D81A9F7006174AB /* Resources */ = {
isa = PBXGroup;
children = (
CE0CAFA92D81A9F7006174AB /* Main.html */,
CE0CAFAC2D81A9F7006174AB /* Icon.png */,
CE0CAFAE2D81A9F7006174AB /* Style.css */,
CE0CAFB02D81A9F7006174AB /* Script.js */,
);
path = Resources;
sourceTree = "<group>";
};
CE0CAFC42D81A9F8006174AB /* AliasVault Extension */ = {
isa = PBXGroup;
children = (
CE0CAFD22D81A9F8006174AB /* Resources */,
CE0CAFC52D81A9F8006174AB /* SafariWebExtensionHandler.swift */,
CE0CAFC72D81A9F8006174AB /* Info.plist */,
CE0CAFC82D81A9F8006174AB /* AliasVault_Extension.entitlements */,
);
path = "AliasVault Extension";
sourceTree = "<group>";
};
CE0CAFD22D81A9F8006174AB /* Resources */ = {
isa = PBXGroup;
children = (
CE0CAFD32D81A9F8006174AB /* background.js */,
CE0CAFD42D81A9F8006174AB /* popup.html */,
CE0CAFD52D81A9F8006174AB /* chunks */,
CE0CAFD62D81A9F8006174AB /* content-scripts */,
CE0CAFD72D81A9F8006174AB /* manifest.json */,
CE0CAFD82D81A9F8006174AB /* icon */,
CE0CAFD92D81A9F8006174AB /* assets */,
CE0CAFDA2D81A9F8006174AB /* src */,
);
name = Resources;
path = "AliasVault Extension";
sourceTree = SOURCE_ROOT;
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
CE0CAFA22D81A9F7006174AB /* AliasVault */ = {
isa = PBXNativeTarget;
buildConfigurationList = CE0CAFCF2D81A9F8006174AB /* Build configuration list for PBXNativeTarget "AliasVault" */;
buildPhases = (
CE0CAF9F2D81A9F7006174AB /* Sources */,
CE0CAFA02D81A9F7006174AB /* Frameworks */,
CE0CAFA12D81A9F7006174AB /* Resources */,
CE0CAFCE2D81A9F8006174AB /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
CE0CAFC32D81A9F8006174AB /* PBXTargetDependency */,
);
name = AliasVault;
productName = AliasVault;
productReference = CE0CAFA32D81A9F7006174AB /* AliasVault.app */;
productType = "com.apple.product-type.application";
};
CE0CAFBF2D81A9F8006174AB /* AliasVault Extension */ = {
isa = PBXNativeTarget;
buildConfigurationList = CE0CAFCB2D81A9F8006174AB /* Build configuration list for PBXNativeTarget "AliasVault Extension" */;
buildPhases = (
CE0CAFBC2D81A9F8006174AB /* Sources */,
CE0CAFBD2D81A9F8006174AB /* Frameworks */,
CE0CAFBE2D81A9F8006174AB /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "AliasVault Extension";
productName = "AliasVault Extension";
productReference = CE0CAFC02D81A9F8006174AB /* AliasVault Extension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
CE0CAF9B2D81A9F7006174AB /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1540;
LastUpgradeCheck = 1540;
TargetAttributes = {
CE0CAFA22D81A9F7006174AB = {
CreatedOnToolsVersion = 15.4;
};
CE0CAFBF2D81A9F8006174AB = {
CreatedOnToolsVersion = 15.4;
};
};
};
buildConfigurationList = CE0CAF9E2D81A9F7006174AB /* Build configuration list for PBXProject "AliasVault" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = CE0CAF9A2D81A9F7006174AB;
productRefGroup = CE0CAFA42D81A9F7006174AB /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
CE0CAFA22D81A9F7006174AB /* AliasVault */,
CE0CAFBF2D81A9F8006174AB /* AliasVault Extension */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
CE0CAFA12D81A9F7006174AB /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CE0CAFAD2D81A9F7006174AB /* Icon.png in Resources */,
CE0CAFB12D81A9F7006174AB /* Script.js in Resources */,
CE0CAFAB2D81A9F7006174AB /* Base in Resources */,
CE0CAFAF2D81A9F7006174AB /* Style.css in Resources */,
CE0CAFB82D81A9F8006174AB /* Assets.xcassets in Resources */,
CE0CAFB62D81A9F7006174AB /* Base in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
CE0CAFBE2D81A9F8006174AB /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CE0CAFDD2D81A9F8006174AB /* chunks in Resources */,
CE0CAFE02D81A9F8006174AB /* icon in Resources */,
CE0CAFE12D81A9F8006174AB /* assets in Resources */,
CE0CAFE22D81A9F8006174AB /* src in Resources */,
CE0CAFDB2D81A9F8006174AB /* background.js in Resources */,
CE0CAFDF2D81A9F8006174AB /* manifest.json in Resources */,
CE0CAFDC2D81A9F8006174AB /* popup.html in Resources */,
CE0CAFDE2D81A9F8006174AB /* content-scripts in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
CE0CAF9F2D81A9F7006174AB /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CE0CAFB32D81A9F7006174AB /* ViewController.swift in Sources */,
CE0CAFA72D81A9F7006174AB /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
CE0CAFBC2D81A9F8006174AB /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CE0CAFC62D81A9F8006174AB /* SafariWebExtensionHandler.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
CE0CAFC32D81A9F8006174AB /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = CE0CAFBF2D81A9F8006174AB /* AliasVault Extension */;
targetProxy = CE0CAFC22D81A9F8006174AB /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
CE0CAFA92D81A9F7006174AB /* Main.html */ = {
isa = PBXVariantGroup;
children = (
CE0CAFAA2D81A9F7006174AB /* Base */,
);
name = Main.html;
sourceTree = "<group>";
};
CE0CAFB42D81A9F7006174AB /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
CE0CAFB52D81A9F7006174AB /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
CE0CAFC92D81A9F8006174AB /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 14.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
CE0CAFCA2D81A9F8006174AB /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 14.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
};
name = Release;
};
CE0CAFCC2D81A9F8006174AB /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "AliasVault Extension/AliasVault_Extension.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 18;
DEVELOPMENT_TEAM = 8PHW4HN3F7;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "AliasVault Extension/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "AliasVault Extension";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 0.18.0;
OTHER_LDFLAGS = (
"-framework",
SafariServices,
);
PRODUCT_BUNDLE_IDENTIFIER = net.aliasvault.safari.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
CE0CAFCD2D81A9F8006174AB /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "AliasVault Extension/AliasVault_Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 18;
DEVELOPMENT_TEAM = 8PHW4HN3F7;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "AliasVault Extension/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "AliasVault Extension";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 0.18.0;
OTHER_LDFLAGS = (
"-framework",
SafariServices,
);
PRODUCT_BUNDLE_IDENTIFIER = net.aliasvault.safari.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Release;
};
CE0CAFD02D81A9F8006174AB /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = AliasVault/AliasVault.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 18;
DEVELOPMENT_TEAM = 8PHW4HN3F7;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = AliasVault/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AliasVault;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
INFOPLIST_KEY_NSMainStoryboardFile = Main;
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 0.18.0;
OTHER_LDFLAGS = (
"-framework",
SafariServices,
"-framework",
WebKit,
);
PRODUCT_BUNDLE_IDENTIFIER = net.aliasvault.safari;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
CE0CAFD12D81A9F8006174AB /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = AliasVault/AliasVault.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 18;
DEVELOPMENT_TEAM = 8PHW4HN3F7;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = AliasVault/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AliasVault;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
INFOPLIST_KEY_NSMainStoryboardFile = Main;
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 0.18.0;
OTHER_LDFLAGS = (
"-framework",
SafariServices,
"-framework",
WebKit,
);
PRODUCT_BUNDLE_IDENTIFIER = net.aliasvault.safari;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
CE0CAF9E2D81A9F7006174AB /* Build configuration list for PBXProject "AliasVault" */ = {
isa = XCConfigurationList;
buildConfigurations = (
CE0CAFC92D81A9F8006174AB /* Debug */,
CE0CAFCA2D81A9F8006174AB /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
CE0CAFCB2D81A9F8006174AB /* Build configuration list for PBXNativeTarget "AliasVault Extension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
CE0CAFCC2D81A9F8006174AB /* Debug */,
CE0CAFCD2D81A9F8006174AB /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
CE0CAFCF2D81A9F8006174AB /* Build configuration list for PBXNativeTarget "AliasVault" */ = {
isa = XCConfigurationList;
buildConfigurations = (
CE0CAFD02D81A9F8006174AB /* Debug */,
CE0CAFD12D81A9F8006174AB /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = CE0CAF9B2D81A9F7006174AB /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,14 @@
import Cocoa
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
// Override point for customization after application launch.
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,68 @@
{
"images" : [
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "mac-icon-16@1x.png",
"scale" : "1x"
},
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "mac-icon-16@2x.png",
"scale" : "2x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "mac-icon-32@1x.png",
"scale" : "1x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "mac-icon-32@2x.png",
"scale" : "2x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "mac-icon-128@1x.png",
"scale" : "1x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "mac-icon-128@2x.png",
"scale" : "2x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "mac-icon-256@1x.png",
"scale" : "1x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "mac-icon-256@2x.png",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "mac-icon-512@1x.png",
"scale" : "1x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "mac-icon-512@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,20 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>AliasVault</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<link rel="stylesheet" href="../Style.css">
<script src="../Script.js" defer></script>
</head>
<body>
<img src="../Icon.png" width="128" height="128" alt="AliasVault Icon">
<p class="state-unknown">To enable AliasVaults browser extension, go to the Safari Extensions preferences.</p>
<p class="state-on">AliasVaults browser extension is currently enabled in Safari. If you wish to turn it off, go to the Safari Extensions preferences.</p>
<p class="state-off">AliasVaults browser extension is currently disabled in Safari. If you wish to turn it on, go to the Safari Extensions preferences.</p>
<button class="open-preferences">Open Safari Extensions Preferences…</button>
</body>
</html>

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="19085" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19085"/>
<plugIn identifier="com.apple.WebKit2IBPlugin" version="19085"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
<scene sceneID="JPo-4y-FX3">
<objects>
<application id="hnw-xV-0zn" sceneMemberID="viewController">
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="AliasVault" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="AliasVault" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About AliasVault" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Hide AliasVault" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit AliasVault" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
<items>
<menuItem title="AliasVault Help" keyEquivalent="?" id="FKE-Sm-Kum">
<connections>
<action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="target"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="76" y="-134"/>
</scene>
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController showSeguePresentationStyle="single" id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="AliasVault" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenNone="YES"/>
<rect key="contentRect" x="196" y="240" width="425" height="325"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<connections>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
</connections>
</window>
<connections>
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
</connections>
</windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="250"/>
</scene>
<!--View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="425" height="325"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<wkWebView wantsLayer="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eOr-cG-IQY">
<rect key="frame" x="0.0" y="0.0" width="425" height="325"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<wkWebViewConfiguration key="configuration">
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
<wkPreferences key="preferences"/>
</wkWebViewConfiguration>
</wkWebView>
</subviews>
</view>
<connections>
<outlet property="webView" destination="eOr-cG-IQY" id="GFe-mU-dBY"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="655"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>SFSafariWebExtensionConverterVersion</key>
<string>15.4</string>
</dict>
</plist>

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -0,0 +1,22 @@
function show(enabled, useSettingsInsteadOfPreferences) {
if (useSettingsInsteadOfPreferences) {
document.getElementsByClassName('state-on')[0].innerText = "AliasVault's Safari browser extension is succesfully enabled. If you wish to turn it off, go to the Safari Extensions preferences.";
document.getElementsByClassName('state-off')[0].innerText = "AliasVault's Safari browser extension is currently disabled. If you wish to turn it on, go to the Safari Extensions preferences.";
document.getElementsByClassName('state-unknown')[0].innerText = "To enable AliasVault's Safari browser extension, go to the Safari Extensions preferences.";
document.getElementsByClassName('open-preferences')[0].innerText = "Open Safari Extensions Preferences…";
}
if (typeof enabled === "boolean") {
document.body.classList.toggle(`state-on`, enabled);
document.body.classList.toggle(`state-off`, !enabled);
} else {
document.body.classList.remove(`state-on`);
document.body.classList.remove(`state-off`);
}
}
function openPreferences() {
webkit.messageHandlers.controller.postMessage("open-preferences");
}
document.querySelector("button.open-preferences").addEventListener("click", openPreferences);

View File

@@ -0,0 +1,44 @@
* {
-webkit-user-select: none;
-webkit-user-drag: none;
cursor: default;
}
:root {
color-scheme: light dark;
--spacing: 20px;
}
html {
height: 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: var(--spacing);
margin: 0 calc(var(--spacing) * 2);
height: 100%;
text-align: center;
font: -apple-system-short-body;
font-family: -apple-system-short-body, system-ui;
}
body:not(.state-on, .state-off) :is(.state-on, .state-off) {
display: none;
}
body.state-on :is(.state-off, .state-unknown) {
display: none;
}
body.state-off :is(.state-on, .state-unknown) {
display: none;
}
button {
font-size: 1em;
}

View File

@@ -0,0 +1,67 @@
import Cocoa
import SafariServices
import WebKit
let extensionBundleIdentifier = "net.aliasvault.safari.extension"
class ViewController: NSViewController, WKNavigationDelegate, WKScriptMessageHandler {
@IBOutlet var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
self.webView.navigationDelegate = self
self.webView.configuration.userContentController.add(self, name: "controller")
self.webView.loadFileURL(Bundle.main.url(forResource: "Main", withExtension: "html")!, allowingReadAccessTo: Bundle.main.resourceURL!)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionBundleIdentifier) { (state, error) in
guard let state = state, error == nil else {
// Insert code to inform the user that something went wrong.
return
}
DispatchQueue.main.async {
if #available(macOS 13, *) {
webView.evaluateJavaScript("show(\(state.isEnabled), true)")
} else {
webView.evaluateJavaScript("show(\(state.isEnabled), false)")
}
}
}
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if (message.body as! String != "open-preferences") {
return;
}
SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in
DispatchQueue.main.async {
if let error = error {
// Show manual instructions in case opening the preferences fails due to restricted permissions.
let alert = NSAlert()
alert.messageText = "Safari Extensions Settings"
alert.informativeText = """
Please follow these steps to enable the extension:
1. Open Safari
2. Click Safari > Settings in the menu bar
3. Go to Extensions
4. Find and enable "AliasVault"
"""
alert.addButton(withTitle: "OK")
alert.runModal()
}
else {
// Close app
NSApplication.shared.terminate(nil)
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
This folder contains the Xcode project used to publish the Safari version of the AliasVault browser extension to Apple.
This project was created using the `safari-web-extension-converter` tool. This XCode project is a simple wrapper around the
WXT React browser extension, which is required by Apple in order to package and submit a Safari extension.
For more information see:
- https://developer.apple.com/documentation/safariservices/converting-a-web-extension-for-safari
- https://developer.apple.com/documentation/safariservices/running-your-safari-web-extension
To recreate this project, run the following command in the browser-extension root directory:
```bash
# Build the Safari extension via the normal build process (outputs in dist/safari-mv2)
npm run build:safari
# Convert the safari extension to an Xcode project (requires MacOS/XCode command line interface)
xcrun safari-web-extension-converter --bundle-identifier net.aliasvault.safari --macos-only dist/safari-mv2 --project-location safari-xcode --force
# After the Xcode project is opened, you can run the extension by clicking the "Run" button in the top left corner of the Xcode window.
# This will install the extension to your Safari browser and allow you to run it.
```
> Note: This project does not need to be recreated when the extension is updated. It loads all extension files from the dist/safari-mv2 directory that is created by the `build:safari` command. To update the extension and/or publish a new version:
> 1. Run `npm run build:safari` to rebuild the Safari extension
> 2. Open this Xcode project and rebuild it to get the latest version
> 3. Submit the extension to Apple for review via Xcode:
> - Select the "Archive" option from the Product menu
> - Select the newly created archive and click "Distribute App"
> - Select "Distribute" and follow the instructions to submit to App Store Connect

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,73 @@
import { defineBackground } from '#imports';
import { onMessage, sendMessage } from "webext-bridge/background";
import { setupContextMenus } from '@/entrypoints/background/ContextMenu';
import { handleCheckAuthStatus, handleClearVault, handleCreateIdentity, handleGetCredentials, handleGetDefaultEmailDomain, handleGetDefaultIdentityLanguage, handleGetDerivedKey, handleGetPasswordSettings, handleGetVault, handleStoreVault, handleSyncVault } from '@/entrypoints/background/VaultMessageHandler';
import { handleOpenPopup, handlePopupWithCredential, handleToggleContextMenu } from '@/entrypoints/background/PopupMessageHandler';
import { storage, browser } from '#imports';
import { GLOBAL_CONTEXT_MENU_ENABLED_KEY } from '@/utils/Constants';
export default defineBackground({
/**
* This is the main entry point for the background script.
*/
async main() {
// Listen for messages using webext-bridge
onMessage('CHECK_AUTH_STATUS', () => handleCheckAuthStatus());
onMessage('STORE_VAULT', ({ data }) => handleStoreVault(data));
onMessage('SYNC_VAULT', () => handleSyncVault());
onMessage('GET_VAULT', () => handleGetVault());
onMessage('CLEAR_VAULT', () => handleClearVault());
onMessage('GET_CREDENTIALS', () => handleGetCredentials());
onMessage('CREATE_IDENTITY', ({ data }) => handleCreateIdentity(data));
onMessage('GET_DEFAULT_EMAIL_DOMAIN', () => handleGetDefaultEmailDomain());
onMessage('GET_DEFAULT_IDENTITY_LANGUAGE', () => handleGetDefaultIdentityLanguage());
onMessage('GET_PASSWORD_SETTINGS', () => handleGetPasswordSettings());
onMessage('GET_DERIVED_KEY', () => handleGetDerivedKey());
onMessage('OPEN_POPUP', () => handleOpenPopup());
onMessage('OPEN_POPUP_WITH_CREDENTIAL', ({ data }) => handlePopupWithCredential(data));
onMessage('TOGGLE_CONTEXT_MENU', ({ data }) => handleToggleContextMenu(data));
// Setup context menus
const isContextMenuEnabled = await storage.getItem(GLOBAL_CONTEXT_MENU_ENABLED_KEY) ?? true;
if (isContextMenuEnabled) {
setupContextMenus();
}
// Listen for custom commands
try {
browser.commands.onCommand.addListener(async (command) => {
if (command === "show-autofill-popup") {
// Get the currently active tab
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
if (!tab?.id) {
return;
}
// Execute script in the active tab
await browser.scripting.executeScript({
target: { tabId: tab.id },
func: getActiveElementIdentifier,
}).then((results) => {
const elementIdentifier = results[0]?.result;
if (elementIdentifier) {
sendMessage('OPEN_AUTOFILL_POPUP', { elementIdentifier }, `content-script@${tab.id}`);
}
}).catch(console.error);
}
});
} catch (error) {
console.error('Error setting up command listener:', error);
}
}
});
/**
* Activate AliasVault for the active input element.
*/
function getActiveElementIdentifier() : string {
const target = document.activeElement;
if (target instanceof HTMLInputElement) {
return target.id || target.name || '';
}
return '';
}

View File

@@ -0,0 +1,119 @@
import { sendMessage } from 'webext-bridge/background';
import { browser } from "#imports";
import { type Browser } from '@wxt-dev/browser';
import { PasswordGenerator } from '@/utils/shared/password-generator';
/**
* Setup the context menus.
*/
export function setupContextMenus() : void {
// Create root menu
browser.contextMenus.create({
id: "aliasvault-root",
title: "AliasVault",
contexts: ["all"]
});
// Add fill option first (only for editable fields)
browser.contextMenus.create({
id: "aliasvault-activate-form",
parentId: "aliasvault-root",
title: "Autofill with AliasVault",
contexts: ["editable"],
});
// Add separator (only for editable fields)
browser.contextMenus.create({
id: "aliasvault-separator",
parentId: "aliasvault-root",
type: "separator",
contexts: ["editable"],
});
// Add password generator option
browser.contextMenus.create({
id: "aliasvault-generate-password",
parentId: "aliasvault-root",
title: "Generate random password (copy to clipboard)",
contexts: ["all"]
});
browser.contextMenus.onClicked.addListener((info: Browser.contextMenus.OnClickData, tab?: Browser.tabs.Tab) =>
handleContextMenuClick(info, tab)
);
}
/**
* Handle context menu clicks.
*/
export function handleContextMenuClick(info: Browser.contextMenus.OnClickData, tab?: Browser.tabs.Tab) : void {
if (info.menuItemId === "aliasvault-generate-password") {
// Initialize password generator
const passwordGenerator = new PasswordGenerator();
const password = passwordGenerator.generateRandomPassword();
// Use browser.scripting to write password to clipboard from active tab
if (tab?.id) {
browser.scripting.executeScript({
target: { tabId: tab.id },
func: copyPasswordToClipboard,
args: [password]
});
}
}
if (info.menuItemId === "aliasvault-activate-form" && tab?.id) {
// First get the active element's identifier
browser.scripting.executeScript({
target: { tabId: tab.id },
func: getActiveElementIdentifier,
}, (results) => {
const elementIdentifier = results[0]?.result;
if (elementIdentifier) {
// Send message to content script with proper tab targeting
sendMessage('OPEN_AUTOFILL_POPUP', { elementIdentifier }, `content-script@${tab.id}`);
}
});
}
}
/**
* Copy provided password to clipboard.
*/
function copyPasswordToClipboard(generatedPassword: string) : void {
navigator.clipboard.writeText(generatedPassword).then(() => {
showToast('Password copied to clipboard');
});
/**
* Show a toast notification.
*/
function showToast(message: string) : void {
const notification = document.createElement('div');
notification.textContent = message;
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
padding: 16px;
background: #4CAF50;
color: white;
border-radius: 4px;
z-index: 9999;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
`;
document.body.appendChild(notification);
setTimeout(() => notification.remove(), 3000);
}
}
/**
* Activate AliasVault for the active input element.
*/
function getActiveElementIdentifier() : string {
const target = document.activeElement;
if (target instanceof HTMLInputElement) {
return target.id || target.name || '';
}
return '';
}

View File

@@ -0,0 +1,50 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { browser } from '#imports';
import { BoolResponse } from '@/utils/types/messaging/BoolResponse';
import { setupContextMenus } from './ContextMenu';
/**
* Handle opening the popup.
*/
export function handleOpenPopup() : Promise<BoolResponse> {
return (async () : Promise<BoolResponse> => {
browser.windows.create({
url: browser.runtime.getURL('/popup.html?mode=inline_unlock&expanded=true'),
type: 'popup',
width: 400,
height: 600,
focused: true
});
return { success: true };
})();
}
/**
* Handle opening the popup with a credential.
*/
export function handlePopupWithCredential(message: any) : Promise<BoolResponse> {
return (async () : Promise<BoolResponse> => {
browser.windows.create({
url: browser.runtime.getURL(`/popup.html?expanded=true#/credentials/${message.credentialId}`),
type: 'popup',
width: 400,
height: 600,
focused: true
});
return { success: true };
})();
}
/**
* Handle toggling the context menu.
*/
export function handleToggleContextMenu(message: any) : Promise<BoolResponse> {
return (async () : Promise<BoolResponse> => {
if (!message.enabled) {
browser.contextMenus.removeAll();
} else {
setupContextMenus();
}
return { success: true };
})();
}

View File

@@ -0,0 +1,374 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { storage } from 'wxt/utils/storage';
import { EncryptionUtility } from '@/utils/EncryptionUtility';
import { SqliteClient } from '@/utils/SqliteClient';
import { WebApiService } from '@/utils/WebApiService';
import { Vault } from '@/utils/types/webapi/Vault';
import { VaultResponse } from '@/utils/types/webapi/VaultResponse';
import { VaultPostResponse } from '@/utils/types/webapi/VaultPostResponse';
import { BoolResponse as messageBoolResponse } from '@/utils/types/messaging/BoolResponse';
import { VaultResponse as messageVaultResponse } from '@/utils/types/messaging/VaultResponse';
import { CredentialsResponse as messageCredentialsResponse } from '@/utils/types/messaging/CredentialsResponse';
import { StringResponse as stringResponse } from '@/utils/types/messaging/StringResponse';
import { PasswordSettingsResponse as messagePasswordSettingsResponse } from '@/utils/types/messaging/PasswordSettingsResponse';
/**
* Check if the user is logged in and if the vault is locked.
*/
export async function handleCheckAuthStatus() : Promise<{ isLoggedIn: boolean, isVaultLocked: boolean }> {
const username = await storage.getItem('local:username');
const accessToken = await storage.getItem('local:accessToken');
const vaultData = await storage.getItem('session:encryptedVault');
const isLoggedIn = username !== null && accessToken !== null;
const isVaultLocked = isLoggedIn && vaultData === null;
return {
isLoggedIn,
isVaultLocked
};
}
/**
* Store the vault in browser storage.
*/
export async function handleStoreVault(
message: any,
) : Promise<messageBoolResponse> {
try {
const vaultResponse = message.vaultResponse as VaultResponse;
const encryptedVaultBlob = vaultResponse.vault.blob;
// Store encrypted vault and derived key in session storage.
await storage.setItems([
{ key: 'session:encryptedVault', value: encryptedVaultBlob },
{ key: 'session:derivedKey', value: message.derivedKey },
{ key: 'session:publicEmailDomains', value: vaultResponse.vault.publicEmailDomainList },
{ key: 'session:privateEmailDomains', value: vaultResponse.vault.privateEmailDomainList },
{ key: 'session:vaultRevisionNumber', value: vaultResponse.vault.currentRevisionNumber }
]);
return { success: true };
} catch (error) {
console.error('Failed to store vault:', error);
return { success: false, error: 'Failed to store vault' };
}
}
/**
* Sync the vault with the server to check if a newer vault is available. If so, the vault will be updated.
*/
export async function handleSyncVault(
) : Promise<messageBoolResponse> {
const webApi = new WebApiService(() => {});
const statusResponse = await webApi.getStatus();
const statusError = webApi.validateStatusResponse(statusResponse);
if (statusError !== null) {
return { success: false, error: statusError };
}
const vaultRevisionNumber = await storage.getItem('session:vaultRevisionNumber') as number;
if (statusResponse.vaultRevision > vaultRevisionNumber) {
// Retrieve the latest vault from the server.
const vaultResponse = await webApi.get<VaultResponse>('Vault');
await storage.setItems([
{ key: 'session:encryptedVault', value: vaultResponse.vault.blob },
{ key: 'session:publicEmailDomains', value: vaultResponse.vault.publicEmailDomainList },
{ key: 'session:privateEmailDomains', value: vaultResponse.vault.privateEmailDomainList },
{ key: 'session:vaultRevisionNumber', value: vaultResponse.vault.currentRevisionNumber }
]);
}
return { success: true };
}
/**
* Get the vault from browser storage.
*/
export async function handleGetVault(
) : Promise<messageVaultResponse> {
try {
const encryptedVault = await storage.getItem('session:encryptedVault') as string;
const derivedKey = await storage.getItem('session:derivedKey') as string;
const publicEmailDomains = await storage.getItem('session:publicEmailDomains') as string[];
const privateEmailDomains = await storage.getItem('session:privateEmailDomains') as string[];
const vaultRevisionNumber = await storage.getItem('session:vaultRevisionNumber') as number;
if (!encryptedVault) {
console.error('Vault not available');
return { success: false, error: 'Vault not available' };
}
const decryptedVault = await EncryptionUtility.symmetricDecrypt(
encryptedVault,
derivedKey
);
return {
success: true,
vault: decryptedVault,
publicEmailDomains: publicEmailDomains ?? [],
privateEmailDomains: privateEmailDomains ?? [],
vaultRevisionNumber: vaultRevisionNumber ?? 0
};
} catch (error) {
console.error('Failed to get vault:', error);
return { success: false, error: 'Failed to get vault' };
}
}
/**
* Clear the vault from browser storage.
*/
export function handleClearVault(
) : messageBoolResponse {
storage.removeItems([
'session:encryptedVault',
'session:derivedKey',
'session:publicEmailDomains',
'session:privateEmailDomains',
'session:vaultRevisionNumber'
]);
return { success: true };
}
/**
* Get all credentials.
*/
export async function handleGetCredentials(
) : Promise<messageCredentialsResponse> {
const derivedKey = await storage.getItem('session:derivedKey') as string;
if (!derivedKey) {
return { success: false, error: 'Vault is locked' };
}
try {
const sqliteClient = await createVaultSqliteClient();
const credentials = sqliteClient.getAllCredentials();
return { success: true, credentials: credentials };
} catch (error) {
console.error('Error getting credentials:', error);
return { success: false, error: 'Failed to get credentials' };
}
}
/**
* Create an identity.
*/
export async function handleCreateIdentity(
message: any,
) : Promise<messageBoolResponse> {
const derivedKey = await storage.getItem('session:derivedKey') as string;
if (!derivedKey) {
return { success: false, error: 'Vault is locked' };
}
try {
const sqliteClient = await createVaultSqliteClient();
// Add the new credential to the vault/database.
sqliteClient.createCredential(message.credential);
// Upload the new vault to the server.
await uploadNewVaultToServer(sqliteClient);
return { success: true };
} catch (error) {
console.error('Failed to create identity:', error);
return { success: false, error: 'Failed to create identity' };
}
}
/**
* Get the email addresses for a vault.
*/
export async function getEmailAddressesForVault(
sqliteClient: SqliteClient
): Promise<string[]> {
// TODO: create separate query to only get email addresses to avoid loading all credentials.
const credentials = sqliteClient.getAllCredentials();
// Get metadata from storage
const privateEmailDomains = await storage.getItem('session:privateEmailDomains') as string[];
const emailAddresses = credentials
.filter(cred => cred.Alias?.Email != null)
.map(cred => cred.Alias.Email ?? '')
.filter((email, index, self) => self.indexOf(email) === index);
return emailAddresses.filter(email => {
const domain = email?.split('@')[1];
return domain && privateEmailDomains.includes(domain);
});
}
/**
* Get default email domain for a vault.
*/
export function handleGetDefaultEmailDomain(
) : Promise<stringResponse> {
return (async () : Promise<stringResponse> => {
try {
const privateEmailDomains = await storage.getItem('session:privateEmailDomains') as string[];
const publicEmailDomains = await storage.getItem('session:publicEmailDomains') as string[];
const sqliteClient = await createVaultSqliteClient();
const defaultEmailDomain = sqliteClient.getDefaultEmailDomain();
/**
* Check if a domain is valid.
*/
const isValidDomain = (domain: string) : boolean => {
const isValid = (domain &&
domain !== 'DISABLED.TLD' &&
(privateEmailDomains.includes(domain) || publicEmailDomains.includes(domain))) as boolean;
return isValid;
};
// First check if the default domain that is configured in the vault is still valid.
if (defaultEmailDomain && isValidDomain(defaultEmailDomain)) {
return { success: true, value: defaultEmailDomain };
}
// If default domain is not valid, fall back to first available private domain.
const firstPrivate = privateEmailDomains.find(isValidDomain);
if (firstPrivate) {
return { success: true, value: firstPrivate };
}
// Return first valid public domain if no private domains are available.
const firstPublic = publicEmailDomains.find(isValidDomain);
if (firstPublic) {
return { success: true, value: firstPublic };
}
// Return null if no valid domains are found
return { success: true };
} catch (error) {
console.error('Error getting default email domain:', error);
return { success: false, error: 'Failed to get default email domain' };
}
})();
}
/**
* Get the default identity language.
*/
export async function handleGetDefaultIdentityLanguage(
) : Promise<stringResponse> {
try {
const sqliteClient = await createVaultSqliteClient();
const settingValue = sqliteClient.getDefaultIdentityLanguage();
return { success: true, value: settingValue };
} catch (error) {
console.error('Error getting default identity language:', error);
return { success: false, error: 'Failed to get default identity language' };
}
}
/**
* Get the password settings.
*/
export async function handleGetPasswordSettings(
) : Promise<messagePasswordSettingsResponse> {
try {
const sqliteClient = await createVaultSqliteClient();
const passwordSettings = sqliteClient.getPasswordSettings();
return { success: true, settings: passwordSettings };
} catch (error) {
console.error('Error getting password settings:', error);
return { success: false, error: 'Failed to get password settings' };
}
}
/**
* Get the derived key for the encrypted vault.
*/
export async function handleGetDerivedKey(
) : Promise<string> {
const derivedKey = await storage.getItem('session:derivedKey') as string;
return derivedKey;
}
/**
* Upload a new version of the vault to the server using the provided sqlite client.
*/
async function uploadNewVaultToServer(sqliteClient: SqliteClient) : Promise<void> {
const updatedVaultData = sqliteClient.exportToBase64();
const derivedKey = await storage.getItem('session:derivedKey') as string;
const encryptedVault = await EncryptionUtility.symmetricEncrypt(
updatedVaultData,
derivedKey
);
await storage.setItems([
{ key: 'session:encryptedVault', value: encryptedVault }
]);
// Get metadata from storage
const vaultRevisionNumber = await storage.getItem('session:vaultRevisionNumber') as number;
// Upload new encrypted vault to server.
const username = await storage.getItem('local:username') as string;
const emailAddresses = await getEmailAddressesForVault(sqliteClient);
const newVault: Vault = {
blob: encryptedVault,
createdAt: new Date().toISOString(),
credentialsCount: sqliteClient.getAllCredentials().length,
currentRevisionNumber: vaultRevisionNumber,
emailAddressList: emailAddresses,
privateEmailDomainList: [], // Empty on purpose, API will not use this for vault updates.
publicEmailDomainList: [], // Empty on purpose, API will not use this for vault updates.
encryptionPublicKey: '', // Empty on purpose, only required if new public/private key pair is generated.
client: '', // Empty on purpose, API will not use this for vault updates.
updatedAt: new Date().toISOString(),
username: username,
version: sqliteClient.getDatabaseVersion() ?? '0.0.0'
};
const webApi = new WebApiService(() => {});
const response = await webApi.post<Vault, VaultPostResponse>('Vault', newVault);
// Check if response is successful (.status === 0)
if (response.status === 0) {
await storage.setItem('session:vaultRevisionNumber', response.newRevisionNumber);
} else {
throw new Error('Failed to upload new vault to server');
}
}
/**
* Create a new sqlite client for the stored vault.
*/
async function createVaultSqliteClient() : Promise<SqliteClient> {
const encryptedVault = await storage.getItem('session:encryptedVault') as string;
const derivedKey = await storage.getItem('session:derivedKey') as string;
if (!encryptedVault || !derivedKey) {
throw new Error('No vault or derived key found');
}
// Decrypt the vault.
const decryptedVault = await EncryptionUtility.symmetricDecrypt(
encryptedVault,
derivedKey
);
// Initialize the SQLite client with the decrypted vault.
const sqliteClient = new SqliteClient();
await sqliteClient.initializeFromBase64(decryptedVault);
return sqliteClient;
}

View File

@@ -0,0 +1,141 @@
import '@/entrypoints/contentScript/style.css';
import { FormDetector } from '@/utils/formDetector/FormDetector';
import { isAutoShowPopupEnabled, openAutofillPopup, removeExistingPopup } from '@/entrypoints/contentScript/Popup';
import { injectIcon, popupDebounceTimeHasPassed, validateInputField } from '@/entrypoints/contentScript/Form';
import { onMessage } from "webext-bridge/content-script";
import { BoolResponse as messageBoolResponse } from '@/utils/types/messaging/BoolResponse';
import { defineContentScript } from '#imports';
import { createShadowRootUi } from '#imports';
export default defineContentScript({
matches: ['<all_urls>'],
cssInjectionMode: 'ui',
allFrames: true,
matchAboutBlank: true,
runAt: 'document_start',
/**
* Main entry point for the content script.
*/
async main(ctx) {
if (ctx.isInvalid) {
return;
}
// Wait for 750ms to give the host page time to load and to increase the chance that the body is available and ready.
await new Promise(resolve => setTimeout(resolve, 750));
// Create a shadow root UI for isolation
const ui = await createShadowRootUi(ctx, {
name: 'aliasvault-ui',
position: 'inline',
anchor: 'body',
/**
* Handle mount.
*/
onMount(container) {
/**
* Handle input field focus.
*/
const handleFocusIn = async (e: FocusEvent) : Promise<void> => {
if (ctx.isInvalid) {
return;
}
// Check if element itself, html or body has av-disable attribute like av-disable="true"
const avDisable = ((e.target as HTMLElement).getAttribute('av-disable') ?? document.body?.getAttribute('av-disable') ?? document.documentElement.getAttribute('av-disable')) === 'true';
if (avDisable) {
return;
}
const { isValid, inputElement } = validateInputField(e.target as Element);
if (isValid && inputElement) {
const formDetector = new FormDetector(document, inputElement);
if (!formDetector.containsLoginForm()) {
return;
}
// Only show popup for autofill-triggerable fields
if (!formDetector.isAutofillTriggerableField()) {
return;
}
// Only inject icon and show popup if autofill popup is enabled
if (await isAutoShowPopupEnabled()) {
injectIcon(inputElement, container);
// Only show popup if debounce time has passed
if (popupDebounceTimeHasPassed()) {
openAutofillPopup(inputElement, container);
}
}
}
};
// Listen for input field focus in the main document
document.addEventListener('focusin', handleFocusIn);
// Check if currently something is focused, if so, apply check for that element
const currentFocusedElement = document.activeElement;
if (currentFocusedElement) {
showPopupForElement(currentFocusedElement);
}
// Listen for popstate events (back/forward navigation)
window.addEventListener('popstate', () => {
if (ctx.isInvalid) {
return;
}
removeExistingPopup(container);
});
// Listen for messages from the background script
onMessage('OPEN_AUTOFILL_POPUP', async (message: { data: { elementIdentifier: string } }) : Promise<messageBoolResponse> => {
const { data } = message;
const { elementIdentifier } = data;
if (!elementIdentifier) {
return { success: false, error: 'No element identifier provided' };
}
const target = document.getElementById(elementIdentifier) ?? document.getElementsByName(elementIdentifier)[0];
await showPopupForElement(target, true);
return { success: true };
});
/**
* Show popup for element.
*/
async function showPopupForElement(element: Element, forceShow: boolean = false) : Promise<void> {
const { isValid, inputElement } = validateInputField(element);
if (!isValid || !inputElement) {
return;
}
const formDetector = new FormDetector(document, inputElement);
if (!formDetector.containsLoginForm()) {
return;
}
/**
* By default we check if the popup is not disabled (for current site) and if the field is autofill-triggerable
* but if forceShow is true, we show the popup regardless.
*/
const canShowPopup = forceShow || (await isAutoShowPopupEnabled() && formDetector.isAutofillTriggerableField());
if (canShowPopup) {
injectIcon(inputElement, container);
openAutofillPopup(inputElement, container);
}
}
},
});
// Mount the UI to create the shadow root
ui.autoMount();
},
});

View File

@@ -0,0 +1,108 @@
import { CombinedStopWords } from '@/utils/formDetector/FieldPatterns';
import { Credential } from '@/utils/types/Credential';
type CredentialWithPriority = Credential & {
priority: number;
}
/**
* Filter credentials based on current URL and page context to determine which credentials to show
* in the autofill popup. Credentials are sorted by priority:
* 1. Exact URL match (highest priority)
* 2. Base URL match AND page title word match
* 3. Base URL match only
* 4. Page title word match only (lowest priority)
*/
export function filterCredentials(credentials: Credential[], currentUrl: string, pageTitle: string): Credential[] {
const urlObject = new URL(currentUrl);
const baseUrl = `${urlObject.protocol}//${urlObject.hostname}`;
const filtered: CredentialWithPriority[] = [];
const sanitizedCurrentUrl = currentUrl.toLowerCase().replace('www.', '');
// 1. Exact URL match (priority 1)
credentials.forEach(cred => {
if (!cred.ServiceUrl || cred.ServiceUrl.length === 0) {
return;
}
const sanitizedCredUrl = cred.ServiceUrl.toLowerCase().replace('www.', '');
if (sanitizedCurrentUrl.startsWith(sanitizedCredUrl)) {
filtered.push({ ...cred, priority: 1 });
}
});
// If we have one or more exact matches, do not continue to other matches
if (filtered.length > 0) {
return filtered;
}
// Prepare page title words for matching
const titleWords = pageTitle.length > 0
? pageTitle.toLowerCase()
.split(/\s+/)
.filter(word =>
word.length > 3 &&
!CombinedStopWords.has(word.toLowerCase())
)
: [];
// Check for base URL matches and page title matches
credentials.forEach(cred => {
if (!cred.ServiceUrl || filtered.some(f => f.Id === cred.Id)) {
return;
}
let hasBaseUrlMatch = false;
let hasTitleMatch = false;
// Check base URL match
try {
const credUrlObject = new URL(cred.ServiceUrl);
const currentUrlObject = new URL(baseUrl);
const credDomainParts = credUrlObject.hostname.toLowerCase().split('.');
const currentDomainParts = currentUrlObject.hostname.toLowerCase().split('.');
const credRootDomain = credDomainParts.slice(-2).join('.');
const currentRootDomain = currentDomainParts.slice(-2).join('.');
if (credUrlObject.protocol === currentUrlObject.protocol &&
credRootDomain === currentRootDomain) {
hasBaseUrlMatch = true;
}
} catch {
// Invalid URL, skip
}
// Check page title match
if (titleWords.length > 0) {
const credNameWords = cred.ServiceName.toLowerCase()
.split(/\s+/)
.filter(word => word.length > 3 && !CombinedStopWords.has(word));
hasTitleMatch = titleWords.some(word =>
credNameWords.some(credWord => credWord.includes(word))
);
}
// Assign priority based on matches
if (hasBaseUrlMatch && hasTitleMatch) {
filtered.push({ ...cred, priority: 2 });
} else if (hasBaseUrlMatch) {
filtered.push({ ...cred, priority: 3 });
} else if (hasTitleMatch) {
filtered.push({ ...cred, priority: 4 });
}
});
// Sort by priority and then take unique credentials
const uniqueCredentials = Array.from(
new Map(filtered
.sort((a, b) => a.priority - b.priority)
.map(cred => [cred.Id, cred]))
.values()
);
// Show max 3 results
return uniqueCredentials.slice(0, 3);
}

View File

@@ -0,0 +1,290 @@
import { FormDetector } from '@/utils/formDetector/FormDetector';
import { FormFiller } from '@/utils/formDetector/FormFiller';
import { Credential } from '@/utils/types/Credential';
import { openAutofillPopup } from '@/entrypoints/contentScript/Popup';
/**
* Global timestamp to track popup debounce time.
* This is used to not show the popup again for a specific amount of time.
* Used after autofill events to prevent spamming the popup from automatic
* triggered browser events which can cause "focus" events to trigger.
*/
let popupDebounceTime = 0;
/**
* Check if popup can be shown based on debounce time.
*/
export function popupDebounceTimeHasPassed() : boolean {
if (Date.now() < popupDebounceTime) {
return false;
}
return true;
}
/**
* Hide popup for a specific amount of time.
*/
export function hidePopupFor(ms: number) : void {
popupDebounceTime = Date.now() + ms;
}
/**
* Validates if an element is a supported input field that can be processed for autofill.
* @param element The element to validate
* @returns An object containing validation result and the element cast as HTMLInputElement if valid
*/
export function validateInputField(element: Element | null): { isValid: boolean; inputElement?: HTMLInputElement } {
if (!element) {
return { isValid: false };
}
const textInputTypes = ['text', 'email', 'tel', 'password', 'search', 'url', 'number'];
const elementType = element.getAttribute('type');
const isInputElement = element.tagName.toLowerCase() === 'input';
// Check if it's a valid input field we should process
const isValid = (
// Case 1: It's an input element (with either explicit type or defaulting to "text")
(isInputElement && (!elementType || textInputTypes.includes(elementType?.toLowerCase() ?? ''))) ||
// Case 2: Non-input element but has valid type attribute
(!isInputElement && elementType && textInputTypes.includes(elementType.toLowerCase()))
) as boolean;
return {
isValid,
inputElement: isValid ? (element as HTMLInputElement) : undefined
};
}
/**
* Fill credential into current form.
*
* @param credential - The credential to fill.
* @param input - The input element that triggered the popup. Required when filling credentials to know which form to fill.
*/
export function fillCredential(credential: Credential, input: HTMLInputElement) : void {
// Set debounce time to 300ms to prevent the popup from being shown again within 300ms because of autofill events.
hidePopupFor(300);
const formDetector = new FormDetector(document, input);
const form = formDetector.getForm();
if (!form) {
// No form found, so we can't fill anything.
return;
}
const formFiller = new FormFiller(form, triggerInputEvents);
formFiller.fillFields(credential);
}
/**
* Find the actual visible input element, either the element itself or a child input.
* Certain websites use custom input element wrappers that not only contain the input but
* also other elements like labels, icons, etc. As we want to position the icon relative to the actual
* input, we try to find the actual input element. If there is no actual input element, we fallback
* to the provided element.
*
* This method is optional, but it improves the AliasVault icon positioning on certain websites.
*
* @param element - The element to check.
* @returns The actual input element to use for positioning.
*/
function findActualInput(element: HTMLElement): HTMLInputElement {
// If it's already an input, return it
if (element.tagName.toLowerCase() === 'input') {
return element as HTMLInputElement;
}
// Try to find a visible child input
const childInput = element.querySelector('input');
if (childInput) {
const style = window.getComputedStyle(childInput);
if (style.display !== 'none' && style.visibility !== 'hidden') {
return childInput;
}
}
// Fallback to the provided element if no child input found
return element as HTMLInputElement;
}
/**
* Inject icon for a focused input element
*/
export function injectIcon(input: HTMLInputElement, container: HTMLElement): void {
// Find the actual input element to use for positioning
const actualInput = findActualInput(input);
const aliasvaultIconSvg = `<?xml version="1.0" encoding="UTF-8"?>
<svg enable-background="new 0 0 500 500" version="1.1" viewBox="0 0 500 500" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<path d="m459.87 294.95c0.016205 5.4005 0.03241 10.801-0.35022 16.873-1.111 6.3392-1.1941 12.173-2.6351 17.649-10.922 41.508-36.731 69.481-77.351 83.408-7.2157 2.4739-14.972 3.3702-22.479 4.995-23.629 0.042205-47.257 0.11453-70.886 0.12027-46.762 0.011322-93.523-0.01416-140.95-0.43411-8.59-2.0024-16.766-2.8352-24.398-5.3326-21.595-7.0666-39.523-19.656-53.708-37.552-10.227-12.903-17.579-27.17-21.28-43.221-1.475-6.3967-2.4711-12.904-3.6852-19.361-0.051849-5.747-0.1037-11.494 0.26915-17.886 4.159-42.973 27.68-71.638 63.562-92.153 0-0.70761-0.001961-1.6988 3.12e-4 -2.69 0.022484-9.8293-1.3071-19.894 0.35664-29.438 3.2391-18.579 11.08-35.272 23.763-49.773 12.098-13.832 26.457-23.989 43.609-30.029 7.813-2.7512 16.14-4.0417 24.234-5.9948 7.392-0.025734 14.784-0.05146 22.835 0.32253 4.1959 0.95392 7.7946 1.2538 11.258 2.1053 17.16 4.2192 32.287 12.176 45.469 24.104 2.2558 2.0411 4.372 6.6241 9.621 3.868 16.839-8.8419 34.718-11.597 53.603-8.594 16.791 2.6699 31.602 9.4308 44.236 20.636 11.531 10.227 19.84 22.841 25.393 37.236 6.3436 16.445 10.389 33.163 6.0798 49.389 7.9587 8.9321 15.807 16.704 22.421 25.414 9.162 12.065 15.33 25.746 18.144 40.776 0.97046 5.1848 1.9111 10.375 2.8654 15.563m-71.597 71.012c5.5615-5.2284 12.002-9.7986 16.508-15.817 10.474-13.992 14.333-29.916 11.288-47.446-2.2496-12.95-8.1973-24.076-17.243-33.063-12.746-12.663-28.865-18.614-46.786-18.569-69.912 0.17712-139.82 0.56831-209.74 0.96176-15.922 0.089599-29.168 7.4209-39.685 18.296-14.45 14.944-20.408 33.343-16.655 54.368 2.2763 12.754 8.2167 23.748 17.158 32.66 13.299 13.255 30.097 18.653 48.728 18.651 59.321-0.005188 118.64 0.042358 177.96-0.046601 9.5912-0.014374 19.181-0.86588 28.773-0.88855 10.649-0.025146 19.978-3.825 29.687-9.1074z" fill="#EEC170"/>
<path d="m162.77 293c15.654 4.3883 20.627 22.967 10.304 34.98-5.3104 6.1795-14.817 8.3208-24.278 5.0472-7.0723-2.4471-12.332-10.362-12.876-17.933-1.0451-14.542 11.089-23.176 21.705-23.046 1.5794 0.019287 3.1517 0.61566 5.1461 0.95184z" fill="#EEC170"/>
<path d="m227.18 293.64c7.8499 2.3973 11.938 8.2143 13.524 15.077 1.8591 8.0439-0.44817 15.706-7.1588 21.121-6.7633 5.4572-14.417 6.8794-22.578 3.1483-8.2972-3.7933-12.836-10.849-12.736-19.438 0.1687-14.497 14.13-25.368 28.948-19.908z" fill="#EEC170"/>
<path d="m261.57 319.07c-2.495-14.418 4.6853-22.603 14.596-26.108 9.8945-3.4995 23.181 3.4303 26.267 13.779 4.6504 15.591-7.1651 29.064-21.665 28.161-8.5254-0.53088-17.202-6.5094-19.198-15.831z" fill="#EEC170"/>
<path d="m336.91 333.41c-9.0175-4.2491-15.337-14.349-13.829-21.682 3.0825-14.989 13.341-20.304 23.018-19.585 10.653 0.79141 17.93 7.407 19.765 17.547 1.9588 10.824-4.1171 19.939-13.494 23.703-5.272 2.1162-10.091 1.5086-15.46 0.017883z" fill="#EEC170"/>
</svg>`;
const ICON_HTML = `
<div class="av-input-icon">
<img src="data:image/svg+xml;base64,${btoa(aliasvaultIconSvg)}" style="width: 100%; height: 100%;" />
</div>
`;
// Generate unique ID if input doesn't have one
if (!actualInput.id) {
actualInput.id = `aliasvault-input-${Math.random().toString(36).substring(2, 11)}`;
}
// Create an overlay container at document level if it doesn't exist
let overlayContainer = container.querySelector('#aliasvault-overlay-container');
if (!overlayContainer) {
overlayContainer = document.createElement('div') as HTMLElement;
overlayContainer.id = 'aliasvault-overlay-container';
overlayContainer.className = 'av-overlay-container';
container.appendChild(overlayContainer);
}
// Create the icon element from the HTML template
const iconContainer = document.createElement('div');
iconContainer.innerHTML = ICON_HTML;
const icon = iconContainer.firstElementChild as HTMLElement;
icon.setAttribute('data-icon-for', actualInput.id);
// Enable pointer events just for the icon
icon.style.pointerEvents = 'auto';
/**
* Update position of the icon.
* Positions icon relative to right edge, moving it left by any existing padding.
*/
const updateIconPosition = () : void => {
const rect = actualInput.getBoundingClientRect();
const computedStyle = window.getComputedStyle(actualInput);
const paddingRight = parseInt(computedStyle.paddingLeft + computedStyle.paddingRight);
// Default offset is 32px, add any padding to move it further left
const rightOffset = 24 + paddingRight;
icon.style.position = 'fixed';
icon.style.top = `${rect.top + (rect.height - 24) / 2}px`;
icon.style.left = `${(rect.left + rect.width) - rightOffset}px`;
};
// Update position initially and on relevant events
updateIconPosition();
window.addEventListener('scroll', updateIconPosition, true);
window.addEventListener('resize', updateIconPosition);
// Add click event to trigger the autofill popup and refocus the input
icon.addEventListener('click', (e: MouseEvent) => {
e.preventDefault();
e.stopPropagation();
setTimeout(() => actualInput.focus(), 0);
openAutofillPopup(actualInput, container);
});
// Append the icon to the overlay container
overlayContainer.appendChild(icon);
// Fade in the icon
requestAnimationFrame(() => {
icon.style.opacity = '1';
});
/**
* Remove the icon when the input loses focus.
*/
const handleBlur = (): void => {
icon.style.opacity = '0';
setTimeout(() => {
icon.remove();
actualInput.removeEventListener('blur', handleBlur);
actualInput.removeEventListener('keydown', handleKeyPress);
window.removeEventListener('scroll', updateIconPosition, true);
window.removeEventListener('resize', updateIconPosition);
// Remove overlay container if it's empty
if (!overlayContainer.children.length) {
overlayContainer.remove();
}
}, 200);
};
/**
* Handle key press to dismiss icon.
*/
const handleKeyPress = (e: KeyboardEvent): void => {
// Dismiss on Enter, Escape, or Tab.
if (e.key === 'Enter' || e.key === 'Escape' || e.key === 'Tab') {
handleBlur();
}
};
actualInput.addEventListener('blur', handleBlur);
actualInput.addEventListener('keydown', handleKeyPress);
}
/**
* Trigger input events for an element to trigger form validation
* which some websites require before the "continue" button is enabled.
*/
function triggerInputEvents(element: HTMLInputElement | HTMLSelectElement, animate: boolean = true) : void {
// Add keyframe animation if animation is requested
if (animate) {
// Create an overlay div that will show the highlight effect
const overlay = document.createElement('div');
/**
* Update position of the overlay.
*/
const updatePosition = () : void => {
const rect = element.getBoundingClientRect();
overlay.style.cssText = `
position: fixed;
z-index: 999999991;
pointer-events: none;
top: ${rect.top}px;
left: ${rect.left}px;
width: ${rect.width}px;
height: ${rect.height}px;
background-color: rgba(244, 149, 65, 0.3);
border-radius: ${getComputedStyle(element).borderRadius};
animation: fadeOut 1.4s ease-out forwards;
`;
};
updatePosition();
// Add scroll event listener
window.addEventListener('scroll', updatePosition);
const style = document.createElement('style');
style.textContent = `
@keyframes fadeOut {
0% { opacity: 1; transform: scale(1.02); }
100% { opacity: 0; transform: scale(1); }
}
`;
document.head.appendChild(style);
document.body.appendChild(overlay);
// Remove overlay and cleanup after animation
setTimeout(() => {
window.removeEventListener('scroll', updatePosition);
overlay.remove();
style.remove();
}, 1400);
}
// Trigger events
element.dispatchEvent(new Event('input', { bubbles: true }));
element.dispatchEvent(new Event('change', { bubbles: true }));
if (element.type === 'radio') {
element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
element.dispatchEvent(new MouseEvent('click', { bubbles: true }));
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,835 @@
/* AliasVault Content Script Styles */
body {
position: absolute;
margin: 0;
padding: 0;
}
/* Base Popup Styles */
.av-popup {
position: absolute;
z-index: 2147483646;
background-color: rgb(31, 41, 55);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
width: 320px;
border: 1px solid rgb(55, 65, 81);
border-radius: 4px;
max-width: 90vw;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 14px;
color: #333;
overflow: hidden;
box-sizing: border-box;
margin-top: 4px;
}
/* Loading Popup Styles */
.av-loading-container {
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
gap: 8px;
}
.av-loading-spinner {
width: 16px;
height: 16px;
border: 2px solid #e5e7eb;
border-radius: 50%;
border-top-color: transparent;
animation: av-loading-spin 1s linear infinite;
}
@keyframes av-loading-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.av-loading-text {
font-size: 14px;
font-weight: 500;
line-height: normal;
color: #e5e7eb;
}
/* Credential List Styles */
.av-credential-list {
max-height: 180px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: #4b5563 #1f2937;
line-height: 1.3;
}
.av-credential-item {
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
transition: background-color 0.2s ease;
border-radius: 4px;
width: 100%;
box-sizing: border-box;
text-align: left;
}
.av-credential-item:hover {
background-color: #2d3748;
}
.av-credential-info {
display: flex;
align-items: center;
gap: 16px;
flex-grow: 1;
padding: 10px 16px;
border-radius: 4px;
transition: background-color 0.2s ease;
min-width: 0;
}
.av-credential-logo {
width: 20px;
height: 20px;
}
.av-credential-text {
display: flex;
flex-direction: column;
flex-grow: 1;
min-width: 0;
margin-right: 8px;
}
.av-service-name {
font-weight: 500;
white-space: nowrap;
overflow: hidden;
font-size: 14px;
text-overflow: ellipsis;
color: #f3f4f6;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.av-suggested-names {
margin-top: 4px;
font-size: 12px;
color: #acacac;
}
.av-suggested-name {
color: #bababa;
cursor: pointer;
text-decoration: underline;
}
.av-suggested-name:hover {
color: #d68338;
}
.av-service-details {
font-size: 0.85em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #9ca3af;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.av-popout-icon {
display: flex;
align-items: center;
padding: 4px;
margin-right: 16px;
opacity: 0.6;
border-radius: 4px;
flex-shrink: 0;
color: #ffffff;
transition: opacity 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.av-popout-icon:hover {
opacity: 1;
background-color: #ffffff;
color: #000000;
}
.av-no-matches {
padding-left: 10px;
padding-top: 8px;
padding-bottom: 8px;
font-size: 14px;
color: #9ca3af;
font-style: italic;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
text-align: left;
}
/* Divider */
.av-divider {
height: 1px;
background: #374151;
margin-bottom: 8px;
}
/* Action Container */
.av-action-container {
display: flex;
padding-left: 8px;
padding-right: 8px;
padding-bottom: 8px;
gap: 8px;
}
/* Button Styles */
.av-button {
padding: 6px 12px;
border-radius: 4px;
background: #374151;
color: #e5e7eb;
font-size: 14px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
cursor: pointer;
border: none;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
transition: background-color 0.2s ease;
min-width: 0px;
}
.av-button:hover {
background-color: #4b5563;
}
.av-button-primary {
background-color: #374151;
}
.av-button-primary:hover {
background-color: #d68338;
}
.av-button-close {
padding: 6px;
}
.av-button-close:hover {
background-color: #dc2626;
color: #ffffff;
}
/* Search Input */
.av-search-input {
flex: 2;
border-radius: 4px;
background: #374151;
color: #e5e7eb;
font-size: 14px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
border: 1px solid #4b5563;
outline: none;
line-height: 1;
text-align: center;
min-width: 0px;
}
.av-search-input::placeholder {
color: #bdbebe;
}
.av-search-input:focus {
border-color: #2563eb;
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
}
/* Vault Locked Popup */
.av-vault-locked {
padding: 12px 16px;
position: relative;
}
.av-vault-locked:hover {
background-color: #374151;
}
.av-vault-locked-container {
display: flex;
align-items: center;
padding-right: 32px;
width: 100%;
transition: background-color 0.2s ease;
border-radius: 4px;
}
.av-vault-locked-message {
color: #d1d5db;
font-size: 14px;
flex-grow: 1;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.av-vault-locked-button {
background: none;
border: none;
cursor: pointer;
padding: 4px;
padding-right: 28px;
display: flex;
align-items: center;
justify-content: center;
color: #d68338;
border-radius: 4px;
margin-left: 8px;
}
.av-vault-locked-close {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
padding: 4px;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
border: 1px solid #6f6f6f;
}
/* Create Name Popup */
.av-create-popup-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 2147483647;
display: flex;
align-items: center;
justify-content: center;
}
.av-create-popup {
position: relative;
z-index: 1000000000;
background: #1f2937;
border: 1px solid #374151;
border-radius: 8px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06),
0 20px 25px -5px rgba(0, 0, 0, 0.1);
width: 400px;
max-width: 90vw;
transform: scale(0.95);
opacity: 0;
padding: 16px 24px;
transition: transform 0.2s ease, opacity 0.2s ease;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.av-create-popup.show {
transform: scale(1);
opacity: 1;
}
.av-create-popup-title {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #f8f9fa;
}
.av-create-popup-help-text {
margin: 4px 0 0;
font-size: 13px;
color: #9ca3af;
text-align: center;
line-height: 1.4;
padding: 0 16px;
}
.av-create-popup-modes {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 10px;
}
.av-create-popup-mode-btn {
display: flex;
align-items: center;
gap: 16px;
padding: 8px;
background: #374151;
border: 1px solid #4b5563;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
text-align: left;
width: 100%;
}
.av-create-popup-mode-btn:hover {
background: #4b5563;
transform: translateY(-1px);
}
.av-create-popup-mode-icon {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
background: #1f2937;
border-radius: 8px;
color: #d68338;
}
.av-create-popup-mode-icon .av-icon {
width: 24px;
height: 24px;
}
.av-create-popup-mode-content {
flex: 1;
}
.av-create-popup-mode-content h4 {
margin: 0 0 4px 0;
font-size: 16px;
font-weight: 600;
color: #f8f9fa;
}
.av-create-popup-mode-content p {
margin: 0;
font-size: 14px;
color: #9ca3af;
}
.av-create-popup-input {
width: 100%;
padding: 8px 12px;
border: 1px solid #374151;
border-radius: 6px;
background: #374151;
color: #f8f9fa;
font-size: 14px;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
box-sizing: border-box;
}
.av-create-popup-input:focus {
border-color: #2563eb;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
.av-create-popup-input-default {
color: #737373;
}
/* Custom Credential UI Styles */
.av-create-popup-custom-toggle {
margin: 16px 0;
padding: 0 16px;
}
.av-create-popup-toggle-label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
user-select: none;
}
.av-create-popup-toggle-text {
font-size: 14px;
color: #4b5563;
}
.av-create-popup-custom-fields {
margin: 16px 0;
padding: 0 16px;
}
.av-create-popup-field-group {
margin-top: 16px;
}
.av-create-popup-field-group label {
display: block;
margin-bottom: 0.5rem;
color: #eee;
font-size: 0.875rem;
font-weight: 500;
}
.av-create-popup-input-error {
border-color: #ef4444 !important;
box-shadow: 0 0 0 1px #ef4444 !important;
}
.av-create-popup-error-text {
color: #ef4444;
font-size: 0.875rem;
margin-top: 0.25rem;
margin-left: 5px;
}
.av-create-popup-password-preview {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
}
.av-create-popup-password-preview input {
flex: 1;
width: 100%;
}
.av-create-popup-regenerate-btn,
.av-create-popup-visibility-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 9px;
background: #374151;
border: none;
border-radius: 4px;
cursor: pointer;
color: #e5e7eb;
transition: background-color 0.2s ease;
flex-shrink: 0;
}
.av-create-popup-regenerate-btn:hover,
.av-create-popup-visibility-btn:hover {
background-color: #4b5563;
}
.av-create-popup-regenerate-btn .av-icon {
width: 16px;
height: 16px;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.av-create-popup-visibility-btn .av-icon {
width: 18px;
height: 18px;
stroke: currentColor;
stroke-width: 1.5;
fill: none;
}
.av-create-popup-error {
margin-top: 16px;
padding: 8px 12px;
background-color: #fee2e2;
color: #dc2626;
border-radius: 4px;
font-size: 14px;
animation: fadeIn 0.2s ease-in-out;
}
.av-create-popup-actions {
display: flex;
justify-content: flex-end;
gap: 12px;
margin-top: 24px;
}
.av-create-popup-back {
padding: 8px 16px;
border-radius: 6px;
border: 1px solid #374151;
background: transparent;
color: #f8f9fa;
cursor: pointer;
font-size: 14px;
transition: all 0.2s ease;
}
.av-create-popup-back:hover {
background: #374151;
}
.av-create-popup-cancel {
padding: 8px 16px;
border-radius: 6px;
border: 1px solid #374151;
background: transparent;
color: #f8f9fa;
cursor: pointer;
font-size: 14px;
transition: all 0.2s ease;
}
.av-create-popup-cancel:hover {
background: #374151;
}
.av-create-popup-save {
padding: 8px 16px;
border-radius: 6px;
border: none;
background: #d68338;
color: white;
cursor: pointer;
font-size: 14px;
transition: all 0.2s ease;
}
.av-create-popup-save:hover {
background: #c97731;
transform: translateY(-1px);
}
/* SVG Icons */
.av-icon {
width: 16px;
height: 16px;
fill: none;
stroke: currentColor;
stroke-width: 2;
}
.av-icon-lock {
width: 20px;
height: 20px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
/* Form Icon Styles */
.av-overlay-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 2147483640;
}
.av-input-icon {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
cursor: pointer;
width: 24px;
height: 24px;
pointer-events: auto;
opacity: 0;
transition: opacity 0.2s ease-in-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeOut {
0% { opacity: 1; transform: scale(1.02); }
100% { opacity: 0; transform: scale(1); }
}
/* Create Popup Styles */
.av-create-popup-header {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.av-create-popup-title-container {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
justify-content: center;
cursor: pointer;
padding: 4px 8px;
border-radius: 4px;
transition: background-color 0.2s;
}
.av-create-popup-title-wrapper {
display: flex;
align-items: center;
gap: 8px;
color: #d68338;
}
.av-create-popup-title-wrapper .av-icon {
width: 20px;
height: 20px;
stroke-width: 1.5;
stroke-linecap: round;
stroke-linejoin: round;
}
.av-create-popup-title-wrapper .av-create-popup-title {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #f8f9fa;
}
.av-create-popup-title-container:hover {
background-color: #374151;
}
.av-create-popup-mode-dropdown {
background: none;
border: none;
padding: 4px;
cursor: pointer;
color: #9ca3af;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: background-color 0.2s;
}
.av-create-popup-mode-dropdown:hover {
background-color: #4b5563;
}
.av-create-popup-mode-dropdown .av-icon {
width: 16px;
height: 16px;
}
.av-create-popup-mode-dropdown-menu {
position: absolute;
left: 50%;
transform: translateX(-50%);
background: #1f2937;
border: 1px solid #374151;
border-radius: 8px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
z-index: 1000;
min-width: 280px;
}
.av-create-popup-mode-dropdown-menu::before {
content: '';
position: absolute;
top: -6px;
left: 50%;
width: 12px;
height: 12px;
background: #1f2937;
border-left: 1px solid #374151;
border-top: 1px solid #374151;
transform: translateX(-50%) rotate(45deg);
}
.av-create-popup-mode-option {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
width: 100%;
border: none;
background: none;
cursor: pointer;
text-align: left;
transition: background-color 0.2s;
position: relative;
z-index: 100;
}
.av-create-popup-mode-option:hover {
background-color: #374151;
}
.av-create-popup-mode-option .av-create-popup-mode-icon {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
background-color: #374151;
border-radius: 8px;
color: #d68338;
}
.av-create-popup-mode-option .av-create-popup-mode-content {
flex: 1;
}
.av-create-popup-mode-option .av-create-popup-mode-content h4 {
margin: 0;
font-size: 14px;
font-weight: 600;
color: #f8f9fa;
}
.av-create-popup-mode-option .av-create-popup-mode-content p {
margin: 4px 0 0;
font-size: 12px;
color: #9ca3af;
}
/* Context Menu */
.av-context-menu {
position: fixed;
background: #1f2937;
border: 1px solid #374151;
border-radius: 6px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -1px rgba(0, 0, 0, 0.06);
z-index: 2147483647;
min-width: 180px;
padding: 4px;
margin-top: 4px;
}
.av-context-menu-item {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 8px 12px;
border: none;
background: none;
color: #e5e7eb;
font-size: 14px;
text-align: left;
cursor: pointer;
border-radius: 4px;
transition: background-color 0.2s;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.av-context-menu-item:hover {
background-color: #374151;
}
.av-context-menu-item .av-icon {
width: 16px;
height: 16px;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}

View File

@@ -0,0 +1,112 @@
import React, { useState, useEffect } from 'react';
import { HashRouter as Router, Routes, Route } from 'react-router-dom';
import { useAuth } from '@/entrypoints/popup/context/AuthContext';
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
import Header from '@/entrypoints/popup/components/Layout/Header';
import BottomNav from '@/entrypoints/popup/components/Layout/BottomNav';
import AuthSettings from '@/entrypoints/popup/pages/AuthSettings';
import CredentialsList from '@/entrypoints/popup/pages/CredentialsList';
import EmailsList from '@/entrypoints/popup/pages/EmailsList';
import LoadingSpinner from '@/entrypoints/popup/components/LoadingSpinner';
import Home from '@/entrypoints/popup/pages/Home';
import CredentialDetails from '@/entrypoints/popup/pages/CredentialDetails';
import EmailDetails from '@/entrypoints/popup/pages/EmailDetails';
import Settings from '@/entrypoints/popup/pages/Settings';
import GlobalStateChangeHandler from '@/entrypoints/popup/components/GlobalStateChangeHandler';
import { useLoading } from '@/entrypoints/popup/context/LoadingContext';
import Logout from '@/entrypoints/popup/pages/Logout';
import '@/entrypoints/popup/style.css';
/**
* Route configuration.
*/
type RouteConfig = {
path: string;
element: React.ReactNode;
showBackButton?: boolean;
title?: string;
};
/**
* App component.
*/
const App: React.FC = () => {
const authContext = useAuth();
const { isInitialLoading } = useLoading();
const [isLoading, setIsLoading] = useMinDurationLoading(true, 150);
const [message, setMessage] = useState<string | null>(null);
// Add these route configurations
const routes: RouteConfig[] = [
{ path: '/', element: <Home />, showBackButton: false },
{ path: '/auth-settings', element: <AuthSettings />, showBackButton: true, title: 'Settings' },
{ path: '/credentials', element: <CredentialsList />, showBackButton: false },
{ path: '/credentials/:id', element: <CredentialDetails />, showBackButton: true, title: 'Credential details' },
{ path: '/emails', element: <EmailsList />, showBackButton: false },
{ path: '/emails/:id', element: <EmailDetails />, showBackButton: true, title: 'Email details' },
{ path: '/settings', element: <Settings />, showBackButton: false },
{ path: '/logout', element: <Logout />, showBackButton: false },
];
useEffect(() => {
if (!isInitialLoading) {
setIsLoading(false);
}
}, [isInitialLoading, setIsLoading]);
/**
* Print global message if it exists.
*/
useEffect(() => {
if (authContext.globalMessage) {
setMessage(authContext.globalMessage);
} else {
setMessage(null);
}
}, [authContext, authContext.globalMessage]);
return (
<Router>
<div className="min-h-screen min-w-[350px] bg-white dark:bg-gray-900 flex flex-col">
{isLoading && (
<div className="fixed inset-0 bg-white dark:bg-gray-900 z-50 flex items-center justify-center">
<LoadingSpinner />
</div>
)}
<GlobalStateChangeHandler />
<Header
routes={routes}
/>
<main
className="flex-1 overflow-y-auto bg-gray-100 dark:bg-gray-900"
style={{
paddingTop: '64px',
height: 'calc(100% - 120px)',
maxHeight: '600px',
}}
>
<div className="p-4 mb-16">
{message && (
<p className="text-red-500 mb-4">{message}</p>
)}
<Routes>
{routes.map((route) => (
<Route
key={route.path}
path={route.path}
element={route.element}
/>
))}
</Routes>
</div>
</main>
<BottomNav />
</div>
</Router>
);
};
export default App;

View File

@@ -0,0 +1,35 @@
import React from 'react';
type ButtonProps = {
onClick?: () => void;
children: React.ReactNode;
type?: 'button' | 'submit' | 'reset';
variant?: 'primary' | 'secondary';
};
/**
* Button component
*/
const Button: React.FC<ButtonProps> = ({
onClick,
children,
type = 'button',
variant = 'primary'
}) => {
const colorClasses = {
primary: 'bg-primary-500 hover:bg-primary-600',
secondary: 'bg-gray-500 hover:bg-gray-600'
};
return (
<button
className={`${colorClasses[variant]} text-white font-medium rounded-lg px-4 py-2 text-sm w-full`}
onClick={onClick}
type={type}
>
{children}
</button>
);
};
export default Button;

View File

@@ -0,0 +1,80 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Credential } from '@/utils/types/Credential';
import SqliteClient from '@/utils/SqliteClient';
type CredentialCardProps = {
credential: Credential;
};
/**
* CredentialCard component
*
* This component displays a credential card with a service name, username, and email.
* It allows the user to navigate to the credential details page when clicked.
*
*/
const CredentialCard: React.FC<CredentialCardProps> = ({ credential }) => {
const navigate = useNavigate();
/**
* Get the display text for the credential
* @param cred - The credential to get the display text for
* @returns The display text for the credential
*/
const getDisplayText = (cred: Credential): string => {
let returnValue = '';
// Show username if available
if (cred.Username) {
returnValue = cred.Username;
}
// Show email if username is not available
if (cred.Alias?.Email) {
returnValue = cred.Alias.Email;
}
// Trim the return value to max. 33 characters.
return returnValue.length > 33 ? returnValue.slice(0, 30) + '...' : returnValue;
};
/**
* Get the service name for a credential, trimming it to maximum length so it doesn't overflow the UI.
*/
const getCredentialServiceName = (cred: Credential): string => {
let returnValue = 'Untitled';
if (cred.ServiceName) {
returnValue = cred.ServiceName;
}
// Trim the return value to max. 33 characters.
return returnValue.length > 33 ? returnValue.slice(0, 30) + '...' : returnValue;
};
return (
<li>
<button
onClick={() => navigate(`/credentials/${credential.Id}`)}
className="w-full p-2 border dark:border-gray-600 rounded flex items-center bg-white dark:bg-gray-800 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<img
src={SqliteClient.imgSrcFromBytes(credential.Logo)}
alt={credential.ServiceName}
className="w-8 h-8 mr-2 flex-shrink-0"
onError={(e) => {
const target = e.target as HTMLImageElement;
target.src = '/assets/images/service-placeholder.webp';
}}
/>
<div className="text-left">
<p className="font-medium text-gray-900 dark:text-white">{getCredentialServiceName(credential)}</p>
<p className="text-sm text-gray-600 dark:text-gray-400">{getDisplayText(credential)}</p>
</div>
</button>
</li>
);
};
export default CredentialCard;

View File

@@ -0,0 +1,65 @@
import React from 'react';
import { Credential } from '@/utils/types/Credential';
import { FormInputCopyToClipboard } from '@/entrypoints/popup/components/FormInputCopyToClipboard';
import { IdentityHelperUtils } from '@/utils/shared/identity-generator';
type AliasBlockProps = {
credential: Credential;
}
/**
* Render the alias block.
*/
const AliasBlock: React.FC<AliasBlockProps> = ({ credential }) => {
const hasFirstName = Boolean(credential.Alias?.FirstName?.trim());
const hasLastName = Boolean(credential.Alias?.LastName?.trim());
const hasNickName = Boolean(credential.Alias?.NickName?.trim());
const hasBirthDate = IdentityHelperUtils.isValidBirthDate(credential.Alias?.BirthDate);
if (!hasFirstName && !hasLastName && !hasNickName && !hasBirthDate) {
return null;
}
return (
<div className="space-y-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Alias</h2>
{(hasFirstName || hasLastName) && (
<FormInputCopyToClipboard
id="fullName"
label="Full Name"
value={[credential.Alias?.FirstName, credential.Alias?.LastName].filter(Boolean).join(' ')}
/>
)}
{hasFirstName && (
<FormInputCopyToClipboard
id="firstName"
label="First Name"
value={credential.Alias?.FirstName ?? ''}
/>
)}
{hasLastName && (
<FormInputCopyToClipboard
id="lastName"
label="Last Name"
value={credential.Alias?.LastName ?? ''}
/>
)}
{hasBirthDate && (
<FormInputCopyToClipboard
id="birthDate"
label="Birth Date"
value={IdentityHelperUtils.normalizeBirthDateForDisplay(credential.Alias?.BirthDate)}
/>
)}
{hasNickName && (
<FormInputCopyToClipboard
id="nickName"
label="Nickname"
value={credential.Alias?.NickName ?? ''}
/>
)}
</div>
);
};
export default AliasBlock;

View File

@@ -0,0 +1,18 @@
import React from 'react';
import { EmailPreview } from '@/entrypoints/popup/components/EmailPreview';
type EmailBlockProps = {
email: string;
isSupported: boolean;
}
/**
* Render the email block.
*/
const EmailBlock: React.FC<EmailBlockProps> = ({ email, isSupported }) => (
<>
{isSupported && <EmailPreview email={email} />}
</>
);
export default EmailBlock;

View File

@@ -0,0 +1,60 @@
import React from 'react';
import { Credential } from '@/utils/types/Credential';
import SqliteClient from '@/utils/SqliteClient';
type HeaderBlockProps = {
credential: Credential;
onOpenNewPopup: () => void;
}
/**
* Render the header block.
*/
const HeaderBlock: React.FC<HeaderBlockProps> = ({ credential, onOpenNewPopup }) => (
<div className="mb-6">
<div className="flex items-center justify-between">
<div className="flex items-center">
<img
src={SqliteClient.imgSrcFromBytes(credential.Logo)}
alt={credential.ServiceName}
className="w-12 h-12 rounded-lg mr-4"
/>
<div>
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">{credential.ServiceName}</h1>
{credential.ServiceUrl && (
<a
href={credential.ServiceUrl}
target="_blank"
rel="noopener noreferrer"
className="text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 break-all"
>
{credential.ServiceUrl}
</a>
)}
</div>
</div>
<button
onClick={onOpenNewPopup}
className="text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white"
title="Open in new window"
>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"
/>
</svg>
</button>
</div>
</div>
);
export default HeaderBlock;

View File

@@ -0,0 +1,50 @@
import React from 'react';
import { Credential } from '@/utils/types/Credential';
import { FormInputCopyToClipboard } from '@/entrypoints/popup/components/FormInputCopyToClipboard';
type LoginCredentialsBlockProps = {
credential: Credential;
}
/**
* Render the login credentials block.
*/
const LoginCredentialsBlock: React.FC<LoginCredentialsBlockProps> = ({ credential }) => {
const email = credential.Alias?.Email?.trim();
const username = credential.Username?.trim();
const password = credential.Password?.trim();
if (!email && !username && !password) {
return null;
}
return (
<div className="space-y-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Login credentials</h2>
{email && (
<FormInputCopyToClipboard
id="email"
label="Email"
value={email}
/>
)}
{username && (
<FormInputCopyToClipboard
id="username"
label="Username"
value={username}
/>
)}
{password && (
<FormInputCopyToClipboard
id="password"
label="Password"
value={password}
type="password"
/>
)}
</div>
);
};
export default LoginCredentialsBlock;

View File

@@ -0,0 +1,42 @@
import React from 'react';
type NotesBlockProps = {
notes: string | undefined;
}
/**
* Convert URLs in text to clickable links.
*/
const convertUrlsToLinks = (text: string): string => {
const urlPattern = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/g;
return text.replace(urlPattern, (url) => {
const href = url.startsWith('http') ? url : `http://${url}`;
return `<a href="${href}" target="_blank" rel="noopener noreferrer" class="text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300">${url}</a>`;
});
};
/**
* Render the notes block.
*/
const NotesBlock: React.FC<NotesBlockProps> = ({ notes }) => {
if (!notes) {
return null;
}
const formattedNotes = convertUrlsToLinks(notes);
return (
<div>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Notes</h2>
<div className="p-4 bg-gray-50 rounded-lg dark:bg-gray-700">
<p
className="text-gray-900 dark:text-gray-100 whitespace-pre-wrap"
dangerouslySetInnerHTML={{ __html: formattedNotes }}
/>
</div>
</div>
);
};
export default NotesBlock;

View File

@@ -0,0 +1,194 @@
import React, { useState, useEffect } from 'react';
import { useDb } from '@/entrypoints/popup/context/DbContext';
import { TotpCode } from '@/utils/types/TotpCode';
import * as OTPAuth from 'otpauth';
type TotpBlockProps = {
credentialId: string;
}
/**
* This component shows TOTP codes for a credential.
*/
const TotpBlock: React.FC<TotpBlockProps> = ({ credentialId }) => {
const [totpCodes, setTotpCodes] = useState<TotpCode[]>([]);
const [loading, setLoading] = useState(true);
const [currentCodes, setCurrentCodes] = useState<Record<string, string>>({});
const [copiedId, setCopiedId] = useState<string | null>(null);
const dbContext = useDb();
/**
* Gets the remaining seconds for the TOTP code.
*/
const getRemainingSeconds = (step = 30): number => {
const totp = new OTPAuth.TOTP({
secret: 'dummy', // We only need this for timing calculations
algorithm: 'SHA1',
digits: 6,
period: step
});
return totp.period - (Math.floor(Date.now() / 1000) % totp.period);
};
/**
* Gets the remaining percentage for the TOTP code.
*/
const getRemainingPercentage = (): number => {
const remaining = getRemainingSeconds();
// Invert the percentage so it counts down instead of up
return Math.floor(((30.0 - remaining) / 30.0) * 100);
};
/**
* Generates a TOTP code for a given secret key.
*/
const generateTotpCode = (secretKey: string): string => {
try {
const totp = new OTPAuth.TOTP({
secret: secretKey,
algorithm: 'SHA1',
digits: 6,
period: 30
});
return totp.generate();
} catch (error) {
console.error('Error generating TOTP code:', error);
return 'Error';
}
};
/**
* Copies a TOTP code to the clipboard.
*/
const copyToClipboard = async (code: string, id: string): Promise<void> => {
try {
await navigator.clipboard.writeText(code);
setCopiedId(id);
// Reset copied state after 2 seconds
setTimeout(() => {
setCopiedId(null);
}, 2000);
} catch (error) {
console.error('Failed to copy:', error);
}
};
useEffect(() => {
/**
* Loads the TOTP codes for the credential.
*/
const loadTotpCodes = async (): Promise<void> => {
if (!dbContext?.sqliteClient) {
return;
}
try {
const codes = dbContext.sqliteClient.getTotpCodesForCredential(credentialId);
setTotpCodes(codes);
} catch (error) {
console.error('Error loading TOTP codes:', error);
} finally {
setLoading(false);
}
};
loadTotpCodes();
}, [credentialId, dbContext?.sqliteClient]);
useEffect(() => {
/**
* Updates the current TOTP codes.
*/
const updateTotpCodes = (prevCodes: Record<string, string>): Record<string, string> => {
const newCodes: Record<string, string> = {};
totpCodes.forEach(code => {
const generatedCode = generateTotpCode(code.SecretKey);
// Only update if we have a valid code
if (generatedCode !== 'Error') {
newCodes[code.Id] = generatedCode;
} else {
// Keep the previous code if there's an error
newCodes[code.Id] = prevCodes[code.Id] ?? 'Error';
}
});
return newCodes;
};
// Generate initial codes
const initialCodes: Record<string, string> = {};
totpCodes.forEach(code => {
initialCodes[code.Id] = generateTotpCode(code.SecretKey);
});
setCurrentCodes(initialCodes);
// Set up interval to refresh codes
const intervalId = setInterval(() => {
setCurrentCodes(updateTotpCodes);
}, 1000);
// Clean up interval on unmount or when totpCodes change
return () : void => {
clearInterval(intervalId);
};
}, [totpCodes]);
if (loading) {
return (
<div className="text-gray-500 dark:text-gray-400 mb-4">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">Two-factor authentication</h2>
Loading TOTP codes...
</div>
);
}
if (totpCodes.length === 0) {
return null;
}
return (
<div className="mb-4">
<div className="space-y-2">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">Two-factor authentication</h2>
<div className="grid grid-cols-1 gap-2">
{totpCodes.map(totpCode => (
<button
key={totpCode.Id}
className={`w-full text-left p-2 ps-3 pe-3 rounded bg-white dark:bg-gray-800 shadow hover:shadow-md transition-all border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700`}
onClick={() => copyToClipboard(currentCodes[totpCode.Id], totpCode.Id)}
aria-label={`Copy ${totpCode.Name} code`}
>
<div className="flex justify-between items-center gap-2">
<div className="flex items-center flex-1">
<h4 className="text-sm font-medium text-gray-900 dark:text-white">{totpCode.Name}</h4>
</div>
<div className="flex items-center gap-2">
<div className="flex flex-col items-end">
<span className="text-lg font-bold text-gray-900 dark:text-white">
{currentCodes[totpCode.Id]}
</span>
<div className="text-xs">
{copiedId === totpCode.Id ? (
<span className="text-green-600 dark:text-green-400">Copied!</span>
) : (
<span className="text-gray-500 dark:text-gray-400">{getRemainingSeconds()}s</span>
)}
</div>
</div>
<div className="w-1 h-6 bg-gray-200 rounded-full dark:bg-gray-600">
<div
className="bg-blue-600 rounded-full transition-all"
style={{ height: `${getRemainingPercentage()}%`, width: '100%' }}
/>
</div>
</div>
</div>
</button>
))}
</div>
</div>
</div>
);
};
export default TotpBlock;

View File

@@ -0,0 +1,15 @@
import HeaderBlock from './HeaderBlock';
import EmailBlock from './EmailBlock';
import TotpBlock from './TotpBlock';
import LoginCredentialsBlock from './LoginCredentialsBlock';
import AliasBlock from './AliasBlock';
import NotesBlock from './NotesBlock';
export {
HeaderBlock,
EmailBlock,
TotpBlock,
LoginCredentialsBlock,
AliasBlock,
NotesBlock
};

View File

@@ -0,0 +1,172 @@
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { storage } from '#imports';
import { useWebApi } from '@/entrypoints/popup/context/WebApiContext';
import { useDb } from '@/entrypoints/popup/context/DbContext';
import { EncryptionUtility } from '@/utils/EncryptionUtility';
import { MailboxEmail } from '@/utils/types/webapi/MailboxEmail';
import { AppInfo } from '@/utils/AppInfo';
type EmailPreviewProps = {
email: string;
}
/**
* This component shows a preview of the latest emails in the inbox.
*/
export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) => {
const [emails, setEmails] = useState<MailboxEmail[]>([]);
const [loading, setLoading] = useState(true);
const [lastEmailId, setLastEmailId] = useState<number>(0);
const [isSpamOk, setIsSpamOk] = useState(false);
const webApi = useWebApi();
const dbContext = useDb();
/**
* Checks if the email is a public domain.
*/
const isPublicDomain = async (emailAddress: string): Promise<boolean> => {
// Get metadata from storage
const publicEmailDomains = await storage.getItem('session:publicEmailDomains') as string[] ?? [];
return publicEmailDomains.some(domain => emailAddress.toLowerCase().endsWith(domain));
};
useEffect(() => {
/**
* Loads the latest emails from the server and decrypts them locally if needed.
*/
const loadEmails = async (): Promise<void> => {
try {
const isPublic = await isPublicDomain(email);
setIsSpamOk(isPublic);
if (isPublic) {
// For public domains (SpamOK), use the SpamOK API directly
const emailPrefix = email.split('@')[0];
const response = await fetch(`https://api.spamok.com/v2/EmailBox/${emailPrefix}`, {
headers: {
'X-Asdasd-Platform-Id': 'av-chrome',
'X-Asdasd-Platform-Version': AppInfo.VERSION,
}
});
const data = await response.json();
// Only show the latest 2 emails to save space in UI
const latestMails = data?.mails
?.toSorted((a: MailboxEmail, b: MailboxEmail) =>
new Date(b.dateSystem).getTime() - new Date(a.dateSystem).getTime())
?.slice(0, 2) ?? [];
if (loading && latestMails.length > 0) {
setLastEmailId(latestMails[0].id);
}
setEmails(latestMails);
} else {
// For private domains, use existing encrypted email logic
const response = await webApi.get(`EmailBox/${email}`);
const data = response as { mails: MailboxEmail[] };
// Only show the latest 2 emails to save space in UI
const latestMails = data.mails
.toSorted((a, b) => new Date(b.dateSystem).getTime() - new Date(a.dateSystem).getTime())
.slice(0, 2);
if (latestMails) {
// Loop through all emails and decrypt them locally
const decryptedEmails: MailboxEmail[] = await EncryptionUtility.decryptEmailList(
latestMails,
dbContext.sqliteClient!.getAllEncryptionKeys()
);
if (loading && decryptedEmails.length > 0) {
setLastEmailId(decryptedEmails[0].id);
}
setEmails(decryptedEmails);
}
}
} catch (err) {
console.error('Error loading emails:', err);
}
setLoading(false);
};
loadEmails();
// Set up auto-refresh interval
const interval = setInterval(loadEmails, 2000);
return () : void => clearInterval(interval);
}, [email, loading, webApi, dbContext]);
if (loading) {
return (
<div className="text-gray-500 dark:text-gray-400 mb-4">
<div className="flex items-center gap-2 mb-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">Recent emails</h2>
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
</div>
Loading emails...
</div>
);
}
if (emails.length === 0) {
return (
<div className="text-gray-500 dark:text-gray-400 mb-4">
<div className="flex items-center gap-2 mb-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">Recent emails</h2>
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
</div>
No emails received yet.
</div>
);
}
return (
<div className="space-y-2 mb-4">
<div className="flex items-center gap-2 mb-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">Recent emails</h2>
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
</div>
{emails.map((mail) => (
isSpamOk ? (
<a
key={mail.id}
href={`https://spamok.com/${email.split('@')[0]}/${mail.id}`}
target="_blank"
rel="noopener noreferrer"
className={`flex justify-between items-center p-2 ps-3 pe-3 rounded cursor-pointer bg-white dark:bg-gray-800 shadow hover:shadow-md transition-all border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 ${
mail.id > lastEmailId ? 'bg-yellow-50 dark:bg-yellow-900/30' : ''
}`}
>
<div className="truncate flex-1">
<span className="text-sm text-gray-900 dark:text-white">
{mail.subject.substring(0, 30)}{mail.subject.length > 30 ? '...' : ''}
</span>
</div>
<div className="text-xs text-gray-500 dark:text-gray-400 ml-2">
{new Date(mail.dateSystem).toLocaleDateString()}
</div>
</a>
) : (
<Link
key={mail.id}
to={`/emails/${mail.id}`}
className={`flex justify-between items-center p-2 ps-3 pe-3 rounded cursor-pointer bg-white dark:bg-gray-800 shadow hover:shadow-md transition-all border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 ${
mail.id > lastEmailId ? 'bg-yellow-50 dark:bg-yellow-900/30' : ''
}`}
>
<span className="truncate flex-1">
<span className="text-sm text-gray-900 dark:text-white">
{mail.subject.substring(0, 30)}{mail.subject.length > 30 ? '...' : ''}
</span>
</span>
<span className="text-xs text-gray-500 dark:text-gray-400 ml-2">
{new Date(mail.dateSystem).toLocaleDateString()}
</span>
</Link>
)
))}
</div>
);
};

View File

@@ -0,0 +1,90 @@
import React, { useState, useEffect } from 'react';
import { ClipboardCopyService } from '@/entrypoints/popup/utils/ClipboardCopyService';
/**
* Form input copy to clipboard props.
*/
type FormInputCopyToClipboardProps = {
id: string;
label: string;
value: string;
type?: 'text' | 'password';
}
const clipboardService = new ClipboardCopyService();
/**
* Form input copy to clipboard component.
*/
export const FormInputCopyToClipboard: React.FC<FormInputCopyToClipboardProps> = ({
id,
label,
value,
type = 'text'
}) => {
const [showPassword, setShowPassword] = useState(false);
const [copied, setCopied] = useState(false);
useEffect(() => {
const unsubscribe = clipboardService.subscribe((copiedId) : void => {
setCopied(copiedId === id);
});
return () : void => {
unsubscribe();
};
}, [id]);
/**
* Copy to clipboard.
*/
const copyToClipboard = async () : Promise<void> => {
try {
await navigator.clipboard.writeText(value);
clipboardService.setCopied(id);
// Reset copied state after 2 seconds
setTimeout(() => {
if (clipboardService.getCopiedId() === id) {
clipboardService.setCopied('');
}
}, 2000);
} catch (err) {
console.error('Failed to copy text:', err);
}
};
return (
<div>
<label htmlFor={id} className="block mb-2 text-sm font-medium text-gray-700 dark:text-gray-300">
{label}
</label>
<div className="relative">
<input
type={type === 'password' && !showPassword ? 'password' : 'text'}
id={id}
readOnly
value={value}
onClick={copyToClipboard}
className={`w-full px-3 py-2.5 bg-white border ${
copied ? 'border-green-500 border-2' : 'border-gray-300'
} text-gray-900 sm:text-sm rounded-lg shadow-sm focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:placeholder-gray-400`}
/>
<div className="absolute right-2 top-1/2 -translate-y-1/2 flex items-center gap-2">
{copied && (
<span className="text-green-500 dark:text-green-400">
Copied!
</span>
)}
{type === 'password' && (
<button
onClick={() => setShowPassword(!showPassword)}
className="px-3 py-1 text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white transition-colors duration-200"
>
{showPassword ? 'Hide' : 'Show'}
</button>
)}
</div>
</div>
</div>
);
};

Some files were not shown because too many files have changed in this diff Show More