1
0
mirror of https://github.com/bitwarden/web synced 2025-12-06 00:03:28 +00:00

Compare commits

...

1089 Commits

Author SHA1 Message Date
Kyle Spearrin
eaa6bc12ce bump version 2020-03-12 21:16:53 -04:00
Kyle Spearrin
b3337df774 New Crowdin translations (#492)
* New translations messages.json (Afrikaans)

* New translations messages.json (Hebrew)

* New translations messages.json (Ukrainian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (Greek)

* New translations messages.json (Belarusian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Esperanto)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Catalan)

* New translations messages.json (Bulgarian)

* New translations messages.json (Vietnamese)
2020-03-12 21:14:55 -04:00
Kyle Spearrin
6c8c5bcde6 update jslib 2020-03-12 20:27:50 -04:00
Vincent Salucci
d255f6add4 Enforce passphrase policy (#490)
* Update jslib and initial commit for passphrase policy

* Removed unused strings

* Pulling in latest jslib (44b86f5 -> 36241e9)

* Made revision requests

Co-authored-by: Vincent Salucci <vsalucci@bitwarden.com>
2020-03-11 10:35:12 -05:00
brunohunziker
84dde72990 Total number of organization users added (#489) 2020-03-10 12:06:25 -04:00
Kyle Spearrin
5dfeee548d New Crowdin translations (#485)
* New translations messages.json (Turkish)

* New translations messages.json (Polish)

* New translations messages.json (German)

* New translations messages.json (Ukrainian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Greek)

* New translations messages.json (German)

* New translations messages.json (Estonian)

* New translations messages.json (Danish)

* New translations messages.json (Bulgarian)
2020-03-06 11:28:34 -05:00
Kyle Spearrin
09516b4d4e init masterPassMinComplexity as null 2020-03-05 22:19:46 -05:00
Kyle Spearrin
b7b74d8f1f New Crowdin translations (#484)
* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Catalan)
2020-03-05 11:51:31 -05:00
Kyle Spearrin
80d3cd3126 New Crowdin translations (#483)
* New translations messages.json (Portuguese)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (Dutch)

* New translations messages.json (Chinese Simplified)
2020-03-05 11:47:32 -05:00
Kyle Spearrin
bbd416ba24 New Crowdin translations (#482)
* New translations messages.json (Afrikaans)

* New translations messages.json (Hebrew)

* New translations messages.json (Ukrainian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (Greek)

* New translations messages.json (Belarusian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Esperanto)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Catalan)

* New translations messages.json (Bulgarian)

* New translations messages.json (Vietnamese)

* New translations messages.json (Portuguese)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Hungarian)

* New translations messages.json (Dutch)
2020-03-05 09:38:47 -05:00
Kyle Spearrin
75563660f0 update package lock 2020-03-05 09:22:08 -05:00
Kyle Spearrin
c2197bcc53 bump version 2020-03-05 09:18:04 -05:00
Kyle Spearrin
12114c786b add select option to password score list 2020-03-04 16:00:23 -05:00
Kyle Spearrin
73c192ad18 update jslib and swal2 styles 2020-03-04 14:14:27 -05:00
Kyle Spearrin
465564325e remove p tags 2020-03-04 10:57:00 -05:00
Vincent Salucci
7c0d093be5 Fix password score display switch statement (#481) 2020-03-04 09:21:52 -06:00
Kyle Spearrin
a1fbe6b970 no bottom margin 2020-03-03 23:23:40 -05:00
Vincent Salucci
305d86f765 Update complexity score display (#479)
* Update complexity score

* Simplifying switch statement
2020-03-03 15:37:54 -06:00
Vincent Salucci
e7e5816ded Enforce Master Password Policies (Change/Register) (#478)
* Initial commit for change password mp policy enforcement

* Initial commit of mp policy for registering

* Testing Register component

* Final testing complete

* Reverting service module URLs

* Requested changes and build fix

* Updated submit function
2020-03-03 10:20:28 -06:00
Vincent Salucci
cd9b1b906c Update jslib (6210396 -> da9b9b4) (#477) 2020-03-02 14:25:00 -06:00
MartB
0b5a74aa9f sweetalert: ported to sweetalert2 and simplified code. (#465)
No styling changes besides making the "primary" button-text bold (aligned with desktop app)
2020-03-02 13:52:09 -05:00
Vincent Salucci
c3407ac35a Update jslib (6c52942..6210396) (#476) 2020-03-02 11:40:58 -06:00
Kyle Spearrin
c9699647d7 load policies on register if org invite (#475) 2020-03-02 11:51:05 -05:00
Kyle Spearrin
aac011d3b3 react to jslib #77 changes (#474) 2020-02-28 16:57:54 -05:00
Kyle Spearrin
e2108ff85b Show reason for invite accept failure if available (#473) 2020-02-28 15:27:02 -05:00
Vincent Salucci
5c492f893b Show policy in effect banner for password generator (#472)
* Show Password Generator Policy in effect banner

* Extra character cleanup

* Updated back to base setUrls

* Updated app-callout class to info
2020-02-28 13:48:48 -06:00
Vincent Salucci
2877b3c63d Update jslib (862057d -> 6c52942) (#471) 2020-02-28 11:15:43 -06:00
Kyle Spearrin
1d94185078 Add copy descriptions and warnings to policies (#470) 2020-02-27 13:07:33 -05:00
Vincent Salucci
a27eddae56 Enforce Password Generator Policy Options (#469)
* Initial commit for enforcing password generator policy options

* Revert to previous isDev URL setup
2020-02-26 18:32:57 -06:00
Vincent Salucci
5ed830205d Update jslib (98ae9b0 -> 862057d) (#468) 2020-02-26 17:04:58 -06:00
Kyle Spearrin
aeca6f04f9 encryptr instructions 2020-02-24 23:19:57 -05:00
Kyle Spearrin
c099ff7662 encryptr importer 2020-02-20 16:55:10 -05:00
Kyle Spearrin
83ba366558 Admin config for master password policy (#463)
* Admin config for master password policy

* UI cleanup and master pass options improvements

* ui tweaks
2020-02-19 21:25:46 -05:00
Vincent Salucci
6129fdb6e5 Update jslib (fd260df -> 98ae9b0) (#464) 2020-02-19 14:03:42 -06:00
Kyle Spearrin
8db66bf282 bitwarden inc. 2020-02-18 22:25:04 -05:00
Vincent Salucci
b7cd18b715 Allow organizational admins to assign clone ownership (#458) 2020-02-12 15:11:38 -06:00
Kyle Spearrin
6ed991593a deploy on master 2020-02-12 15:39:48 -05:00
Vincent Salucci
ccf3d49fc4 Implement Clone item functionality (personal/org) (#457)
* Clone personal/org items

* Removed ability to delete during clone process
2020-02-10 14:03:36 -05:00
Kyle Spearrin
7e95e44f1d add support for check payment method type 2020-02-07 16:48:46 -05:00
Vincent Salucci
a5de11d002 Update jslib (bb459ce -> 3b8df85) (#455) 2020-02-07 11:12:57 -05:00
Vincent Salucci
756bd82a46 Update jslib (3a40cb8 -> bb459ce) (#452) 2020-02-04 23:50:53 -05:00
Vincent Salucci
f9ce4a2f81 Update jslib (3d2e2cb -> 3a40cb8) and npm sub:pull script (#450) 2020-02-03 23:10:47 -05:00
Kyle Spearrin
088301c4be configure some policy data 2020-01-29 17:49:20 -05:00
Kyle Spearrin
f7f70408c9 update jslib and construct policy service 2020-01-28 22:42:20 -05:00
Kyle Spearrin
292d713423 symlink jslib on mac/lin 2020-01-27 12:46:25 -05:00
Kyle Spearrin
e02eadc9f7 remove angualr http and upgrade node-sass 2020-01-27 09:04:07 -05:00
Naoaki Iwakiri
6e66df59b7 Stop showing score 3 passwords as weak passwords (#445) 2020-01-27 08:30:19 -05:00
Kyle Spearrin
00b9f4cab6 set policy data to null 2020-01-20 08:59:06 -05:00
Kyle Spearrin
f6fb56229e policy edit 2020-01-20 08:57:55 -05:00
Kyle Spearrin
5b770084c9 policies enabled badge 2020-01-15 17:05:08 -05:00
Kyle Spearrin
a2472e0cf5 stub out policies management page 2020-01-15 16:51:42 -05:00
Kyle Spearrin
4de7b52044 stub out policies menu 2020-01-15 15:42:30 -05:00
Kyle Spearrin
1e100d1bf1 list height fix 2020-01-13 08:45:08 -05:00
Kyle Spearrin
d00fb9e0a5 update jslib 2020-01-13 07:49:16 -05:00
Kyle Spearrin
f5d8673ad4 update signalr client 2020-01-09 17:30:35 -05:00
Kyle Spearrin
bd2cba1f31 make hidden options button more accessible 2020-01-08 09:46:27 -05:00
Kyle Spearrin
45c07b7c39 Append copy textarea to model for all browsers 2019-12-31 14:35:58 -05:00
Kyle Spearrin
36244d58aa avast json importer 2019-12-20 13:30:01 -05:00
Kyle Spearrin
e968d5a2a5 update jslib 2019-11-26 08:35:08 -05:00
Kyle Spearrin
84df9cca87 codebook csv importer 2019-11-25 16:10:55 -05:00
Kyle Spearrin
e550989ce2 autocomplete off for search inputs 2019-11-25 08:20:53 -05:00
Kyle Spearrin
94edc1e284 fix twofactorauth.org API path. resolves #422 2019-10-29 08:04:09 -04:00
Kyle Spearrin
b9f8cad578 npm i 2019-10-21 08:48:41 -04:00
Kyle Spearrin
02eb382ae7 show enabled check always when 2fa enabled 2019-10-14 16:44:38 -04:00
Kyle Spearrin
1ecc092f08 update jslib 2019-10-11 13:38:51 -04:00
Kyle Spearrin
191fa922d2 more a11y updates 2019-10-11 11:47:41 -04:00
Kyle Spearrin
fb817f1ca7 more a11y fixes 2019-10-11 11:22:21 -04:00
Kyle Spearrin
9c2f128585 ally title work 2019-10-11 10:35:24 -04:00
Kyle Spearrin
9ebd700317 sr text for shared and attachments 2019-10-10 11:42:05 -04:00
Kyle Spearrin
9ab6cf31fd npm audit fix 2019-10-07 15:00:21 -04:00
Kyle Spearrin
bb5c114b8d New translations messages.json (Dutch) (#418) 2019-10-04 21:12:34 -04:00
Kyle Spearrin
1f2a724d32 New Crowdin translations (#417)
* New translations messages.json (Czech)

* New translations messages.json (Dutch)

* New translations messages.json (Hungarian)

* New translations messages.json (Portuguese, Brazilian)
2019-10-04 15:38:49 -04:00
Kyle Spearrin
9b28203757 buttercup csv importer 2019-10-04 10:11:34 -04:00
Kyle Spearrin
ac9f30f5f0 New Crowdin translations (#416)
* New translations messages.json (Bulgarian)

* New translations messages.json (Hebrew)

* New translations messages.json (Ukrainian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (Greek)

* New translations messages.json (Danish)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Esperanto)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Catalan)

* New translations messages.json (Afrikaans)

* New translations messages.json (Hungarian)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Vietnamese)
2019-10-02 10:35:45 -04:00
Kyle Spearrin
b13b0a66ce symlink 2019-09-25 16:10:13 -04:00
Kyle Spearrin
fcfdd5bc76 update jslib 2019-09-24 16:03:36 -04:00
Kyle Spearrin
cdbbc37d59 update jslib 2019-09-23 14:39:40 -04:00
Kyle Spearrin
4ba4af7cf9 bump version 2019-09-20 07:48:53 -04:00
Kyle Spearrin
89708d1fd6 limit sub and billing actions when using iap 2019-09-19 16:34:44 -04:00
Kyle Spearrin
6cb48c186e restrict changing payment method with iap 2019-09-19 15:46:33 -04:00
Kyle Spearrin
a1c9c47c89 blackberry importer 2019-09-11 17:08:33 -04:00
Kyle Spearrin
85cc2865b6 show locale name for language selection 2019-09-06 09:33:35 -04:00
Kyle Spearrin
2dc74b26f3 version bump 2019-08-30 14:19:52 -04:00
Kyle Spearrin
3d0ed43920 update jslib 2019-08-29 10:02:39 -04:00
Kyle Spearrin
dc54943a19 added hebrew language 2019-08-29 07:20:36 -04:00
Kyle Spearrin
c6ae5368fe securesafe and logmeonce csv importers 2019-08-26 10:12:36 -04:00
Kyle Spearrin
c947354517 locale string typo 2019-08-23 07:58:42 -04:00
Kyle Spearrin
076f01b65f data port 2019-08-20 17:23:27 -04:00
Kyle Spearrin
e37292a276 isViewOpen returns promise 2019-08-20 13:47:58 -04:00
Kyle Spearrin
7d76473580 sca card failure warning 2019-08-10 19:51:49 -04:00
Kyle Spearrin
8bafbbd2ff handle seats and storage adjustment for sca 2019-08-10 13:43:47 -04:00
Kyle Spearrin
80c5dff5ad adjust storage with payment intent/method handling 2019-08-10 13:00:07 -04:00
Kyle Spearrin
a4571a2617 handleCardPayment for incomplete payments 2019-08-09 23:57:30 -04:00
Kyle Spearrin
18608a8b63 fix lint issue 2019-08-09 11:14:46 -04:00
Kyle Spearrin
c9116ad7ab update jslib 2019-08-03 19:59:25 -04:00
Kyle Spearrin
d982902986 update jslib 2019-08-02 09:51:11 -04:00
Kyle Spearrin
3ab6868460 New Crowdin translations (#404)
* New translations messages.json (Afrikaans)

* New translations messages.json (Hungarian)

* New translations messages.json (Ukrainian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (Hebrew)

* New translations messages.json (Catalan)

* New translations messages.json (Greek)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Esperanto)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Vietnamese)

* New translations messages.json (Portuguese)
2019-07-26 21:45:48 -04:00
Kyle Spearrin
8d5974d0f8 docker health check 2019-07-26 11:59:59 -04:00
Kyle Spearrin
35a64afdf9 bump version 2019-07-25 20:48:14 -04:00
Kyle Spearrin
1ed850324d upgrade signalr libs 2019-07-25 20:42:26 -04:00
Kyle Spearrin
8f886df84f setComponentParameters for modal 2019-07-25 12:24:32 -04:00
Kyle Spearrin
55481b255b exportedOrganizationVault l10n 2019-07-12 17:15:40 -04:00
Kyle Spearrin
b0b9d8445e export vault event 2019-07-12 17:11:50 -04:00
Kyle Spearrin
3a2f04006f event log from copy on listing 2019-07-12 15:34:27 -04:00
Kyle Spearrin
1aacd4ece1 add ref for event service 2019-07-12 11:05:30 -04:00
Kyle Spearrin
f0e3e3b6f9 client events for edit page 2019-07-12 10:41:18 -04:00
Kyle Spearrin
26533713ff update jslib 2019-07-12 00:01:14 -04:00
Kyle Spearrin
b55d54eb5b syb out event log processing and event list desc 2019-07-11 22:03:12 -04:00
Kyle Spearrin
01cb57c9fb allow 2 mil KDF iterations 2019-07-06 23:35:38 -04:00
Kyle Spearrin
eb85464f8d New Crowdin translations (#398)
* New translations messages.json (English, United Kingdom)

* New translations messages.json (Estonian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Spanish)

* New translations messages.json (Polish)

* New translations messages.json (Catalan)

* New translations messages.json (Dutch)

* New translations messages.json (Japanese)

* New translations messages.json (Japanese)

* New translations messages.json (French)

* New translations messages.json (French)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Dutch)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Spanish)

* New translations messages.json (Italian)

* New translations messages.json (French)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Czech)

* New translations messages.json (French)

* New translations messages.json (Ukrainian)
2019-07-04 08:44:01 -04:00
Kyle Spearrin
d30fcf8dca New Crowdin translations (#397)
* New translations messages.json (Afrikaans)

* New translations messages.json (Hungarian)

* New translations messages.json (Ukrainian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (Hebrew)

* New translations messages.json (Catalan)

* New translations messages.json (Greek)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Esperanto)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Vietnamese)
2019-07-03 15:15:38 -04:00
Kyle Spearrin
004d14eaf4 fix html for checkbox on gen 2019-07-02 17:01:19 -04:00
Kyle Spearrin
d1a7c3390a capitalize and include num for pass gen 2019-07-02 16:54:46 -04:00
Kyle Spearrin
132c4139ad update jslib 2019-07-02 08:44:45 -04:00
Kyle Spearrin
0aa664fb4f re-set favicon state on login/unlock 2019-07-02 08:44:29 -04:00
Kyle Spearrin
d25dc1a23f myki importer 2019-06-28 23:17:22 -04:00
Kyle Spearrin
3d5f22b67d select one collection string 2019-06-26 17:45:53 -04:00
Kyle Spearrin
cf6ae951d2 events urls from web project 2019-06-25 12:19:18 -04:00
Kyle Spearrin
cca9384cd7 simlink for windows 2019-06-24 21:13:09 -04:00
Kyle Spearrin
e7b2557bcd logged in as on 2019-06-04 00:06:15 -04:00
Kyle Spearrin
dad084b309 update jslib 2019-05-27 10:31:28 -04:00
Kyle Spearrin
e7fea1b138 services on 2fa report with software tokens only 2019-05-27 08:15:02 -04:00
Kyle Spearrin
b24d7df789 clear desc 2019-05-16 08:00:22 -04:00
Kyle Spearrin
c2f801b6a9 add korean to i18n 2019-05-15 08:52:43 -04:00
Kyle Spearrin
20112688ab bump version 2019-05-11 21:12:58 -04:00
Kyle Spearrin
2a19bdd8d1 correct launch icon 2019-04-26 22:44:10 -04:00
Kyle Spearrin
2d95806feb import all botostrap except toasts 2019-04-26 22:29:51 -04:00
Kyle Spearrin
40da48a106 password wallet txt importer 2019-04-26 20:55:15 -04:00
Kyle Spearrin
df81d9fd5f launch uri adjustments 2019-04-26 09:12:37 -04:00
Shawn Beachy
1060775cad Add a "launch site" button directly to the list of ciphers (#384)
* Add a button to launch the primary uri for a site straight from the list.

* Take cues from the add-edit component on properly checking if we can launch.

* Move the launch button to the dropdown menu.

* Take LoginView as launch parameter instead of LoginUriView.
2019-04-26 09:07:57 -04:00
Kyle Spearrin
96cc9c681c switch to terser minimizer with safari 10 fix 2019-04-20 20:54:50 -04:00
Kyle Spearrin
b4200fba60 support authBlocked message 2019-04-18 10:11:04 -04:00
Kyle Spearrin
2ded5228cb change plan is only for free subs 2019-04-17 11:06:21 -04:00
Kyle Spearrin
7be58fb884 update jslib 2019-04-15 23:04:13 -04:00
Kyle Spearrin
a29e9e11f7 focus length input on change 2019-04-15 22:37:29 -04:00
Kyle Spearrin
18c89e4fa5 premises 2019-04-04 00:45:53 -04:00
Kyle Spearrin
84dd370cfb add A11yTitleDirective 2019-04-02 09:48:49 -04:00
Kyle Spearrin
b45c79d65b send modal state messages 2019-04-02 09:29:20 -04:00
Kyle Spearrin
52a5086f7e dont use flex for password positioning 2019-04-01 13:56:34 -04:00
Kyle Spearrin
3980dc7e84 update bootstrap 2019-03-29 00:20:49 -04:00
Kyle Spearrin
ffd0608dda npm audit fix 2019-03-29 00:12:07 -04:00
Kyle Spearrin
322bc90920 drag n drop cleanup 2019-03-28 11:59:53 -04:00
Kovah
9685f2c2b3 Drag n drop sorting for custom fields (#370)
* Implement custom field ordering with new handle placement

* Update reference for jslib
2019-03-28 11:39:49 -04:00
Kyle Spearrin
342871a216 update jslib 2019-03-28 11:37:33 -04:00
Kyle Spearrin
1cd1ab07a2 New Crowdin translations (#369)
* New translations messages.json (Catalan)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Danish)

* New translations messages.json (Dutch)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Estonian)

* New translations messages.json (French)

* New translations messages.json (German)

* New translations messages.json (Italian)

* New translations messages.json (Portuguese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Spanish)

* New translations messages.json (Ukrainian)
2019-03-25 17:40:31 -04:00
Kyle Spearrin
137be678c0 update jslib 2019-03-25 09:16:55 -04:00
Kyle Spearrin
bcf0aaab17 update jslib 2019-03-23 12:32:14 -04:00
Kyle Spearrin
9c331e1777 New Crowdin translations (#368)
* New translations messages.json (Afrikaans)

* New translations messages.json (Italian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Hungarian)

* New translations messages.json (Catalan)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Ukrainian)
2019-03-21 23:12:25 -04:00
Kyle Spearrin
789516e573 changeBillingPlanUpgrade 2019-03-21 22:59:11 -04:00
Kyle Spearrin
02f964c7d9 New Crowdin translations (#367)
* New translations messages.json (Afrikaans)

* New translations messages.json (Italian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Hungarian)

* New translations messages.json (Catalan)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Ukrainian)
2019-03-21 22:36:29 -04:00
Kyle Spearrin
ea4d1de772 org plan upgrade 2019-03-21 21:38:56 -04:00
Kyle Spearrin
0f3d71a504 shared org plans component 2019-03-21 13:11:40 -04:00
Kyle Spearrin
5dc00a8bc6 update jslib 2019-03-21 10:08:29 -04:00
Kyle Spearrin
5690e3fe9e close buttons on cards 2019-03-20 10:16:01 -04:00
Kyle Spearrin
f6fcb280fc sub out change plan component 2019-03-20 10:11:51 -04:00
Kyle Spearrin
65a20815bf download license component 2019-03-20 09:56:50 -04:00
Kyle Spearrin
9a55202a9f PUSH_DOCKER checks 2019-03-19 22:17:03 -04:00
Kyle Spearrin
06ec65fb10 update jslib 2019-03-19 15:54:13 -04:00
Kyle Spearrin
371ecd9d3a page at 200 2019-03-19 14:55:19 -04:00
Kyle Spearrin
ff3fce821c bump version 2019-03-19 12:53:59 -04:00
Kyle Spearrin
cc706a48da paging ciphers for better performance 2019-03-19 12:44:22 -04:00
Kyle Spearrin
e4093209cc update jslib 2019-03-18 15:02:41 -04:00
Kyle Spearrin
1f7e5632ac ignore cli from jslib 2019-03-16 08:38:38 -04:00
Kyle Spearrin
bda9e7b2b2 bump version 2019-03-16 00:46:32 -04:00
Kyle Spearrin
5427ddb8d6 fix confirmModalRef 2019-03-15 21:04:57 -04:00
Kyle Spearrin
b34d40252f New Crowdin translations (#364)
* New translations messages.json (Catalan)

* New translations messages.json (French)

* New translations messages.json (Spanish)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Italian)

* New translations messages.json (German)

* New translations messages.json (Finnish)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Ukrainian)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Slovak)

* New translations messages.json (Slovak)

* New translations messages.json (Slovak)
2019-03-13 14:52:36 -04:00
Kyle Spearrin
f73d74dd73 move to ps appveyor 2019-03-13 10:38:49 -04:00
Kyle Spearrin
eb48b8e65f back to cmd 2019-03-12 16:10:08 -04:00
Kyle Spearrin
ce0fe368ab set git pathing 2019-03-12 16:02:39 -04:00
Kyle Spearrin
34ef71707a move to ps commands 2019-03-12 15:37:32 -04:00
Kyle Spearrin
ffeb9dbaa5 update jslib 2019-03-12 10:45:47 -04:00
Kyle Spearrin
62a1d09f48 New Crowdin translations (#362)
* New translations messages.json (Catalan)

* New translations messages.json (Japanese)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Italian)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Ukrainian)
2019-03-09 09:20:07 -05:00
Kyle Spearrin
60039de67d only log into docker when password available 2019-03-08 16:38:21 -05:00
Kyle Spearrin
526df6e41a remove double build 2019-03-08 15:05:23 -05:00
Kyle Spearrin
cf8b451e35 APPVEYOR_RE_BUILD is True 2019-03-08 14:48:37 -05:00
Kyle Spearrin
059260d318 ci builds 2019-03-08 14:44:02 -05:00
Kyle Spearrin
45134f903d update jslib 2019-03-07 23:55:13 -05:00
Kyle Spearrin
fefe4edda1 collection externalId 2019-03-07 15:18:05 -05:00
Kyle Spearrin
aabb1bc264 get/rotate org api key 2019-03-07 11:18:45 -05:00
Kyle Spearrin
02ba2d3b60 update jslib 2019-03-07 10:03:09 -05:00
Kyle Spearrin
925c5aa389 update jslib 2019-03-06 21:37:50 -05:00
Kyle Spearrin
2b6ce14a32 update jslib 2019-03-05 17:25:01 -05:00
Kyle Spearrin
ed45e524b9 New Crowdin translations (#360)
* New translations messages.json (Estonian)

* New translations messages.json (Russian)
2019-03-04 20:16:49 -05:00
Kyle Spearrin
e645204e37 New Crowdin translations (#359)
* New translations messages.json (Czech)

* New translations messages.json (Estonian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Turkish)
2019-03-02 15:47:19 -05:00
Kyle Spearrin
ff1429c6b3 update jslib 2019-03-02 13:58:26 -05:00
Kyle Spearrin
abe17a02c4 update jslib 2019-02-27 14:39:55 -05:00
Kyle Spearrin
7bde73102b readFromClipboard implemented in web 2019-02-26 22:42:30 -05:00
Kyle Spearrin
3f27093f82 update jslib 2019-02-25 16:36:00 -05:00
Kyle Spearrin
37ed53cb3c show icon for wiretransfers 2019-02-25 09:22:25 -05:00
Kyle Spearrin
4b20d3ef0a New Crowdin translations (#357)
* New translations messages.json (Catalan)

* New translations messages.json (Italian)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Korean)

* New translations messages.json (German)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Ukrainian)
2019-02-25 09:14:24 -05:00
Kyle Spearrin
12492b5749 add image_url to paypal checkout 2019-02-24 22:12:20 -05:00
Kyle Spearrin
af2b422730 handle credit types 2019-02-23 20:34:21 -05:00
Kyle Spearrin
0c63f65aa7 refundNoun 2019-02-22 23:12:12 -05:00
Kyle Spearrin
4b2d1e6745 update jslib 2019-02-22 21:15:32 -05:00
Kyle Spearrin
25e6a03435 New Crowdin translations (#356)
* New translations messages.json (Catalan)

* New translations messages.json (Japanese)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Italian)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Ukrainian)
2019-02-22 15:50:18 -05:00
Kyle Spearrin
d681f91de9 update jslib 2019-02-22 15:07:55 -05:00
Kyle Spearrin
12e2bcbbd9 go back to previous url after lock 2019-02-22 13:17:10 -05:00
Kyle Spearrin
ec3e438c99 show bitcoin icon on transaction listing 2019-02-22 12:47:04 -05:00
Kyle Spearrin
2089237d23 add credit via bitpay 2019-02-21 22:48:59 -05:00
Kyle Spearrin
7bcd0ac3e5 account_credit:1 2019-02-21 21:48:02 -05:00
Kyle Spearrin
8e9ab12219 billing imrovements 2019-02-21 18:03:39 -05:00
Kyle Spearrin
33b539858f format html files 2019-02-21 16:50:37 -05:00
Kyle Spearrin
cdfd828a8b dont send token when null 2019-02-21 00:03:40 -05:00
Kyle Spearrin
22727b5abe support credit on get token method 2019-02-20 20:39:40 -05:00
Kyle Spearrin
041cf1268d credit fixes 2019-02-20 20:37:27 -05:00
Kyle Spearrin
fb3afbdc76 credit payment method 2019-02-20 20:16:06 -05:00
Kyle Spearrin
1f6632146b add credit via paypal 2019-02-20 17:33:05 -05:00
Kyle Spearrin
944187f276 ie11 fix 2019-02-19 22:00:55 -05:00
Kyle Spearrin
81eb2189ca New Crowdin translations (#354)
* New translations messages.json (Catalan)

* New translations messages.json (Czech)

* New translations messages.json (Dutch)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Finnish)

* New translations messages.json (French)

* New translations messages.json (German)

* New translations messages.json (Italian)

* New translations messages.json (Japanese)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Portuguese)

* New translations messages.json (Russian)

* New translations messages.json (Spanish)
2019-02-19 21:40:59 -05:00
Kyle Spearrin
4fc90984d8 pass payment method type 2019-02-19 17:06:01 -05:00
Kyle Spearrin
0b1abc9ab0 more style fixes 2019-02-19 00:23:15 -05:00
Kyle Spearrin
212d81b93c New Crowdin translations (#353)
* New translations messages.json (Catalan)

* New translations messages.json (Japanese)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Italian)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Ukrainian)
2019-02-19 00:03:44 -05:00
Kyle Spearrin
238ac22b85 styling 2019-02-18 23:53:36 -05:00
Kyle Spearrin
773f0be84a move to stripe elements 2019-02-18 23:40:04 -05:00
Kyle Spearrin
e45c988637 account credit/balance 2019-02-18 17:34:57 -05:00
Kyle Spearrin
8305b49046 dont show billing page on self host 2019-02-18 16:10:32 -05:00
Kyle Spearrin
92b2601ba2 split billing and subscription management up 2019-02-18 15:28:23 -05:00
Kyle Spearrin
af8ab752ad update jslib 2019-02-17 21:16:59 -05:00
Kyle Spearrin
e45105ccb3 Merge branch 'master' of github.com:bitwarden/web 2019-02-16 16:04:39 -05:00
Kyle Spearrin
9114b68659 dont show add/remove seats when sub canceled 2019-02-16 16:04:35 -05:00
Kyle Spearrin
cd2e091580 New Crowdin translations (#349)
* New translations messages.json (Catalan)

* New translations messages.json (Japanese)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Italian)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Ukrainian)

* New translations messages.json (Czech)

* New translations messages.json (Danish)

* New translations messages.json (French)

* New translations messages.json (Portuguese)

* New translations messages.json (Russian)
2019-02-14 22:54:13 -05:00
Kyle Spearrin
38d8f83587 update python-gnomekeyring link 2019-02-14 09:07:48 -05:00
Kyle Spearrin
5f3b6501d7 update jslib 2019-02-13 22:09:06 -05:00
Kyle Spearrin
f35efbdd5b fix deps 2019-02-13 21:58:16 -05:00
Kyle Spearrin
961954364a move to lock service is locked 2019-02-13 21:55:11 -05:00
Kyle Spearrin
259725882a remembear csv importer 2019-02-13 15:32:41 -05:00
Kyle Spearrin
fb2288c4bc show loading on braintree 2019-02-09 21:54:09 -05:00
Kyle Spearrin
0220f4519d billing page invoices and transactions 2019-02-09 00:19:54 -05:00
Kyle Spearrin
3432243acb update jslib 2019-02-02 22:33:47 -05:00
ShirokaiLon
27a32463d9 Add trackBy option (#342) 2019-02-02 22:31:33 -05:00
Kyle Spearrin
b47f7e8cf1 enable paypal for orgs. and paypal method changes 2019-01-31 12:11:23 -05:00
Kyle Spearrin
459bc69032 fix year in frontend footer 2019-01-29 12:52:11 -05:00
Kyle Spearrin
378b4bb8c1 update jslib 2019-01-28 11:10:55 -05:00
Kyle Spearrin
6a5712070f added kaspersky 2019-01-28 09:21:00 -05:00
Kyle Spearrin
48e125881b update jslib 2019-01-26 21:31:41 -05:00
Kyle Spearrin
e6cec93f2c postinstall task for fixing sweetalert typings 2019-01-25 15:05:22 -05:00
Kyle Spearrin
b5726393f3 update to angular 7 2019-01-25 14:05:09 -05:00
Kyle Spearrin
82010e4fa3 update jslib 2019-01-24 12:05:16 -05:00
Kyle Spearrin
eb99fe58dd refresh token and UI when license updated 2019-01-24 08:54:33 -05:00
Kyle Spearrin
a18e7ab2da flex copy on web generator 2019-01-23 17:05:36 -05:00
Kyle Spearrin
e1f78f519c flex copy directive 2019-01-23 16:27:34 -05:00
Kyle Spearrin
50a57727fe update jslib 2019-01-20 23:03:17 -05:00
Kyle Spearrin
4bbb7f82b4 update jslib 2019-01-18 23:42:19 -05:00
Kyle Spearrin
1da4cf8907 New Crowdin translations (#335)
* New translations messages.json (Catalan)

* New translations messages.json (Slovak)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Polish)

* New translations messages.json (Italian)

* New translations messages.json (German)

* New translations messages.json (Estonian)

* New translations messages.json (Croatian)
2019-01-18 16:09:04 -05:00
Kyle Spearrin
978a58391b add ca language 2019-01-18 15:59:04 -05:00
Kyle Spearrin
b2be44e372 use some 2019-01-17 10:47:03 -05:00
Kyle Spearrin
650fc6aa27 null checks on query param sub 2019-01-16 23:30:32 -05:00
Kyle Spearrin
47bda7d789 card exp month and year empty string defaults 2019-01-16 23:26:39 -05:00
Kyle Spearrin
64f41f004d en-GB locale 2019-01-15 20:49:15 -05:00
Kyle Spearrin
68f69074cb New Crowdin translations (#330)
* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Italian)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Hungarian)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Ukrainian)
2019-01-15 20:11:55 -05:00
Kyle Spearrin
4d3fb52956 Revert "New Crowdin translations (#323)"
This reverts commit 1f39761f8c.
2019-01-15 20:09:21 -05:00
Kyle Spearrin
18a23d6844 Revert "New Crowdin translations (#327)"
This reverts commit bdf653bc70.
2019-01-15 20:09:11 -05:00
Kyle Spearrin
bdf653bc70 New Crowdin translations (#327)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Spanish)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Italian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2019-01-15 19:07:18 -05:00
Kyle Spearrin
0aaa351797 en-GB support 2019-01-15 17:53:49 -05:00
Kyle Spearrin
1f39761f8c New Crowdin translations (#323)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Japanese)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Korean)

* New translations messages.json (Italian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (English, United Kingdom)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Croatian)

* New translations messages.json (Ukrainian)

* New translations messages.json (Portuguese)
2019-01-15 17:34:41 -05:00
Kyle Spearrin
c7914fa8e4 bump version 2019-01-15 11:35:59 -05:00
Kyle Spearrin
a48cc2a7f3 always allow chrome to use u2f 2019-01-10 11:23:16 -05:00
Kyle Spearrin
3942409c9a lock screen improvements 2019-01-08 00:32:35 -05:00
Kyle Spearrin
6b0719db45 allow launching URLs without protocol than end with tld 2019-01-07 10:33:27 -05:00
Kyle Spearrin
9728116836 pass messagingService dependency 2019-01-03 10:24:29 -05:00
Kyle Spearrin
6cffabe259 f secure importer 2019-01-03 09:58:48 -05:00
Kyle Spearrin
28b20cc8ba update jslib 2019-01-03 00:18:42 -05:00
Kyle Spearrin
62b012941e update jslib 2019-01-01 23:17:12 -05:00
Kyle Spearrin
1b94ac383c New Crowdin translations (#316)
* New translations messages.json (Czech)

* New translations messages.json (German)

* New translations messages.json (Korean)

* New translations messages.json (Polish)
2018-12-31 12:57:33 -05:00
Kyle Spearrin
9a96ef2623 avast csv option 2018-12-31 12:42:27 -05:00
Kyle Spearrin
6480750757 New Crowdin translations (#315)
* New translations messages.json (Bulgarian)

* New translations messages.json (Danish)

* New translations messages.json (Dutch)

* New translations messages.json (Estonian)

* New translations messages.json (French)

* New translations messages.json (Italian)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Portuguese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Slovak)

* New translations messages.json (Spanish)

* New translations messages.json (Swedish)

* New translations messages.json (Ukrainian)
2018-12-28 10:13:16 -05:00
Kyle Spearrin
df313560c2 added new languages 2018-12-28 10:06:38 -05:00
Kyle Spearrin
be0e832589 New Crowdin translations (#314)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-12-27 09:21:37 -05:00
Kyle Spearrin
9f87f551fd bump version 2018-12-27 09:15:36 -05:00
Kyle Spearrin
5804c57236 unsubscribe from queryparams observable 2018-12-20 10:06:40 -05:00
Kyle Spearrin
7efd81191a show indicator if two-step login is enabled 2018-12-19 11:30:02 -05:00
Kyle Spearrin
84bea20891 duo_web_sdk 2018-12-18 17:19:55 -05:00
Kyle Spearrin
c2b9b6e162 update jslib 2018-12-18 17:00:16 -05:00
Kyle Spearrin
3720b9481f install and use duo_web_sdk w/ npm 2018-12-18 17:00:03 -05:00
Kyle Spearrin
b565d40ec7 New Crowdin translations (#310)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-12-17 23:20:39 -05:00
Kyle Spearrin
0e1f2e721f bitwarden json importer 2018-12-17 13:21:16 -05:00
Kyle Spearrin
951a22b90e make file format select list first 2018-12-17 11:07:44 -05:00
Kyle Spearrin
1dd88a690b support for json exports 2018-12-17 10:54:18 -05:00
Kyle Spearrin
55ba78c66a bump version 2018-12-15 21:56:41 -05:00
Kyle Spearrin
b0364041e2 should be useTotp 2018-12-15 21:54:32 -05:00
Kyle Spearrin
6b9c90f99b update jslib 2018-12-14 17:20:31 -05:00
Kyle Spearrin
4050bc1da8 accessReports typo 2018-12-14 14:50:15 -05:00
Kyle Spearrin
4bb9051136 show reports with upgrade message 2018-12-14 14:48:12 -05:00
Kyle Spearrin
ceca4fbe53 add more org reports 2018-12-14 14:42:04 -05:00
Kyle Spearrin
9b7c0288d4 inactive 2fa report for orgs 2018-12-14 14:22:30 -05:00
Kyle Spearrin
392a90c02c exposed passwords report for orgs 2018-12-14 13:56:01 -05:00
Kyle Spearrin
7a58f6d967 make sure routerService is newed 2018-12-14 11:15:50 -05:00
Kyle Spearrin
35d1e51f9b update jslib 2018-12-13 14:38:03 -05:00
Kyle Spearrin
9729a4c724 enpass json importer 2018-12-13 14:34:43 -05:00
Kyle Spearrin
f13713a055 update jslib 2018-12-13 10:59:05 -05:00
Kyle Spearrin
31655f7832 userInputs for strength check based on username 2018-12-12 19:37:27 -05:00
Kyle Spearrin
fb4bb81595 dashlane json importer 2018-12-12 17:06:22 -05:00
Kyle Spearrin
31cb6916c6 null check 2018-12-12 15:01:23 -05:00
Kyle Spearrin
61d37615af New translations messages.json (Portuguese) (#308) 2018-12-12 12:57:01 -05:00
Kyle Spearrin
eaa7701696 New translations messages.json (Portuguese) (#307) 2018-12-12 12:49:10 -05:00
Kyle Spearrin
d6cff8e0b0 Merge branch 'master' of github.com:bitwarden/web 2018-12-12 12:46:20 -05:00
Kyle Spearrin
8ba761b33c add missing "that" 2018-12-12 12:46:17 -05:00
Kyle Spearrin
05e7e452df New Crowdin translations (#306)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-12-12 12:03:03 -05:00
Kyle Spearrin
3f0fd4f771 use cache instead of async 2018-12-12 11:22:11 -05:00
Kyle Spearrin
a587c1d1da async the weak password checks 2018-12-12 10:34:05 -05:00
Kyle Spearrin
c3355f7fe4 premium reports feature 2018-12-12 10:05:54 -05:00
Kyle Spearrin
c182d874af premium labels for reports section 2018-12-12 09:45:50 -05:00
Kyle Spearrin
ab9ebfb667 fix i18n 2018-12-12 09:30:57 -05:00
Kyle Spearrin
cb953eda61 premium checks on reports 2018-12-12 09:29:51 -05:00
Kyle Spearrin
93c291dba1 base cipher report component class 2018-12-12 09:11:10 -05:00
Kyle Spearrin
603a1ef046 format numbers 2018-12-12 08:54:52 -05:00
Kyle Spearrin
5a504b00fb update report language 2018-12-12 08:53:44 -05:00
Kyle Spearrin
dfa59dc93d instructions language update 2018-12-12 00:02:57 -05:00
Kyle Spearrin
534bcdd52c rearrange reports 2018-12-11 23:29:36 -05:00
Kyle Spearrin
ea032bf551 inactive 2fa report 2018-12-11 23:25:05 -05:00
Kyle Spearrin
b44eee8d81 hasLoaded moved to load method 2018-12-11 22:10:26 -05:00
Kyle Spearrin
8f57ada128 exposed passwords report 2018-12-11 22:09:16 -05:00
Kyle Spearrin
3963990831 weak passwords report 2018-12-11 17:49:51 -05:00
Kyle Spearrin
dc1ffafdf3 hasLoaded spinners 2018-12-11 15:16:45 -05:00
Kyle Spearrin
4a0b4de322 unsecured websites report 2018-12-11 15:11:16 -05:00
Kyle Spearrin
0ede65e9ca add help link for searching 2018-12-11 14:51:44 -05:00
Kyle Spearrin
0ebf30b8b6 reused passwords report 2018-12-11 14:47:41 -05:00
Kyle Spearrin
4222b192c4 max-height on icon image 2018-12-08 14:36:55 -05:00
Kyle Spearrin
4a301aaec3 bump version 2018-12-08 14:11:57 -05:00
Kyle Spearrin
97a3a97a15 colorized password 2018-12-08 14:11:10 -05:00
Kyle Spearrin
c526d73e23 bump version 2018-12-08 10:48:05 -05:00
Kyle Spearrin
58baf137aa dont apply old pipe search during select all filter 2018-12-08 10:47:22 -05:00
Matej Kramny
066ab1500f enable clear button in search input types (#300) 2018-12-07 20:07:34 -05:00
Andrew Peng
224a468712 Fix typo (#298) 2018-12-03 15:39:33 -05:00
Kyle Spearrin
dd282383d7 use router.navigate rather than location 2018-11-30 10:28:46 -05:00
Kyle Spearrin
9a99a95b15 update jslib 2018-11-28 09:52:49 -05:00
Alexandre Lapeyre
e814494e37 fix logos in breach report page (#296) 2018-11-28 09:51:43 -05:00
Kyle Spearrin
90a0155be1 bump version 2018-11-28 08:55:24 -05:00
Kyle Spearrin
555d40408d normalize email on password change 2018-11-28 08:54:33 -05:00
Kyle Spearrin
0c3fbeb0b7 update gulp to 4.0.0 2018-11-27 12:47:06 -05:00
Kyle Spearrin
2f27decaa1 bump version 2018-11-26 15:36:17 -05:00
Kyle Spearrin
867115659f re-enable key rotation on master password change 2018-11-26 15:36:09 -05:00
Kyle Spearrin
6282ab58db hide key rotation option 2018-11-26 12:59:45 -05:00
Kyle Spearrin
95c25c1bcd fix help articles 2018-11-26 12:25:27 -05:00
Kyle Spearrin
74a62de7d0 New Crowdin translations (#295)
* New translations messages.json (Czech)

* New translations messages.json (Danish)

* New translations messages.json (Dutch)

* New translations messages.json (French)

* New translations messages.json (Italian)

* New translations messages.json (Japanese)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Polish)

* New translations messages.json (Portuguese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Slovak)

* New translations messages.json (Spanish)
2018-11-26 08:41:59 -05:00
Kyle Spearrin
7fc021648d update jslib 2018-11-26 08:31:28 -05:00
Kyle Spearrin
95914ad312 Merge branch 'master' of github.com:bitwarden/web 2018-11-23 08:20:25 -05:00
Kyle Spearrin
5ed00e037a bump version 2018-11-23 08:20:22 -05:00
Kyle Spearrin
6f3074536a New Crowdin translations (#292)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-11-21 09:16:53 -05:00
Kyle Spearrin
21f5cb36bb To ensure the integrity 2018-11-21 09:04:46 -05:00
Kyle Spearrin
7b7592822f New Crowdin translations (#290)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-11-20 22:35:17 -05:00
Kyle Spearrin
9c7b7b0d75 premium access addon for orgs 2018-11-20 16:38:00 -05:00
Kyle Spearrin
d88b23c42d learn more about encryption key changes from help article 2018-11-20 13:05:52 -05:00
Kyle Spearrin
1602c0aca2 link to fingerprint phrase article 2018-11-16 11:20:44 -05:00
Kyle Spearrin
384978a511 fix old attachments article info 2018-11-16 09:17:33 -05:00
Kyle Spearrin
afd7a0494f fix password meter aria-valuenow 2018-11-15 14:46:51 -05:00
Kyle Spearrin
ac1f8a69e1 allow bulk sharing of items with new attachments 2018-11-15 12:56:07 -05:00
Kyle Spearrin
05cfa99ea0 fingerprint phrase confirmation 2018-11-14 23:13:50 -05:00
Kyle Spearrin
9b43ccbbc0 updateKey helper 2018-11-14 16:22:57 -05:00
Kyle Spearrin
6d8b156455 old attachments check when rotating enc key 2018-11-14 15:54:13 -05:00
Kyle Spearrin
1b9943a4c8 allow swal single button 2018-11-14 15:45:03 -05:00
Kyle Spearrin
8232a4c9c8 fix old attachments by reuploading them 2018-11-14 15:20:17 -05:00
Kyle Spearrin
9d4d64c95a update jslib 2018-11-13 20:43:56 -05:00
Kyle Spearrin
2d0acc7663 add enc key rotation option during master password change 2018-11-13 11:06:16 -05:00
Kyle Spearrin
4231ed74ba adjust password strength meter 2018-11-13 09:10:44 -05:00
Kyle Spearrin
912e1cf89f getPasswordStrengthUserInput on password change 2018-11-12 23:26:00 -05:00
Kyle Spearrin
26d4fb8005 fix aslignment with invisible progress bar 2018-11-12 23:06:28 -05:00
Kyle Spearrin
4a6c0b39a8 add typings for zxcvbn 2018-11-12 23:03:20 -05:00
Kyle Spearrin
9d01bba170 weak password checks on master password change 2018-11-12 23:00:58 -05:00
Kyle Spearrin
85c0ddba10 password strength checks during registration 2018-11-12 22:54:40 -05:00
Kyle Spearrin
2664059812 caret spacing 2018-11-09 22:25:07 -05:00
Kyle Spearrin
b7e4d9c806 toggle collapse string update 2018-11-09 17:50:26 -05:00
Kyle Spearrin
95b91f0ce2 added collpase/expand functions to groupings 2018-11-09 17:45:01 -05:00
Kyle Spearrin
f0407e4327 catch any errors when generating fingerprint 2018-11-07 23:19:48 -05:00
Kyle Spearrin
a7555f56e7 print user's fingerprint when confirming 2018-11-07 23:15:50 -05:00
Kyle Spearrin
b093ed33b2 update jslib 2018-11-06 15:53:51 -05:00
Kyle Spearrin
ec1a45ba18 update jslib 2018-11-06 15:51:52 -05:00
Kyle Spearrin
def5dc3b0f New Crowdin translations (#286)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Danish)

* New translations messages.json (Dutch)

* New translations messages.json (Estonian)

* New translations messages.json (Finnish)

* New translations messages.json (French)

* New translations messages.json (Japanese)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Polish)

* New translations messages.json (Portuguese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Spanish)
2018-11-06 15:51:05 -05:00
Kyle Spearrin
24ec89c220 open PDF in new window using built-in browser viewer 2018-11-06 09:46:17 -05:00
Kyle Spearrin
303e70bb58 update jslib 2018-11-06 09:05:46 -05:00
Kyle Spearrin
ec3e92fc19 set blob type 2018-10-30 09:54:14 -04:00
Kyle Spearrin
5ae776309d New Crowdin translations (#284)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-10-29 10:26:38 -04:00
Kyle Spearrin
76dd606a48 additionalStorageIntervalDesc 2018-10-29 10:07:03 -04:00
Kyle Spearrin
8998798fa4 always load nested collections 2018-10-29 10:06:42 -04:00
Kyle Spearrin
60ee82ca47 always loading nested now 2018-10-26 10:49:14 -04:00
Kyle Spearrin
e1284002a9 cleanup imports 2018-10-26 08:29:33 -04:00
Kyle Spearrin
8252512784 nested collections 2018-10-25 12:19:35 -04:00
Kyle Spearrin
1390d7eb1d display nested folders 2018-10-25 09:38:52 -04:00
Kyle Spearrin
8da1bb13ff dont stop prob on label simple label click for cb list 2018-10-24 22:15:09 -04:00
Kyle Spearrin
340e377b37 filter collections for current org 2018-10-24 22:09:36 -04:00
Kyle Spearrin
171589fb3d missing searchText property 2018-10-24 22:01:38 -04:00
Kyle Spearrin
bcd07cce0d New Crowdin translations (#281)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Turkish)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-10-24 13:03:03 -04:00
Kyle Spearrin
68880114b4 bump version 2018-10-23 22:57:36 -04:00
Kyle Spearrin
eb2360ae24 update jslib 2018-10-23 16:18:01 -04:00
Kyle Spearrin
62712a352b update jslib 2018-10-23 12:04:28 -04:00
Kyle Spearrin
745e6c1715 use base collections component from jslib 2018-10-23 12:04:05 -04:00
Kyle Spearrin
e20a75eb0c use share component from jslib 2018-10-23 10:33:40 -04:00
Kyle Spearrin
a24c41ff25 set org id and collections if filtered 2018-10-22 16:46:48 -04:00
Kyle Spearrin
69f0339bd5 set collections for org admin 2018-10-22 14:48:17 -04:00
Kyle Spearrin
5e7c9a7278 add ownership and collection assignment from add/edit 2018-10-19 12:44:52 -04:00
Kyle Spearrin
726c323fe1 accessAll is only for collection assignments 2018-10-18 12:25:25 -04:00
SoulSeekkor
e96cbe2710 Added .gitattributes file to files requiring LF endings are properly checked out on Windows. (#279) 2018-10-18 12:15:54 -04:00
Kyle Spearrin
323e54b4bd filtering 2018-10-18 12:15:13 -04:00
Kyle Spearrin
7ab132bbf6 add thead for entity users 2018-10-17 23:04:39 -04:00
Kyle Spearrin
6b09210a80 manage group users 2018-10-17 22:56:49 -04:00
Kyle Spearrin
be80d62c01 manage collection users for entity-users 2018-10-17 22:20:42 -04:00
Kyle Spearrin
30587d625a fixes to showAdd and filtering on load for non-admins 2018-10-17 16:09:09 -04:00
Kyle Spearrin
af43cd407e undo manage rules for org groupings listing 2018-10-17 15:57:39 -04:00
Kyle Spearrin
647388e475 showAddNew only if admin 2018-10-17 15:51:31 -04:00
Kyle Spearrin
329e06ac30 null check in view 2018-10-17 15:46:13 -04:00
Kyle Spearrin
5d96138720 lint fix 2018-10-17 11:23:01 -04:00
Kyle Spearrin
66b275605c load manage collections a manager has access to 2018-10-17 11:20:27 -04:00
Kyle Spearrin
9b7478c0c7 manager sees their assigned collections from org vault view 2018-10-17 11:19:10 -04:00
Kyle Spearrin
668271bb31 add basic org manager access and UI elements 2018-10-17 10:53:04 -04:00
Kyle Spearrin
1aa93e7737 New Crowdin translations (#277)
* New translations messages.json (Danish)

* New translations messages.json (Estonian)

* New translations messages.json (Finnish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Russian)

* New translations messages.json (Slovak)

* New translations messages.json (Turkish)
2018-10-16 08:58:37 -04:00
Kyle Spearrin
a0864f5f67 update jslib 2018-10-16 08:57:19 -04:00
Kyle Spearrin
6e9f71f942 move getDomain to jslib 2018-10-13 23:26:38 -04:00
Kyle Spearrin
65211372df New Crowdin translations (#275)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Spanish)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (French)

* New translations messages.json (Estonian)

* New translations messages.json (Danish)

* New translations messages.json (Ukrainian)
2018-10-11 21:35:24 -04:00
Kyle Spearrin
2ca8d8817a update jslib 2018-10-11 20:59:55 -04:00
Kyle Spearrin
ec266ea657 update jslib 2018-10-10 17:52:29 -04:00
Kyle Spearrin
d117aa5139 update yubiKeyDesc for 5 series 2018-10-10 12:30:03 -04:00
Kyle Spearrin
4534b7d4dc Merge branch 'master' of github.com:bitwarden/web 2018-10-09 18:03:25 -04:00
Kyle Spearrin
707fe01d77 update signalr 2018-10-09 18:03:23 -04:00
Kyle Spearrin
0e09ba0dd5 New Crowdin translations (#273)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-10-09 16:07:41 -04:00
Kyle Spearrin
989560f23c renamed event to updated2fa 2018-10-09 16:01:00 -04:00
Kyle Spearrin
844a9f934f New Crowdin translations (#272)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-10-09 09:21:52 -04:00
Kyle Spearrin
b5348c593a bump version 2018-10-08 23:11:38 -04:00
Kyle Spearrin
7f809ba541 inline redios 2018-10-08 22:42:32 -04:00
Kyle Spearrin
f9058fcddc pass gen fixes. word sep option 2018-10-08 22:06:15 -04:00
Kyle Spearrin
05c9957fd2 passphrase cleanup 2018-10-08 17:55:07 -04:00
Martin Trigaux
675739d24f Adapt the interface to generate passphrase too (#267) 2018-10-08 17:27:25 -04:00
Kyle Spearrin
10be0867ad New Crowdin translations (#270)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Finnish)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-10-08 16:05:16 -04:00
Kyle Spearrin
d2a4b85bdd update passman instructions 2018-10-08 15:54:58 -04:00
ServiusHack
782061ac5e Add instructions for passman (#269) 2018-10-08 15:51:59 -04:00
Kyle Spearrin
8d98e9e6f9 add back proper isDev check 2018-10-08 14:26:10 -04:00
Kyle Spearrin
4aa75e9376 support for setup of multiple u2f keys 2018-10-08 14:23:30 -04:00
Kyle Spearrin
c6d6eecb43 update jslib 2018-10-05 13:57:41 -04:00
Kyle Spearrin
1d6d7b8aa8 dont await void methods 2018-10-04 11:58:19 -04:00
Kyle Spearrin
68ed8e51bd convert analytics and toaster to platform utils 2018-10-03 10:33:04 -04:00
Kyle Spearrin
d4dd962193 update jslib 2018-10-02 09:22:49 -04:00
Kyle Spearrin
7dfb70eb8e purge org vault 2018-09-25 09:12:24 -04:00
Kyle Spearrin
53675eeba7 stop prop on checkbox clicks 2018-09-24 17:45:35 -04:00
Kyle Spearrin
6399973bfa nojekyll 2018-09-22 16:04:09 -04:00
Kyle Spearrin
f1384f5dc1 passpack importer 2018-09-21 13:54:17 -04:00
Kyle Spearrin
027cad9e52 switch to webpack-dev-server 2018-09-18 11:59:03 -04:00
Kyle Spearrin
dffcff48a0 New Crowdin translations (#263)
* New translations messages.json (Czech)

* New translations messages.json (Finnish)

* New translations messages.json (Slovak)
2018-09-17 15:33:14 -04:00
Kyle Spearrin
0391f31b3a update jslib 2018-09-17 14:38:27 -04:00
Kyle Spearrin
eb7b0ba92f update jslib 2018-09-14 09:41:37 -04:00
Kyle Spearrin
3a136e1464 remove tax information 2018-09-13 16:24:02 -04:00
Kyle Spearrin
8792bcabcb preserveWhitespaces 2018-09-13 11:57:28 -04:00
Kyle Spearrin
c362fc4677 Revert "remove swal hack"
This reverts commit 2d6b4f1216.
2018-09-13 11:28:52 -04:00
Kyle Spearrin
f471fe62ea Revert "remove swal hack again"
This reverts commit f19aa96f3e.
2018-09-13 11:28:31 -04:00
Kyle Spearrin
f19aa96f3e remove swal hack again 2018-09-12 15:18:37 -04:00
Kyle Spearrin
2d6b4f1216 remove swal hack 2018-09-12 15:16:02 -04:00
Kyle Spearrin
22a8f766c7 fix adjust seat pricing 2018-09-12 12:26:07 -04:00
Kyle Spearrin
86bc6fa807 remove trailing comma 2018-09-12 00:33:18 -04:00
Kyle Spearrin
14b094cfe0 update jslib 2018-09-11 22:48:51 -04:00
Kyle Spearrin
d90b36bd33 update package lock file 2018-09-11 22:48:30 -04:00
Kyle Spearrin
18b800ff7a fix node refs in tsconfig 2018-09-11 22:41:43 -04:00
Kyle Spearrin
7ab56a9616 prebuild:prod task 2018-09-11 17:49:43 -04:00
Kyle Spearrin
6f8352033b package lock updates 2018-09-11 17:41:56 -04:00
Daniel
188ac5051a Removed requirement to load JavaScript from js.braintreegateway.com (#259)
* Removed requirement to load JavaScript from js.braintreegateway.com

* Moved braintree-web-drop-in from a devDependencies to dependencies per code review.
2018-09-11 17:40:56 -04:00
Kyle Spearrin
335e0dd575 update angular and libs 2018-09-11 17:30:44 -04:00
Kyle Spearrin
67b187f884 bump version is lock file 2018-09-11 09:36:31 -04:00
Kyle Spearrin
c2d262ea1d New Crowdin translations (#258)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Danish)

* New translations messages.json (Dutch)

* New translations messages.json (Estonian)

* New translations messages.json (French)

* New translations messages.json (German)

* New translations messages.json (Hungarian)

* New translations messages.json (Korean)

* New translations messages.json (Polish)

* New translations messages.json (Portuguese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Spanish)

* New translations messages.json (Ukrainian)
2018-09-11 09:26:00 -04:00
Kyle Spearrin
8683465d70 bump version 2018-09-11 09:01:03 -04:00
Kyle Spearrin
8c9705eec0 null check collection ids filter 2018-09-11 08:46:04 -04:00
Kyle Spearrin
d14a8bc301 update jslib 2018-09-10 10:38:32 -04:00
Kyle Spearrin
72aceedab4 update jslib 2018-09-10 10:04:56 -04:00
Kyle Spearrin
7c5ee1bd00 make sure org key exists for collection add/edit 2018-09-10 08:25:52 -04:00
Kyle Spearrin
26aa79db1a trim email also 2018-09-08 08:13:47 -04:00
Kyle Spearrin
2629aaf368 Merge branch 'master' of github.com:bitwarden/web 2018-09-03 21:51:44 -04:00
Kyle Spearrin
3973ebc00f update lunr 2018-09-03 21:51:40 -04:00
Kyle Spearrin
6cddb5f3ba New Crowdin translations (#255)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-09-01 08:24:36 -04:00
Kyle Spearrin
7c55da8cc6 users get premium on enterprise 2018-09-01 08:22:36 -04:00
Kyle Spearrin
0c9f122719 premium access already notice 2018-08-31 17:42:19 -04:00
Kyle Spearrin
1d941baff1 canAccessPremium check on enabled check 2018-08-31 17:28:36 -04:00
Kyle Spearrin
e5226d7ffc check key and premium after sync 2018-08-31 17:23:36 -04:00
Kyle Spearrin
aa3d69cb94 update jslib 2018-08-30 21:48:24 -04:00
Kyle Spearrin
e68d386d3d save length options on input blur 2018-08-30 08:06:40 -04:00
Kyle Spearrin
b322f20c81 fix attachments deps 2018-08-29 09:31:20 -04:00
Kyle Spearrin
7d7a9f3dc6 attachments accessible if can access premium 2018-08-29 09:22:28 -04:00
Kyle Spearrin
977a5e868f Merge branch 'master' of github.com:bitwarden/web 2018-08-28 23:18:02 -04:00
Kyle Spearrin
41ff511165 user canAccessPremium checks 2018-08-28 23:17:58 -04:00
Kyle Spearrin
aadbb970b6 New Crowdin translations (#253)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Korean)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Japanese)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Italian)

* New translations messages.json (Hungarian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Estonian)

* New translations messages.json (Dutch)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-08-28 12:53:14 -04:00
Kyle Spearrin
1873ce41b6 support for logout notification 2018-08-28 08:38:25 -04:00
Kyle Spearrin
ff51e4cc36 update jslib 2018-08-28 00:27:30 -04:00
Kyle Spearrin
73b87f2e97 update dropin to 1.12.0 2018-08-28 00:27:24 -04:00
Kyle Spearrin
1444c99458 change KDF 2018-08-27 22:40:03 -04:00
Kyle Spearrin
85c3056223 remakeEncKey when changing password/email 2018-08-27 19:09:26 -04:00
Kyle Spearrin
4a815b0bdf duplicate node_env check 2018-08-25 08:48:07 -04:00
Kyle Spearrin
b7525e1e7e messagepack protocolf or signalr 2018-08-23 21:45:06 -04:00
Kyle Spearrin
c3f64fe9c4 update jslib 2018-08-23 08:56:45 -04:00
Kyle Spearrin
34f6bc2403 10 minute idle timeout 2018-08-22 22:56:00 -04:00
Kyle Spearrin
9ecec972ca local notifications URL 2018-08-22 22:43:40 -04:00
Kyle Spearrin
80febf97d3 idle reconnects for notifications 2018-08-22 22:37:55 -04:00
Kyle Spearrin
71073874eb update jslib 2018-08-22 16:02:45 -04:00
Kyle Spearrin
f3dfeac125 update jslib 2018-08-22 08:54:22 -04:00
Kyle Spearrin
f12e73519e New Crowdin translations (#249)
* New translations messages.json (Danish)

* New translations messages.json (Dutch)

* New translations messages.json (Estonian)

* New translations messages.json (French)

* New translations messages.json (Italian)

* New translations messages.json (Spanish)
2018-08-21 23:27:57 -04:00
Kyle Spearrin
19f7dda4cc add nl language 2018-08-21 23:23:30 -04:00
Kyle Spearrin
221397b159 add et language 2018-08-21 16:01:47 -04:00
Kyle Spearrin
91766ecea3 word break-all on card lists 2018-08-21 15:48:37 -04:00
Kyle Spearrin
191be134f9 update some packages 2018-08-21 15:31:29 -04:00
Kyle Spearrin
56d279ae1e npm audit fix 2018-08-21 15:19:50 -04:00
Kyle Spearrin
3e61464dac explicitly use https://notifications.bitwarden.com 2018-08-21 13:58:45 -04:00
Kyle Spearrin
85ca10dbb3 notification service implementation 2018-08-20 22:21:13 -04:00
Kyle Spearrin
eaf08c45d9 dont use clipboard writeText api 2018-08-20 09:20:24 -04:00
Kyle Spearrin
bcb44e8cf7 fix copying 2018-08-17 12:25:21 -04:00
Kyle Spearrin
d215e0716e update jslib 2018-08-17 11:09:11 -04:00
Kyle Spearrin
f635162832 New Crowdin translations (#247)
* New translations messages.json (Dutch)

* New translations messages.json (Estonian)
2018-08-16 15:17:55 -04:00
Kyle Spearrin
c892480086 wrap cipher list details for long names 2018-08-16 08:46:49 -04:00
Kyle Spearrin
ea49d17c47 set search text before load 2018-08-15 22:26:39 -04:00
Kyle Spearrin
39c32b0e62 pass original cipher if admin. resolves #245 2018-08-15 11:47:47 -04:00
Kyle Spearrin
5cdfa35a76 update jslib 2018-08-15 09:01:37 -04:00
Kyle Spearrin
147b3ff993 prelogin kdf info 2018-08-14 15:14:04 -04:00
Kyle Spearrin
662c229de1 add italian language to web vault 2018-08-14 10:42:54 -04:00
Kyle Spearrin
c90cb2ae6e New Crowdin translations (#244)
* New translations messages.json (Chinese Traditional)

* New translations messages.json (Danish)

* New translations messages.json (Dutch)

* New translations messages.json (French)

* New translations messages.json (German)

* New translations messages.json (Italian)

* New translations messages.json (Polish)

* New translations messages.json (Slovak)

* New translations messages.json (Spanish)

* New translations messages.json (Swedish)
2018-08-14 10:40:14 -04:00
Kyle Spearrin
864d070656 bump version 2018-08-14 10:36:45 -04:00
Kyle Spearrin
e8ac2b561a apply filters on org vault 2018-08-13 16:38:21 -04:00
Kyle Spearrin
c71a432ce4 update jslib 2018-08-13 16:27:35 -04:00
Kyle Spearrin
e3ca470a6a implement search service 2018-08-13 16:27:17 -04:00
Kyle Spearrin
e7c6fbf423 bump version 2018-08-08 13:45:07 -04:00
Kyle Spearrin
6cef5e614d dont async refresh and sync 2018-08-08 13:44:01 -04:00
Kyle Spearrin
33cf77559f dont refresh token and sync at same time 2018-08-08 13:41:39 -04:00
Kyle Spearrin
b5085d8004 update packages for node 10 2018-08-08 12:08:26 -04:00
Kyle Spearrin
80af20ef54 control save button enabled for sharing modal 2018-08-07 23:46:31 -04:00
Kyle Spearrin
4a324ca764 New Crowdin translations (#240)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Danish)

* New translations messages.json (French)

* New translations messages.json (German)

* New translations messages.json (Polish)

* New translations messages.json (Portuguese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Spanish)

* New translations messages.json (Swedish)
2018-08-07 15:43:30 -04:00
Kyle Spearrin
85db64ed70 webVault param 2018-08-07 15:04:30 -04:00
Kyle Spearrin
d72ba456ae cacheWeb arg 2018-08-07 14:31:16 -04:00
Kyle Spearrin
b4a0913994 dont need to copy settings file anymore 2018-08-07 14:01:47 -04:00
Kyle Spearrin
6fb8a9ef2f add polish language 2018-08-06 17:42:59 -04:00
Kyle Spearrin
4e58708f12 New Crowdin translations (#238)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Korean)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Estonian)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-08-06 17:41:26 -04:00
Kyle Spearrin
32876367c2 update status maps when user status changes 2018-08-06 17:37:54 -04:00
Kyle Spearrin
226aa0b3ba show message that users needs to be confirmed 2018-08-06 17:18:33 -04:00
Kyle Spearrin
c37359cdfd use jslib import service 2018-08-06 11:40:12 -04:00
Kyle Spearrin
d2d89c252a add new languages 2018-08-06 08:58:50 -04:00
Kyle Spearrin
b76f1d3c8c New Crowdin translations (#237)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Japanese)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-08-06 08:57:14 -04:00
Kyle Spearrin
9ff34a12a2 fix save button on collection management 2018-08-03 21:09:22 -04:00
Kyle Spearrin
c5f6ce3fe5 no org message on share 2018-08-03 21:07:24 -04:00
Kyle Spearrin
965d556ac9 fix grammatical error 2018-08-03 17:13:33 -04:00
Kyle Spearrin
e52d3f21d1 standardize locale name 2018-08-02 09:35:44 -04:00
Kyle Spearrin
00576053d0 toaster paragraph formatting 2018-08-02 08:46:33 -04:00
Kyle Spearrin
1f040efb7f set viewport width 2018-08-01 22:02:32 -04:00
Kyle Spearrin
3b5e9775c5 New Crowdin translations (#235)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Korean)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Estonian)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-08-01 17:03:43 -04:00
Kyle Spearrin
ea0653460e update jslib 2018-08-01 16:55:36 -04:00
Kyle Spearrin
6ed80eb6c9 org disabled and license expired warnings 2018-08-01 16:51:25 -04:00
Kyle Spearrin
12bdd87705 free desc 2018-08-01 15:51:46 -04:00
Kyle Spearrin
9bdf7ff174 remove ps1 script 2018-08-01 10:53:02 -04:00
Kyle Spearrin
2ab2f757a0 is mobile browser checks on autofocus 2018-08-01 09:13:55 -04:00
Kyle Spearrin
f830de8d13 New Crowdin translations (#234)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Korean)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Estonian)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-08-01 07:58:30 -04:00
Kyle Spearrin
7eb329db6b add french translations support 2018-08-01 07:35:33 -04:00
Kyle Spearrin
fecb980c9b update jslib 2018-07-31 23:49:40 -04:00
Kyle Spearrin
600218cf7b support for otpauth 2018-07-31 11:26:04 -04:00
Kyle Spearrin
8eb48e4311 rename to "enable gravatars" 2018-07-31 00:02:09 -04:00
Kyle Spearrin
ac33d2f37c add support for gravatars 2018-07-30 23:52:04 -04:00
Kyle Spearrin
bfc462cbec fix navbar text breaks 2018-07-30 22:53:08 -04:00
Kyle Spearrin
8b8bd88adf control when password history shows 2018-07-30 22:02:01 -04:00
Kyle Spearrin
bc768b773b bump version 2018-07-30 21:24:26 -04:00
Kyle Spearrin
950e5a57b1 additional language support 2018-07-30 21:14:34 -04:00
Kyle Spearrin
52a4fc8e93 clean l10n script 2018-07-30 17:10:35 -04:00
Kyle Spearrin
dd5c840b61 contributing doc 2018-07-30 17:06:57 -04:00
Kyle Spearrin
337c01daf8 select, not select in 2018-07-30 16:57:58 -04:00
Kyle Spearrin
5a9da2a97a New Crowdin translations (#232)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Swedish)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Russian)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Polish)

* New translations messages.json (Korean)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Estonian)

* New translations messages.json (Danish)

* New translations messages.json (Czech)

* New translations messages.json (Ukrainian)
2018-07-30 16:55:06 -04:00
Kyle Spearrin
38c1a0f383 clean l10n command 2018-07-30 16:52:00 -04:00
Kyle Spearrin
2b1718945f update paymentCharged messages 2018-07-30 16:47:25 -04:00
Kyle Spearrin
a6319a3865 update jslib 2018-07-30 11:00:23 -04:00
Kyle Spearrin
35241307d3 update jslib 2018-07-30 10:05:44 -04:00
Kyle Spearrin
ed8aaa5505 view password history 2018-07-30 08:48:48 -04:00
Kyle Spearrin
a25f6dee73 check group access on collection edit page 2018-07-30 08:12:47 -04:00
Kyle Spearrin
9aa8699617 disable autocomplete of password fields 2018-07-30 08:00:23 -04:00
Kyle Spearrin
94f671ca6b show reivison dates for item edit 2018-07-27 23:38:12 -04:00
Kyle Spearrin
7c9016bf4a never option in dev mode 2018-07-27 22:52:27 -04:00
Kyle Spearrin
98d18fb097 only show add button if admin 2018-07-27 22:39:51 -04:00
Kyle Spearrin
dc69887628 fixes for non-admin actions on org vault list 2018-07-27 22:36:25 -04:00
Kyle Spearrin
7c882ed40c catch error 2018-07-27 22:08:31 -04:00
Kyle Spearrin
c8909beedd uncheck all on destroy 2018-07-27 22:05:03 -04:00
Kyle Spearrin
15fc4e5f2d filter ciphers before doing select all, resolves #227 2018-07-27 21:59:49 -04:00
Kyle Spearrin
229b9cf40a update jslib 2018-07-27 21:52:49 -04:00
Kyle Spearrin
17ae441c22 dont set default lock option in dev 2018-07-27 21:52:36 -04:00
Kyle Spearrin
9a70c0e8a7 update jslib 2018-07-27 17:48:32 -04:00
Kyle Spearrin
2a41fee1ff on browser refresh 2018-07-27 15:11:57 -04:00
Kyle Spearrin
f385c3773c allow users to change lock options, default to 15 min 2018-07-27 15:08:59 -04:00
Kyle Spearrin
4b4e847816 Update README.md 2018-07-26 10:03:55 -04:00
Kyle Spearrin
a70c4c250c Update README.md 2018-07-26 10:03:22 -04:00
Kyle Spearrin
950e75e7e3 Update README.md 2018-07-26 10:02:24 -04:00
Kyle Spearrin
2cbf2006c6 Update README.md 2018-07-26 10:02:04 -04:00
Kyle Spearrin
14c4095a4e Update README.md 2018-07-26 09:54:36 -04:00
Kyle Spearrin
c755e8a90d Update README.md 2018-07-26 09:25:43 -04:00
Kyle Spearrin
7c1d824636 New Crowdin translations (#226)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Spanish)

* New translations messages.json (Slovak)

* New translations messages.json (Polish)

* New translations messages.json (Ukrainian)

* New translations messages.json (Estonian)

* New translations messages.json (Danish)

* New translations messages.json (Swedish)

* New translations messages.json (Russian)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Portuguese)

* New translations messages.json (Korean)

* New translations messages.json (Japanese)

* New translations messages.json (Italian)

* New translations messages.json (German)

* New translations messages.json (French)

* New translations messages.json (Czech)
2018-07-26 08:51:51 -04:00
Kyle Spearrin
f71be112c2 added missing filters translation 2018-07-26 08:16:37 -04:00
Kyle Spearrin
8a4dba6317 public computer, not PC 2018-07-25 23:21:41 -04:00
Kyle Spearrin
87c72bd595 append copy textarea to modal if open 2018-07-25 22:01:26 -04:00
Kyle Spearrin
f9e756402f prod endpoints commented in 2018-07-25 21:41:55 -04:00
Kyle Spearrin
f576bbd3e1 adjust frontend footer margins 2018-07-25 14:26:22 -04:00
Kyle Spearrin
f57d54249c dont show terms on self hosted 2018-07-25 13:59:55 -04:00
Kyle Spearrin
20dca960ef frontend cards are d-block 2018-07-25 12:13:18 -04:00
Kyle Spearrin
fe9df3977a add/remove created anchor to page when clicking it 2018-07-25 12:04:14 -04:00
Kyle Spearrin
c5bac554a7 overflow hidden on user menu 2018-07-25 11:45:07 -04:00
Kyle Spearrin
0e791fd0ec added sk language 2018-07-25 11:38:37 -04:00
Kyle Spearrin
6fb9aafa03 New Crowdin translations (#224)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (French)

* New translations messages.json (German)

* New translations messages.json (Italian)

* New translations messages.json (Portuguese)

* New translations messages.json (Russian)

* New translations messages.json (Spanish)

* New translations messages.json (Danish)

* New translations messages.json (Estonian)

* New translations messages.json (Polish)

* New translations messages.json (Slovak)
2018-07-25 11:36:39 -04:00
Kyle Spearrin
12f7f764dc upadte jslib 2018-07-25 11:01:24 -04:00
Kyle Spearrin
d9a09a815a remove partial line 2018-07-25 09:26:04 -04:00
Kyle Spearrin
489c7934bf showPremiumCallout always after sync 2018-07-25 09:24:55 -04:00
Kyle Spearrin
5cc1438e8b inOrgWithPremium after sync 2018-07-25 09:23:29 -04:00
Kyle Spearrin
6ee2f05fb7 Whoops 2018-07-25 09:13:46 -04:00
Kyle Spearrin
695dc98010 fix url encoding issue with spaces 2018-07-25 09:10:24 -04:00
Kyle Spearrin
cbc975399c update jslib 2018-07-24 23:23:03 -04:00
Kyle Spearrin
25c643a1a3 vivaldi supports u2f 2018-07-24 21:49:09 -04:00
Kyle Spearrin
2a16be2fb2 await org premium check 2018-07-24 10:53:01 -04:00
Kyle Spearrin
105a7870bf dont show premium ad if in rog with premium 2018-07-24 10:44:52 -04:00
Kyle Spearrin
c05442dea8 delpoy script 2018-07-24 08:45:02 -04:00
Kyle Spearrin
370197aea3 Update README.md 2018-07-24 08:16:49 -04:00
Kyle Spearrin
cf09918a94 sort languages 2018-07-23 22:45:43 -04:00
Kyle Spearrin
65713477de set locale for angular app 2018-07-23 21:47:08 -04:00
Kyle Spearrin
9d4f29f0a9 add danish support 2018-07-23 20:16:49 -04:00
Kyle Spearrin
85429bc505 New Crowdin translations (#222)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (French)

* New translations messages.json (German)

* New translations messages.json (Italian)

* New translations messages.json (Japanese)

* New translations messages.json (Korean)

* New translations messages.json (Portuguese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Spanish)

* New translations messages.json (Swedish)

* New translations messages.json (Danish)

* New translations messages.json (Estonian)

* New translations messages.json (Ukrainian)
2018-07-23 20:13:48 -04:00
Kyle Spearrin
5b66143fbe update sub 2018-07-23 17:37:41 -04:00
Kyle Spearrin
ca78953889 password agent csv importer, resolves #221 2018-07-23 17:34:13 -04:00
Kyle Spearrin
865d475083 fix u2f ref 2018-07-23 17:15:33 -04:00
Kyle Spearrin
6b9c9f9f78 agree to policies on registration page 2018-07-23 16:37:10 -04:00
Kyle Spearrin
97dfb6fdec gnome json importer 2018-07-23 12:04:38 -04:00
Kyle Spearrin
473f5bfb62 passkeep csv importer 2018-07-23 11:41:15 -04:00
Kyle Spearrin
183f5fea5c splash id importer 2018-07-23 11:23:23 -04:00
Kyle Spearrin
69e059ba01 sort user groups 2018-07-23 10:57:25 -04:00
Kyle Spearrin
3544c96a64 nothing selected error 2018-07-21 21:58:24 -04:00
Kyle Spearrin
56c2515f01 mobile check for u2f 2018-07-21 15:45:35 -04:00
Kyle Spearrin
90d3639796 update jslib 2018-07-21 14:38:29 -04:00
Kyle Spearrin
a3e994fc95 update jslib 2018-07-21 14:07:13 -04:00
Kyle Spearrin
98b3cfaaa0 update jslib 2018-07-21 09:59:52 -04:00
Kyle Spearrin
a8f28af2b3 bind nfc 2018-07-21 09:50:50 -04:00
Kyle Spearrin
c2603c3f53 yubikey nfc true by default 2018-07-21 09:28:59 -04:00
Kyle Spearrin
949433b65f update jslib 2018-07-21 08:21:16 -04:00
Kyle Spearrin
dda1a9ecc4 update jslib 2018-07-21 00:32:49 -04:00
Kyle Spearrin
abdb40179c fix u2f params 2018-07-21 00:26:16 -04:00
Kyle Spearrin
c1efe268d0 gulp postdist tasks for version file 2018-07-21 00:11:55 -04:00
Kyle Spearrin
58818dabc5 vendor js chunk 2018-07-20 22:46:03 -04:00
Kyle Spearrin
24ee5c2d5d cleanup braintree stylesheet 2018-07-20 17:37:16 -04:00
Kyle Spearrin
93cec9a2d6 show refunded status 2018-07-20 17:20:41 -04:00
Kyle Spearrin
fe1c5b4b38 update jslib 2018-07-20 13:01:58 -04:00
Kyle Spearrin
e3e94ede65 allow custom plans to download license 2018-07-20 12:16:41 -04:00
Kyle Spearrin
b9ea3de860 premium callout 2018-07-20 10:44:17 -04:00
Kyle Spearrin
b99df5905f handle redirect params for create org/premium 2018-07-20 10:29:40 -04:00
Kyle Spearrin
a5246df3ed check for email verified on premium license upload 2018-07-19 22:04:16 -04:00
Kyle Spearrin
f4127a575b filter analytics on self host 2018-07-19 19:49:48 -04:00
Kyle Spearrin
65860b166f set environmentService baseUrl on self host 2018-07-19 17:27:02 -04:00
Kyle Spearrin
59f5304d87 no collections message 2018-07-19 17:17:30 -04:00
Kyle Spearrin
3d4848da90 zoho csv importer 2018-07-19 15:13:12 -04:00
Kyle Spearrin
f43fd34a8c fallback to en-us 2018-07-19 14:33:33 -04:00
Kyle Spearrin
bb68303b03 larn more links 2018-07-19 13:56:44 -04:00
Kyle Spearrin
236bcdfb68 skip no folder when updating key 2018-07-19 13:31:14 -04:00
Kyle Spearrin
6c7df2788e footer updates 2018-07-19 12:21:31 -04:00
Jacob
b3a344635a Fetch image from bitwarden/brand (#219) 2018-07-19 10:50:45 -04:00
Kyle Spearrin
4ca29a4a75 New Crowdin translations (#218)
* New translations messages.json (Chinese Simplified)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (French)

* New translations messages.json (German)

* New translations messages.json (Italian)

* New translations messages.json (Japanese)

* New translations messages.json (Korean)

* New translations messages.json (Portuguese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Russian)

* New translations messages.json (Spanish)

* New translations messages.json (Swedish)
2018-07-19 09:37:19 -04:00
Kyle Spearrin
de35a62984 remove spansih translation file 2018-07-19 09:33:43 -04:00
Kyle Spearrin
ef886c8742 crowdin yml 2018-07-19 09:32:48 -04:00
Kyle Spearrin
1b754b435b rel="noopener" on all target _blank links 2018-07-19 09:18:31 -04:00
Kyle Spearrin
50b7ce764e trim all domains 2018-07-19 09:16:23 -04:00
Kyle Spearrin
090fa76d15 update jslib 2018-07-19 08:30:19 -04:00
Kyle Spearrin
898137c8a5 password boss importer 2018-07-19 08:05:53 -04:00
Kyle Spearrin
901a9ae9d7 ascendo dv csv importer 2018-07-19 00:01:29 -04:00
Kyle Spearrin
40a5c6f55e remove base tag 2018-07-18 22:53:16 -04:00
Kyle Spearrin
6d0651a1cb move org id to base class 2018-07-18 17:20:35 -04:00
Kyle Spearrin
ee4d2400c9 org 2fa setting for duo 2018-07-18 17:10:26 -04:00
Kyle Spearrin
5131ebb9c9 docker build updates 2018-07-18 15:21:51 -04:00
Kyle Spearrin
0a86709440 update jslib 2018-07-18 15:09:25 -04:00
Kyle Spearrin
9d5b9f0bde inject Angulartics2GoogleAnalytics 2018-07-18 12:57:20 -04:00
Kyle Spearrin
19fa769bd3 only show disable all keys if enabled 2018-07-18 12:42:06 -04:00
Kyle Spearrin
de8e2d1be7 chunkhas on packed assets 2018-07-18 12:34:08 -04:00
Kyle Spearrin
f546d682bd fixes for pathed URL 2018-07-18 12:19:16 -04:00
Kyle Spearrin
197d1c673c subscription null check 2018-07-18 12:13:24 -04:00
Kyle Spearrin
16e6a88ccf deploy with gh-pages 2018-07-18 12:11:35 -04:00
Kyle Spearrin
de43eb4a57 clean gulp task 2018-07-18 11:15:23 -04:00
Kyle Spearrin
ff64ad8df0 gulp webfonts task as part of build 2018-07-18 10:54:22 -04:00
Kyle Spearrin
e55408424e delete webfonts 2018-07-18 10:48:44 -04:00
Kyle Spearrin
3c9354ba2f local webfonts 2018-07-18 10:32:44 -04:00
Kyle Spearrin
2382d5028b passbolt csv import 2018-07-18 10:10:45 -04:00
Kyle Spearrin
7346958b27 totp upgrade fixes 2018-07-18 09:47:02 -04:00
Kyle Spearrin
78e12775e4 fix margin 2018-07-18 09:37:50 -04:00
Kyle Spearrin
a76053be58 new org button 2018-07-18 09:34:48 -04:00
Kyle Spearrin
028731458b update jslib 2018-07-18 09:21:41 -04:00
Kyle Spearrin
1cee1c6e8f premium and paid org callouts 2018-07-18 09:21:23 -04:00
Kyle Spearrin
1f6dd079cd user => organizationId 2018-07-17 23:52:03 -04:00
Kyle Spearrin
faddfe8506 roboform csv importer 2018-07-17 23:47:31 -04:00
Kyle Spearrin
223cd61220 missing loading 2018-07-17 23:27:56 -04:00
Kyle Spearrin
8278a8f3e4 remove all blur clicks 2018-07-17 23:21:23 -04:00
Kyle Spearrin
8bd9eafa37 loading titles 2018-07-17 23:15:15 -04:00
Kyle Spearrin
9a23d5fa97 billing updates 2018-07-17 22:49:53 -04:00
Kyle Spearrin
4557366154 formatting 2018-07-17 22:21:59 -04:00
Kyle Spearrin
8f95ba03ab disable and mark accessall groups 2018-07-17 22:21:09 -04:00
Kyle Spearrin
89b7672630 lint fix 2018-07-17 17:38:48 -04:00
Kyle Spearrin
49f948844f update enc key 2018-07-17 17:22:51 -04:00
Kyle Spearrin
d1395e37fd only owner can access org settings 2018-07-17 15:57:04 -04:00
Kyle Spearrin
06de7b5176 verify bank account 2018-07-17 15:53:52 -04:00
Kyle Spearrin
56b9cb5c9e adjust payment for orgs 2018-07-17 15:07:32 -04:00
Kyle Spearrin
e4a684ff10 org billing seat adjustments 2018-07-17 12:07:52 -04:00
Kyle Spearrin
e4f12ed47f download license for org 2018-07-17 11:25:41 -04:00
Kyle Spearrin
6fcda290c7 org change plan, cancel, reinstate actions 2018-07-17 11:04:40 -04:00
Kyle Spearrin
243a00e326 CVV security code 2018-07-17 10:23:13 -04:00
Kyle Spearrin
d274a83c24 clipperz html importer 2018-07-17 10:08:38 -04:00
Kyle Spearrin
bdb95e58e6 truekey csv importer 2018-07-17 00:15:18 -04:00
Kyle Spearrin
0650cafb28 org billing settings setup 2018-07-16 17:17:07 -04:00
Kyle Spearrin
786f6953e7 my organization page 2018-07-16 12:42:49 -04:00
Kyle Spearrin
a1d52af0ba generate qr code locally 2018-07-13 23:15:09 -04:00
Kyle Spearrin
1da85c96cf stick password xml importer 2018-07-13 17:11:31 -04:00
Kyle Spearrin
84dc1d1b74 verify recovery delete page 2018-07-13 16:24:53 -04:00
Kyle Spearrin
63aa55baf1 recover delete request page 2018-07-13 15:54:49 -04:00
Kyle Spearrin
3b28e68e31 recover 2fa 2018-07-13 15:36:27 -04:00
Kyle Spearrin
19d835c793 more form fixes 2018-07-13 14:55:50 -04:00
Kyle Spearrin
df9282e759 adjust form requirements and verbatim input 2018-07-13 14:50:21 -04:00
Kyle Spearrin
c679726564 lead font weight 2018-07-13 11:23:41 -04:00
Kyle Spearrin
7e6f9eb67a register state service 2018-07-13 11:09:24 -04:00
Kyle Spearrin
3cfe8bf751 org invite accept flow on login/register 2018-07-13 10:51:52 -04:00
Kyle Spearrin
a1495a8f0c update jslib 2018-07-13 09:31:40 -04:00
Kyle Spearrin
fe6a40f7d0 move focus to base 2018-07-13 09:29:22 -04:00
Kyle Spearrin
e5733b83a0 remember email on login 2018-07-13 09:13:37 -04:00
Kyle Spearrin
1dc4f851cb hasEncKey checks 2018-07-12 17:09:09 -04:00
Kyle Spearrin
ba2debf577 msecure csv importer 2018-07-12 16:27:37 -04:00
Kyle Spearrin
470a767eaf accept org invite 2018-07-12 16:05:42 -04:00
Kyle Spearrin
8e3d5b99c5 dashlane csv importer 2018-07-12 15:53:34 -04:00
Kyle Spearrin
763e43905a verify email page 2018-07-12 14:19:47 -04:00
Kyle Spearrin
ab4005ae00 verify email and outdated browser callouts 2018-07-12 11:34:51 -04:00
Kyle Spearrin
0c61e48977 update layouts for user groups and collections 2018-07-12 10:41:38 -04:00
Kyle Spearrin
8526ad17c4 add missing strings for date filters 2018-07-12 10:26:22 -04:00
Kyle Spearrin
ee91f4610e check for confirm status before showing events 2018-07-12 10:14:33 -04:00
Kyle Spearrin
1afc05310e pwsafe xml importer 2018-07-12 09:49:00 -04:00
Kyle Spearrin
ed381bcf0a fix orgs load 2018-07-12 09:14:20 -04:00
Kyle Spearrin
59aaa07e3b set bg color of callout 2018-07-12 09:12:04 -04:00
Kyle Spearrin
4d759a6995 enpass csv importer 2018-07-12 00:11:14 -04:00
Kyle Spearrin
ce00587041 added password dragon xml importer 2018-07-11 23:30:56 -04:00
Kyle Spearrin
50aad69189 kepper csv importer 2018-07-11 17:43:35 -04:00
Kyle Spearrin
2dc04fa041 status filters for user list 2018-07-11 16:40:32 -04:00
Kyle Spearrin
6dd21fe9e9 wire up search and view events query params 2018-07-11 15:44:40 -04:00
Kyle Spearrin
98d3b42728 generic event log component for user/ciphers 2018-07-11 15:22:55 -04:00
Kyle Spearrin
6d225beb46 user events 2018-07-11 14:43:00 -04:00
Kyle Spearrin
1f7ca7386a reinvite and confirm users 2018-07-11 13:30:17 -04:00
Kyle Spearrin
455df290bf load orgs manually from vault 2018-07-11 11:39:48 -04:00
Kyle Spearrin
2d2192f2f6 update jslib 2018-07-11 10:26:42 -04:00
Kyle Spearrin
175d5ec57f onepassword importers 2018-07-11 10:18:40 -04:00
Kyle Spearrin
255886df53 add more importers 2018-07-11 00:03:40 -04:00
Kyle Spearrin
f0bc2d9c9b add keepass importer 2018-07-10 17:58:08 -04:00
Kyle Spearrin
dc778ea578 import isntructions for safeincloud and padlock 2018-07-10 16:44:13 -04:00
Kyle Spearrin
bd0d321dba add padlock importer, move from maps to arrays 2018-07-10 16:39:04 -04:00
Kyle Spearrin
57e13c25b5 manage user groups 2018-07-10 15:03:13 -04:00
Kyle Spearrin
b428660f92 invite/edit org users 2018-07-10 14:46:13 -04:00
Kyle Spearrin
a8618f1c79 modal widths are fixed 2018-07-10 11:02:25 -04:00
Kyle Spearrin
716619e7f1 always operate in xl breakpoint 2018-07-10 10:55:36 -04:00
Kyle Spearrin
b8da4cf6fc remove viewport meta 2018-07-10 10:47:31 -04:00
Kyle Spearrin
9432abbd1a no group/collections message 2018-07-10 10:07:52 -04:00
Kyle Spearrin
edef454043 collection add/edit modal 2018-07-10 10:06:57 -04:00
Kyle Spearrin
febc3093a9 restrict access based on org permissions 2018-07-10 09:19:29 -04:00
Kyle Spearrin
ddd832d016 fix event i18n ids 2018-07-10 08:47:34 -04:00
Kyle Spearrin
137bb3a4c2 allow removeal of accessall users on groups 2018-07-10 08:42:15 -04:00
Kyle Spearrin
5ade229cb9 revert usage of THING translations 2018-07-10 08:39:05 -04:00
Kyle Spearrin
a6bd9ecfa3 remove text button 2018-07-10 08:20:22 -04:00
Kyle Spearrin
1cb396dc51 entity users component 2018-07-09 23:48:26 -04:00
Kyle Spearrin
a27357213a external id desc 2018-07-09 21:44:48 -04:00
Kyle Spearrin
2d4676ed7e primary outline btn 2018-07-09 17:21:13 -04:00
Kyle Spearrin
3e9ac965e8 Merge branch 'master' of github.com:bitwarden/web 2018-07-09 17:07:16 -04:00
Kyle Spearrin
a45c77bda9 aot compilation fixes 2018-07-09 17:07:13 -04:00
Kyle Spearrin
e659fd1262 Update README.md 2018-07-09 17:02:03 -04:00
Kyle Spearrin
7459f1d1ad Update README.md 2018-07-09 17:01:15 -04:00
Kyle Spearrin
637120d0c5 make shareableCiphers public 2018-07-09 16:56:09 -04:00
Kyle Spearrin
cd131b2d21 use https for submodule 2018-07-09 16:52:46 -04:00
Kyle Spearrin
90dd0d0b9b Update README.md 2018-07-09 16:38:21 -04:00
Kyle Spearrin
3358846d41 Merge branch 'angular' 2018-07-09 16:34:17 -04:00
Mart124
473fc1a766 Add a bitwarden label to docker images (#210)
* Add a bitwarden label to docker images

* Prefix label with reverse DNS
2018-07-09 16:33:05 -04:00
Kyle Spearrin
ecfecd295a group add/edit/delete 2018-07-09 16:27:54 -04:00
Kyle Spearrin
b774091b83 placeholders showing format for datetime 2018-07-09 14:29:19 -04:00
Kyle Spearrin
f49640cbe6 event page tweaks 2018-07-09 12:22:32 -04:00
Kyle Spearrin
8b4fadde2b update jslib 2018-07-09 11:49:24 -04:00
Kyle Spearrin
1b94b22360 view l10n 2018-07-09 11:49:08 -04:00
Kyle Spearrin
b090de0da1 event info 2018-07-09 11:47:57 -04:00
Kyle Spearrin
0294c2cb6d device types for web 2018-07-09 09:32:24 -04:00
Kyle Spearrin
d9bcce781a style updates 2018-07-08 00:27:37 -04:00
Kyle Spearrin
3451322a38 org import has all options 2018-07-08 00:01:50 -04:00
Kyle Spearrin
ba604fcd3c update jslib 2018-07-07 23:50:31 -04:00
Kyle Spearrin
c7df888d39 add safeincloud imports 2018-07-07 23:50:22 -04:00
Kyle Spearrin
7b80505f69 api service to audit service 2018-07-07 23:50:06 -04:00
Kyle Spearrin
de5914194e ie11 style fixes 2018-07-07 23:49:48 -04:00
Kyle Spearrin
e9da73b930 event filters and paging 2018-07-06 23:08:10 -04:00
Kyle Spearrin
15cc46bba5 loading styles 2018-07-06 16:36:51 -04:00
Kyle Spearrin
417743ccdd style tweaks 2018-07-06 16:21:19 -04:00
Kyle Spearrin
0f04286783 change org nav bg color 2018-07-06 16:13:12 -04:00
Kyle Spearrin
3e0f2126b3 list styling for people 2018-07-06 15:45:35 -04:00
Kyle Spearrin
656d17cc07 id searching 2018-07-06 15:03:54 -04:00
Kyle Spearrin
35bb106654 people listing 2018-07-06 15:01:23 -04:00
Kyle Spearrin
634e5e27d3 sort groups 2018-07-06 14:22:20 -04:00
Kyle Spearrin
0f9186628b sort orgs 2018-07-06 14:19:49 -04:00
Kyle Spearrin
6267ca52fc remove form inline 2018-07-06 14:15:10 -04:00
Kyle Spearrin
06b32dc6ec cast fixes 2018-07-06 12:55:59 -04:00
Kyle Spearrin
93582da044 collection and group listing from org admin 2018-07-06 12:49:06 -04:00
Kyle Spearrin
d830499c76 stub out org manage pages 2018-07-06 10:21:08 -04:00
Kyle Spearrin
30d1a119f3 lint fix 2018-07-06 10:07:03 -04:00
Kyle Spearrin
5efab1d495 add my account to nav dropdown 2018-07-06 10:04:53 -04:00
Kyle Spearrin
1228010488 avatar in nav dropdown 2018-07-06 10:00:09 -04:00
Kyle Spearrin
b8921713eb nav dropdown menu styling 2018-07-06 09:47:50 -04:00
Kyle Spearrin
0b779dfd3d layout fixes 2018-07-06 00:29:10 -04:00
Kyle Spearrin
311baaa3d1 navigate fix on import success 2018-07-05 23:44:58 -04:00
Kyle Spearrin
6f75e0bba0 org imports 2018-07-05 23:38:36 -04:00
Kyle Spearrin
6193bf431d set page titles 2018-07-05 22:37:35 -04:00
Kyle Spearrin
7baf72d3db org route guards 2018-07-05 15:27:23 -04:00
Kyle Spearrin
ba3b2fbed1 exporting organization data 2018-07-05 14:40:53 -04:00
Kyle Spearrin
9d4e0849d6 move org vault stuff into subfolder 2018-07-05 13:14:33 -04:00
Kyle Spearrin
1a51a7bf5b default collection is i18n 2018-07-05 13:08:29 -04:00
Kyle Spearrin
7d42c4eaa0 org vault collections 2018-07-05 12:56:58 -04:00
Kyle Spearrin
1d60e881ee admin cipher attachments 2018-07-05 10:48:51 -04:00
Kyle Spearrin
fda8155894 set org id when encrypting new 2018-07-05 10:10:30 -04:00
Kyle Spearrin
f089b5e3d1 inherit local base for groupings and ciphers 2018-07-05 09:58:15 -04:00
Kyle Spearrin
f578ebe4ef org cipher add/edit 2018-07-05 09:42:50 -04:00
Kyle Spearrin
b97378dd40 sync after premium/org purchase 2018-07-05 08:39:22 -04:00
Kyle Spearrin
32f62b7ceb org component, org vault listing updates 2018-07-04 09:55:52 -04:00
Kyle Spearrin
db43f817f7 unassigned collection filtering 2018-07-03 23:43:57 -04:00
Kyle Spearrin
3c45e7dac9 org vault listing from apis 2018-07-03 23:33:19 -04:00
Kyle Spearrin
f1584ad7d7 org vault listing from apis 2018-07-03 23:33:12 -04:00
Kyle Spearrin
8f503f4f99 org component loaded independently 2018-07-03 16:04:38 -04:00
Kyle Spearrin
499ecf9c39 org layout 2018-07-03 15:44:33 -04:00
Kyle Spearrin
9cf15e37ce add circle input for avatar 2018-07-03 15:11:58 -04:00
Kyle Spearrin
6d731e2939 setup org module and link org listing 2018-07-03 12:34:20 -04:00
Kyle Spearrin
1e7c2c2362 add name to registration form 2018-07-03 11:42:50 -04:00
Kyle Spearrin
ae51847f02 premium link 2018-07-03 09:58:35 -04:00
Kyle Spearrin
738eaa6ca7 create by license moved from update license component 2018-07-03 09:55:59 -04:00
Kyle Spearrin
70dbca67e7 move premium component to it's own route 2018-07-03 09:27:59 -04:00
Kyle Spearrin
16c3d4c253 style updates on total 2018-07-03 00:16:34 -04:00
Kyle Spearrin
1f62b9fdcb org create 2018-07-02 17:09:53 -04:00
Kyle Spearrin
bd070ff066 no organizations message 2018-07-02 10:58:07 -04:00
Kyle Spearrin
3bb667f524 create and update premium license for self host 2018-07-02 10:30:51 -04:00
Kyle Spearrin
463c1f8b77 alt color navbar on self host 2018-06-30 14:19:01 -04:00
Kyle Spearrin
c5d575b9b6 self host builds 2018-06-30 14:14:52 -04:00
Kyle Spearrin
d509637623 adjust payment 2018-06-30 13:36:39 -04:00
Kyle Spearrin
37026e556f adjust storage implementation 2018-06-29 23:41:35 -04:00
Kyle Spearrin
f7b9416460 user billing page 2018-06-29 16:55:54 -04:00
Kyle Spearrin
1ac22c6d48 col6 2018-06-29 10:49:46 -04:00
Kyle Spearrin
66cb7f9bf0 card brand images 2018-06-29 10:27:04 -04:00
Kyle Spearrin
87f7b782dc blur csv import 2018-06-29 09:28:02 -04:00
Kyle Spearrin
15d6e4937f changed breach report to allow username entry 2018-06-29 08:21:08 -04:00
Kyle Spearrin
dec6b17aa4 missing premium updated message 2018-06-28 23:11:47 -04:00
Kyle Spearrin
4a2b3d6293 load premium status after pruchase 2018-06-28 23:05:49 -04:00
Kyle Spearrin
04ef16a94b premium callout 2018-06-28 22:40:07 -04:00
Kyle Spearrin
fd88a066da payment component and styling 2018-06-28 22:27:32 -04:00
Kyle Spearrin
7267045475 stub out premium payment with payment form 2018-06-28 17:17:14 -04:00
Kyle Spearrin
318b750603 stub out billing component 2018-06-28 14:05:04 -04:00
Kyle Spearrin
38e87b1af0 breach report styling 2018-06-28 11:59:49 -04:00
Kyle Spearrin
ce96a32af3 data breach report 2018-06-28 11:58:33 -04:00
Kyle Spearrin
0ec9045849 u2f logo 2018-06-28 09:46:27 -04:00
Kyle Spearrin
b9895ba79a 2fa recovery code view 2018-06-28 09:40:11 -04:00
Kyle Spearrin
ff65297275 consolidate 2fa component functionality 2018-06-27 23:55:50 -04:00
Kyle Spearrin
c647c0f509 lint fixes 2018-06-27 22:09:50 -04:00
Kyle Spearrin
5760efdaa1 u2d lib is externals 2018-06-27 22:05:33 -04:00
Kyle Spearrin
bf5d8cab1c implement 2fa setup for u2f 2018-06-27 17:50:31 -04:00
Kyle Spearrin
890bf49294 email 2fa setup 2018-06-27 16:56:11 -04:00
Kyle Spearrin
a097793b0d configure duo 2fa 2018-06-27 15:27:59 -04:00
Kyle Spearrin
4b4bedaef3 yubikey 2fa config 2018-06-27 13:45:11 -04:00
Kyle Spearrin
246d605e5c autofocus any type of element on modal shown 2018-06-27 09:45:26 -04:00
Kyle Spearrin
f43319ba7a focus any necessary input elements on modal shown 2018-06-27 09:38:44 -04:00
Kyle Spearrin
09ef907673 authenticator setup 2018-06-27 09:20:09 -04:00
Kyle Spearrin
e345bbcae0 implement two-factor setup page 2018-06-26 22:51:58 -04:00
Kyle Spearrin
381da132f8 sync is not forced 2018-06-26 12:03:11 -04:00
Kyle Spearrin
998a63612f domain rules page implementation 2018-06-26 11:50:23 -04:00
Kyle Spearrin
63ccc49ce2 import analytics 2018-06-26 09:11:29 -04:00
Kyle Spearrin
ce3b4cd817 save button for options 2018-06-26 09:04:12 -04:00
Kyle Spearrin
28f4ed9144 some styling 2018-06-26 08:49:45 -04:00
Kyle Spearrin
4bd47f728a stub out domain rules page 2018-06-25 23:16:59 -04:00
Kyle Spearrin
03dfda7a17 callout component 2018-06-25 20:49:49 -04:00
Kyle Spearrin
1717960a8c options page description 2018-06-25 17:17:55 -04:00
Kyle Spearrin
bb14aa821b options 2018-06-25 16:44:06 -04:00
Kyle Spearrin
fd8128dfe9 callout 2018-06-25 16:04:19 -04:00
Kyle Spearrin
9b67f6e398 improt instructions 2018-06-25 15:47:05 -04:00
Kyle Spearrin
e59277742d avira csv importer 2018-06-25 15:20:58 -04:00
Kyle Spearrin
53d23ec831 update cipher lsiting properly when folder deleted 2018-06-25 15:20:45 -04:00
Kyle Spearrin
a2a6d89908 new folder service deps 2018-06-25 15:20:18 -04:00
Kyle Spearrin
be29e6d847 update jslib 2018-06-25 11:40:13 -04:00
Kyle Spearrin
c26a6a5252 encrypt and post import to api 2018-06-25 11:39:55 -04:00
Kyle Spearrin
ce01fe6141 importing 2018-06-23 15:16:23 -04:00
Kyle Spearrin
39ff952667 export vault on buttton 2018-06-23 09:27:46 -04:00
Kyle Spearrin
cafc65ffa5 blur clicks 2018-06-21 22:41:36 -04:00
Kyle Spearrin
cccd2abb55 purge vault and delete account features 2018-06-21 22:40:01 -04:00
Kyle Spearrin
cb1a62ee27 set proper api url 2018-06-21 22:10:20 -04:00
Kyle Spearrin
51efa59728 set api urls for dev 2018-06-21 21:32:17 -04:00
Kyle Spearrin
aed5db0a8c deauth sessions 2018-06-21 17:14:36 -04:00
Kyle Spearrin
0599dd1525 no toggle on export password field 2018-06-21 15:59:31 -04:00
Kyle Spearrin
989f4c3aa5 danger zone 2018-06-21 15:57:28 -04:00
Kyle Spearrin
22093d5111 change master password implementation 2018-06-21 15:30:17 -04:00
Kyle Spearrin
7022bf005f update jslib 2018-06-21 14:29:09 -04:00
Kyle Spearrin
68b8ad7e28 change email components implemented 2018-06-21 14:28:00 -04:00
Kyle Spearrin
306f8a43e1 stub out change email/password components 2018-06-21 11:47:23 -04:00
Kyle Spearrin
e46f3073b4 move profile to its own component 2018-06-21 11:43:50 -04:00
Kyle Spearrin
ed65bcf185 fallback to email on avatar 2018-06-21 11:29:32 -04:00
Kyle Spearrin
9633800977 avatar component 2018-06-21 11:28:14 -04:00
Kyle Spearrin
1fb4f2946a submit button spinners 2018-06-21 10:06:32 -04:00
Kyle Spearrin
d73b01674f update profile 2018-06-20 23:35:40 -04:00
Kyle Spearrin
271510ffb5 stub out settings 2018-06-20 22:27:37 -04:00
Kyle Spearrin
16b29c6116 cleanup generator 2018-06-20 22:12:54 -04:00
Kyle Spearrin
367104f0a7 added password generator tool 2018-06-20 18:16:20 -04:00
Kyle Spearrin
7979953f33 export data 2018-06-20 16:28:56 -04:00
Kyle Spearrin
5ffd13e2c8 totp code generation on add/edit page 2018-06-19 23:40:51 -04:00
Kyle Spearrin
edb1700218 monospaced card code input 2018-06-18 17:32:59 -04:00
Neil Burrows
9729a2595d Card Code Mask in Angular Branch (#212) 2018-06-18 07:42:58 -04:00
Kyle Spearrin
7c3468fbcb update jslib 2018-06-13 22:14:55 -04:00
Kyle Spearrin
94c5bdb5aa implement hasKey helper 2018-06-13 17:21:27 -04:00
Kyle Spearrin
e714d61a66 update jslib 2018-06-13 17:15:23 -04:00
Kyle Spearrin
14ecc534e0 setUrlsFromStorage in init 2018-06-13 14:09:16 -04:00
Kyle Spearrin
e18f76d2b0 stub out bulk share 2018-06-13 00:03:48 -04:00
Kyle Spearrin
3edf761549 bulk move 2018-06-12 17:33:08 -04:00
Kyle Spearrin
27f18c1630 update jslib 2018-06-12 17:12:34 -04:00
Kyle Spearrin
314ab61349 bulk actions stubbed out. bulk delete implemented 2018-06-12 17:11:24 -04:00
Kyle Spearrin
3666ee5a87 only use blob options if available and not IE 2018-06-12 14:35:44 -04:00
Kyle Spearrin
1f3ecbab33 delete from cipher list 2018-06-12 14:15:19 -04:00
Kyle Spearrin
4aacc06af0 disabled button styling 2018-06-12 14:06:42 -04:00
Kyle Spearrin
ddab383b55 manage item collections 2018-06-12 13:08:47 -04:00
Kyle Spearrin
edef3f90f1 sharing 2018-06-12 11:46:11 -04:00
Kyle Spearrin
85fd36f5c3 update jslib 2018-06-11 13:40:26 -04:00
Kyle Spearrin
d16f599db9 fixes for duo 2018-06-11 12:58:56 -04:00
Kyle Spearrin
ba6451856a frontend footer 2018-06-11 12:06:57 -04:00
Kyle Spearrin
f1651078e4 fido u2f fixes 2018-06-11 11:58:11 -04:00
Kyle Spearrin
a6aef345d5 two-step login pages 2018-06-11 11:43:10 -04:00
Kyle Spearrin
4df4f57de3 logo height 2018-06-11 10:27:36 -04:00
Kyle Spearrin
5bd9a9a81d loaded state for orgs 2018-06-11 10:26:02 -04:00
Kyle Spearrin
a0ac8ec9c2 org link styles 2018-06-11 10:13:06 -04:00
Kyle Spearrin
2bac2f1a39 organizations component in vault 2018-06-11 10:09:59 -04:00
Kyle Spearrin
ab353d8498 add cipher from list 2018-06-11 09:43:22 -04:00
Kyle Spearrin
f054365a46 cache tag 2018-06-11 09:37:29 -04:00
Kyle Spearrin
cfc3fae67c application version 2018-06-11 09:31:11 -04:00
Kyle Spearrin
5d8e32222a use html storage for secure storage in dev 2018-06-11 09:17:41 -04:00
Kyle Spearrin
21a126f31f no items to list 2018-06-11 09:17:24 -04:00
Kyle Spearrin
d21540878e prod build fixes 2018-06-11 08:54:48 -04:00
Kyle Spearrin
894ab16b35 page header styles 2018-06-09 23:43:33 -04:00
Kyle Spearrin
945d661a1e tools pages stubbed out 2018-06-09 23:33:12 -04:00
Kyle Spearrin
a176a4819f logo styling and lock now 2018-06-09 23:13:19 -04:00
Kyle Spearrin
6892badf36 mute color on lock 2018-06-09 22:59:36 -04:00
Kyle Spearrin
5db9e9531f route to previous url after unlock 2018-06-09 22:40:53 -04:00
Kyle Spearrin
7ebd18b00d auth guards 2018-06-09 22:02:45 -04:00
Kyle Spearrin
9f1c7a0a32 html/memory storage services 2018-06-09 15:26:21 -04:00
Kyle Spearrin
561120c51c add local and memory storage to web storage service 2018-06-09 15:19:05 -04:00
Kyle Spearrin
b93b9feee4 enable lock timeout 2018-06-09 14:55:34 -04:00
Kyle Spearrin
ea6317e3a2 lock screen. cleanup modals on navigate 2018-06-09 13:59:09 -04:00
Kyle Spearrin
5ecb26b032 refresh list if attachments change 2018-06-09 13:29:30 -04:00
Mart124
c1a0818376 Add a bitwarden label to docker images (#210)
* Add a bitwarden label to docker images

* Prefix label with reverse DNS
2018-06-09 08:17:56 -04:00
Kyle Spearrin
fbc756c6e3 style fixes on add/edit lists 2018-06-09 00:39:14 -04:00
Kyle Spearrin
8f258a2d05 frontend page styling 2018-06-09 00:38:55 -04:00
Kyle Spearrin
d4d01cc186 set frontend layout body class 2018-06-08 17:37:39 -04:00
Kyle Spearrin
5098153fde layouts and messaging 2018-06-08 17:08:19 -04:00
Kyle Spearrin
63a56b359b swal styling 2018-06-08 15:20:07 -04:00
Kyle Spearrin
38a95c3745 dialogs with swal 2018-06-08 14:56:26 -04:00
Kyle Spearrin
f05c6ccddd attachments list icon 2018-06-08 12:45:31 -04:00
Kyle Spearrin
de9780a756 toaster styles 2018-06-08 12:32:00 -04:00
Kyle Spearrin
b34e511ddc savefile imeplementation 2018-06-08 12:23:46 -04:00
Kyle Spearrin
3de3c7a189 add download file function for attachments 2018-06-08 12:16:47 -04:00
Kyle Spearrin
d256a872fc cipher attachments modal 2018-06-08 12:04:03 -04:00
Kyle Spearrin
3db86e2a6b move duo connector to ts 2018-06-08 10:15:45 -04:00
Kyle Spearrin
6436bb65e2 IE fixes and polyfills 2018-06-07 23:38:17 -04:00
Kyle Spearrin
059df9c45d various vault functionality 2018-06-07 17:12:11 -04:00
Kyle Spearrin
a18a591f0a layouts for cipher/folder add/edit 2018-06-07 10:21:28 -04:00
Kyle Spearrin
08dc36fbb0 some i18n and modal work 2018-06-07 09:05:25 -04:00
Kyle Spearrin
a0ace6e70f adjust viewport width 2018-06-06 23:38:30 -04:00
Kyle Spearrin
a52aadd37d add/edit cipher modal 2018-06-06 23:23:14 -04:00
Kyle Spearrin
0fb66e247a search and move dropdown button 2018-06-06 23:00:57 -04:00
Kyle Spearrin
ecddc1691f style updates 2018-06-06 17:42:42 -04:00
Kyle Spearrin
b0f683bacf update jslib 2018-06-06 17:27:13 -04:00
Kyle Spearrin
a89cf28812 get vault working 2018-06-06 17:25:57 -04:00
Kyle Spearrin
cc9410602c vault layout 2018-06-06 12:35:10 -04:00
Kyle Spearrin
e814b8ef09 theme styling 2018-06-06 11:58:56 -04:00
Kyle Spearrin
ce34ef902f stubbing out some layout 2018-06-06 09:43:28 -04:00
Kyle Spearrin
db5a5e1b37 toastr container 2018-06-05 15:46:26 -04:00
Kyle Spearrin
9e3f3e324c add missing modules for prod build 2018-06-05 15:06:50 -04:00
Kyle Spearrin
a4ff241574 setup services, accounts components 2018-06-05 15:02:53 -04:00
Kyle Spearrin
28197970bd add jslib 2018-06-05 13:31:25 -04:00
Kyle Spearrin
7aa4450556 webpack adjustments 2018-06-05 11:52:09 -04:00
Kyle Spearrin
dabc37a1ef remove test scripts 2018-06-05 11:16:22 -04:00
Kyle Spearrin
4315000905 rename dev cert to shared 2018-06-05 11:14:53 -04:00
Kyle Spearrin
8d4bd1171b remove old cert 2018-06-05 11:14:15 -04:00
Kyle Spearrin
82c5a53f5d es5 support 2018-06-05 09:34:08 -04:00
Kyle Spearrin
29d0803a5c scripts, connectors, and webpack adjustments 2018-06-05 09:01:40 -04:00
Kyle Spearrin
8f14ced5af u2f connector updates 2018-06-05 00:32:06 -04:00
Kyle Spearrin
9cafb76781 enable prod mode on production env 2018-06-05 00:31:06 -04:00
Kyle Spearrin
22c1b0627e https webpack-serve 2018-06-05 00:02:43 -04:00
Kyle Spearrin
995835a96c copy over some necessary assets 2018-06-04 23:26:05 -04:00
Kyle Spearrin
bf796fe80c stub out angular app with webpack 4 2018-06-04 23:10:41 -04:00
Kyle Spearrin
425029783b cleanup index 2018-06-04 21:55:38 -04:00
Kyle Spearrin
8f399f3c64 cleanout old angular.js app 2018-06-04 21:52:26 -04:00
Kyle Spearrin
192eb7e7c9 bump version 2018-05-31 14:33:00 -04:00
Kyle Spearrin
48a36649fa Merge branch 'master' of github.com:bitwarden/web 2018-05-30 22:36:12 -04:00
Kyle Spearrin
6b83b53401 delete old sln file 2018-05-30 22:36:10 -04:00
Mart124
c953c2b93f Rework service user (#208)
Related to https://github.com/bitwarden/core/pull/292
2018-05-29 16:46:04 -04:00
Kyle Spearrin
7cdce165fb pass token and org user id to registration 2018-05-24 16:51:47 -04:00
Kyle Spearrin
b393064f26 reset folder id for ciphers. resolves #204 2018-05-24 09:21:43 -04:00
Kyle Spearrin
31bf22063e Update README.md 2018-05-12 13:56:19 -04:00
Kyle Spearrin
cd9a43f359 update importer for firefox 2018-05-11 08:04:21 -04:00
Kyle Spearrin
c326e03eb2 null check on subtle 2018-05-05 21:28:34 -04:00
Kyle Spearrin
f0a986aa04 remove old api 2018-04-24 11:47:16 -04:00
Kyle Spearrin
4225da355d publish 2018-04-19 21:21:55 -04:00
Kyle Spearrin
14bac6a744 fix userid comparisons 2018-04-16 16:26:54 -04:00
Kyle Spearrin
05cc9b45e6 bump version 2018-04-16 16:10:53 -04:00
Kyle Spearrin
dba596bf35 fix if when no currentid 2018-04-16 16:08:59 -04:00
Kyle Spearrin
db39d58ea8 remove empty uri on add 2018-04-16 15:17:50 -04:00
Kyle Spearrin
c0f38216ef manage group from entrypoint 2018-04-16 15:17:13 -04:00
Kyle Spearrin
3643222b3c added org duo to 2fa flow 2018-04-03 14:33:00 -04:00
Kyle Spearrin
551217ea38 filter for unassigned collection grouping 2018-04-03 08:35:45 -04:00
Kyle Spearrin
24bf1363ab org 2fa management for duo 2018-04-02 23:19:04 -04:00
Kyle Spearrin
08b2184e12 version bump 2018-04-02 21:22:30 -04:00
Kyle Spearrin
b73161882c make user homedir with helper 2018-04-02 21:12:45 -04:00
Kyle Spearrin
e2186ecd62 Revert "make user home dir"
This reverts commit b407402f3f.
2018-04-02 21:12:02 -04:00
Kyle Spearrin
b407402f3f make user home dir 2018-04-02 19:59:11 -04:00
Kyle Spearrin
8bb4132458 version bump 2018-03-30 10:56:24 -04:00
Kyle Spearrin
443822fd52 step down from host root LUID 2018-03-27 22:56:50 -04:00
Kyle Spearrin
68427fd2de bash 2018-03-27 21:15:16 -04:00
Kyle Spearrin
c3d3369601 proper and syntax for entrypoint conditions 2018-03-27 17:11:48 -04:00
Kyle Spearrin
3c5022d628 upsert bitwarden user 2018-03-27 16:37:50 -04:00
Kyle Spearrin
832ddddc58 gosu 2018-03-27 15:44:25 -04:00
Kyle Spearrin
0fc1415a06 chown deep directories 2018-03-26 14:30:37 -04:00
Kyle Spearrin
1ab408c591 non-root docker 2018-03-26 11:24:09 -04:00
Kyle Spearrin
3160d3f275 disable uglify for now 2018-03-24 20:55:00 -04:00
Kyle Spearrin
d083f1ddc3 version bump and lint fix 2018-03-24 20:49:20 -04:00
Kyle Spearrin
5fbc09b135 cannot create item in collection.
set collection after share.
2018-03-24 20:44:51 -04:00
Kyle Spearrin
6282fabf98 use bitwarden user for docker 2018-03-23 21:21:01 -04:00
Kyle Spearrin
2b528bad97 version json file on dist 2018-03-23 13:04:59 -04:00
Kyle Spearrin
c3be8195fd no edit/del of "no folder" 2018-03-20 15:58:00 -04:00
Kyle Spearrin
39471d0421 loading ciphers false after first chunk 2018-03-19 11:33:52 -04:00
Kyle Spearrin
7a50c0536c loading switches for cipher and groupings 2018-03-19 11:28:23 -04:00
Kyle Spearrin
4ccd9501a8 add back missing select function 2018-03-19 11:14:28 -04:00
Kyle Spearrin
75c05a4a85 version bump in settings 2018-03-17 12:03:07 -04:00
Kyle Spearrin
ca7e12370f version bump 2018-03-17 12:02:00 -04:00
Kyle Spearrin
8bc9dafff2 vault fixes 2018-03-17 12:01:03 -04:00
Kyle Spearrin
dcb0416fd6 re-factor vault listings 2018-03-17 11:42:35 -04:00
Kyle Spearrin
bbb69bba26 Update ISSUE_TEMPLATE.md 2018-03-10 16:36:53 -05:00
Kyle Spearrin
c1838b48ff Create ISSUE_TEMPLATE.md 2018-03-10 09:48:22 -05:00
Kyle Spearrin
d53f40002c totp-col breaks at sm, not md 2018-03-09 23:07:43 -05:00
Kyle Spearrin
866954b180 fix lint issues 2018-03-09 16:42:10 -05:00
Kyle Spearrin
befa9cbf08 version bump 2018-03-09 16:39:17 -05:00
Kyle Spearrin
859f44db43 only perpend http if there is no protocol 2018-03-05 22:15:22 -05:00
Kyle Spearrin
cca9c3c561 get rid of apps page and link to bitwarden.com 2018-03-02 22:42:32 -05:00
Kyle Spearrin
27e68e4c75 multi uri support for import/export 2018-03-02 22:13:53 -05:00
Kyle Spearrin
5c92350ed2 refactor for cipher response. add login uris. 2018-03-02 21:12:26 -05:00
Kyle Spearrin
b94c62d1e5 upadte security md 2018-02-27 23:00:10 -05:00
Kyle Spearrin
de888d8a37 remove pwnedtest 2018-02-27 22:42:39 -05:00
Kyle Spearrin
f8d6816101 Uppercase Bitwarden 2018-02-27 22:41:27 -05:00
Kyle Spearrin
119c6d5817 big-textarea not important 2018-02-27 08:21:26 -05:00
Kyle Spearrin
aaa21daa29 only intercept with headers when api is at start 2018-02-26 23:18:03 -05:00
Kyle Spearrin
10f41bf288 pwned test 2018-02-26 22:52:56 -05:00
Kyle Spearrin
91582691d8 whiteListedDomains for jwt 2018-02-26 13:48:26 -05:00
Kyle Spearrin
463efc2254 use new admin apis for attachments 2018-02-24 14:36:13 -05:00
Kyle Spearrin
0333354271 version bump 2018-02-20 23:34:10 -05:00
Kyle Spearrin
b85f56c681 restore collection ids on edit. resolves #174 2018-02-09 10:39:18 -05:00
Kyle Spearrin
be491be2cd Update organizationBilling.html 2018-02-04 16:00:00 -05:00
Kyle Spearrin
4be4a8115d Update settingsBilling.html 2018-02-04 15:58:41 -05:00
Kyle Spearrin
c0eb499f4d value.type should not be case sensitive 2018-01-26 11:55:57 -05:00
Kyle Spearrin
1b43f3facd check for empty name on SIC importer 2018-01-25 21:22:17 -05:00
Chuck
26d41d3cb9 Change npm to use https for gulp-gh-pages restore. (#168)
When using VS 2017 node.js integration, npm fails because a host key cannot be validated. Switching to https, provides security and no additional configuration to restore the package.
2018-01-23 11:43:51 -05:00
Kyle Spearrin
179765f6e4 use random bytes for each HMAC comparison 2018-01-18 12:07:32 -05:00
Kyle Spearrin
df2e332134 macBuf must exist if key has macKey 2018-01-18 09:03:51 -05:00
Kyle Spearrin
2952f9d158 manifest.json included with dist 2018-01-02 23:54:10 -05:00
Kyle Spearrin
3c9face597 disable autocomplete on duo and yubi setup 2018-01-02 23:38:54 -05:00
Kyle Spearrin
25f2e9c1b7 autocomplete="new-password" to disable autofilling 2018-01-02 22:49:05 -05:00
Kyle Spearrin
a6f8e1b9a3 duo connector moved to its own js file 2018-01-02 13:20:58 -05:00
Kyle Spearrin
d832031cec update cdn libs 2017-12-29 09:45:44 -05:00
Kyle Spearrin
7a1a3ab64d revert uglify removal 2017-12-29 09:28:49 -05:00
Kyle Spearrin
19491a684e additional user/pw field names for roboform 2017-12-29 08:43:07 -05:00
Kyle Spearrin
757224287e disable uglify since it seems to be conflicting 2017-12-29 08:40:37 -05:00
Kyle Spearrin
c9b5426f6f version bump 2017-12-28 12:56:00 -05:00
Kyle Spearrin
bf885c184f lint fixes 2017-12-19 12:15:24 -05:00
Kyle Spearrin
0d2bf4f7a1 update libs 2017-12-19 12:13:33 -05:00
Kyle Spearrin
01ffc68fc2 focus vault search on $viewContentLoaded 2017-12-19 11:30:52 -05:00
Kyle Spearrin
16892239fb cross navigation for event subject ids 2017-12-19 11:14:15 -05:00
Kyle Spearrin
d5765d8814 display app/device info on events 2017-12-18 13:56:38 -05:00
Kyle Spearrin
8d6a96074d send device type header 2017-12-18 13:37:06 -05:00
Kyle Spearrin
f54884eb79 event logs for users. ip address. useEvents checks 2017-12-18 13:17:49 -05:00
Kyle Spearrin
828149b2d6 eventService and cipher event logs page 2017-12-18 11:52:42 -05:00
Kyle Spearrin
501c4fc263 serve CSP from proxy 2017-12-16 23:44:35 -05:00
Kyle Spearrin
1d0b45e17d whiteListedDomains only on dev builds 2017-12-16 23:23:17 -05:00
Kyle Spearrin
a0f7ed68fb content-type doesn't need to be text anymore 2017-12-16 23:14:43 -05:00
Kyle Spearrin
7bd0c17188 switch to fork for gh-pages fix 2017-12-16 23:10:40 -05:00
Kyle Spearrin
1ea9d28523 local api/identity uri paths 2017-12-16 22:08:23 -05:00
Kyle Spearrin
8a3fb92bbe paging 2017-12-15 15:02:27 -05:00
Kyle Spearrin
de3a9b9903 date range filtering 2017-12-15 12:42:21 -05:00
Kyle Spearrin
9834f3d2aa use events check 2017-12-14 18:04:18 -05:00
Kyle Spearrin
ac079b9d88 audit logs icon 2017-12-14 15:24:18 -05:00
Kyle Spearrin
9e96906f32 compute counts on every load scenario 2017-12-14 15:20:18 -05:00
Kyle Spearrin
90c079e743 org events page setup 2017-12-14 15:03:46 -05:00
Kyle Spearrin
4ecf307285 properly flag new folder as type folder
resolves #149
2017-12-09 08:28:52 -05:00
Kyle Spearrin
6cf4c453d9 Update README.md 2017-12-05 11:12:34 -05:00
Philipp Hug
d2899d14c7 vaultAddCipherController.js: secureNote Type is int not string (#144) 2017-12-04 07:59:28 -05:00
Kyle Spearrin
f3b438d514 null ref on keeper import 2017-12-03 21:27:49 -05:00
Kyle Spearrin
2997f694f8 import notes for form fills 2017-11-30 23:45:06 -05:00
Kyle Spearrin
b78ab4db27 import form fill csv for lastpass 2017-11-30 23:40:05 -05:00
Kyle Spearrin
37dddea515 simplify collapse/expand logic 2017-11-30 22:47:16 -05:00
Kyle Spearrin
e307d1e87d init storage 2017-11-29 22:47:21 -05:00
Kyle Spearrin
62e1dbb642 expand/collapse all boxes 2017-11-29 22:43:58 -05:00
Kyle Spearrin
b8a425f530 version bump 2017-11-29 22:12:46 -05:00
Kyle Spearrin
cafb6fa694 not always CSV data 2017-11-28 10:07:21 -05:00
Kyle Spearrin
0482ddea2c store large items in notes for import 2017-11-28 10:02:41 -05:00
Kyle Spearrin
b411176c8d better error message handling 2017-11-28 09:27:44 -05:00
Kyle Spearrin
2f13449cb6 fix null ref 2017-11-22 12:29:30 -05:00
Kyle Spearrin
b0c1b7b683 default password generated is 14 length 2017-11-22 12:28:06 -05:00
Kyle Spearrin
7e8978c7fc single collection icon is a cube 2017-11-22 12:24:21 -05:00
Kyle Spearrin
d58b422bd0 no items in folder/collection 2017-11-22 12:21:55 -05:00
Kyle Spearrin
3563601382 no collections message 2017-11-22 12:17:40 -05:00
Kyle Spearrin
d42e6ca3fd show collection and folder groupings together 2017-11-22 12:08:31 -05:00
Kyle Spearrin
7f0d8c99e3 version bump 2017-11-13 12:31:23 -05:00
Kyle Spearrin
48a67dc2b3 remove amazon app 2017-11-13 12:28:11 -05:00
Kyle Spearrin
8d0b42492d families plan desc 2017-11-08 22:05:53 -05:00
520 changed files with 138358 additions and 24850 deletions

View File

@@ -1,3 +1,3 @@
*
!dist/*
!build/*
!entrypoint.sh

15
.editorconfig Normal file
View File

@@ -0,0 +1,15 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Set default charset
[*.{js,ts,scss,html}]
charset = utf-8
indent_style = space
indent_size = 4

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
*.sh eol=lf
.dockerignore eol=lf
dockerfile eol=lf

212
.gitignore vendored
View File

@@ -1,203 +1,13 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studo 2015 cache/options directory
.vs/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
*.[Cc]ache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
bower_components/
lib/
.vs
.idea
.DS_Store
node_modules
npm-debug.log
vwd.webinfo
css/
dist/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Other
package-lock.json
src/js/*.min.js
*.pem
*.crx
*.zip
build/
!dev-server.shared.pem

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "jslib"]
path = jslib
url = https://github.com/bitwarden/jslib.git
branch = master

1
CNAME
View File

@@ -1 +0,0 @@
vault.bitwarden.com

13
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,13 @@
Code contributions are welcome! Please commit any pull requests against the `master` branch.
# Localization (l10n)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-web/localized.svg)](https://crowdin.com/project/bitwarden-web)
We use a translation tool called [Crowdin](https://crowdin.com) to help manage our localization efforts across many different languages.
If you are interested in helping translate the Bitwarden web vault into another language (or make a translation correction), please register an account at Crowdin and join our project here: https://crowdin.com/project/bitwarden-web
If the language that you are interested in translating is not already listed, create a new account on Crowdin, join the project, and contact the project owner (https://crowdin.com/profile/kspearrin).
You can read Crowdin's getting started guide for translators here: https://support.crowdin.com/crowdin-intro/

View File

@@ -1,10 +1,20 @@
FROM bitwarden/server
LABEL com.bitwarden.product="bitwarden"
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
gosu \
curl \
&& rm -rf /var/lib/apt/lists/*
ENV ASPNETCORE_URLS http://+:5000
WORKDIR /app
COPY ./dist .
EXPOSE 80
EXPOSE 5000
COPY ./build .
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
HEALTHCHECK CMD curl -f http://localhost:5000 || exit 1
ENTRYPOINT ["/entrypoint.sh"]

5
ISSUE_TEMPLATE.md Normal file
View File

@@ -0,0 +1,5 @@
<!--
Please do not submit feature requests. The [Community Forums][1] has a
section for submitting, voting for, and discussing product feature requests.
[1]: https://community.bitwarden.com
-->

View File

@@ -1,31 +1,59 @@
[![appveyor build](https://ci.appveyor.com/api/projects/status/github/bitwarden/web?branch=master&svg=true)](https://ci.appveyor.com/project/bitwarden/web) [![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby)
<p align="center">
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/web-vault-macbook.png" alt="" width="600" height="358" />
</p>
<p align="center">
The Bitwarden web project is an Angular application that powers the web vault (https://vault.bitwarden.com/).
</p>
<p align="center">
<a href="https://ci.appveyor.com/project/bitwarden/web/branch/master" target="_blank">
<img src="https://ci.appveyor.com/api/projects/status/github/bitwarden/web?branch=master&svg=true" alt="appveyor build" />
</a>
<a href="https://crowdin.com/project/bitwarden-web" target="_blank">
<img src="https://d322cqt584bo4o.cloudfront.net/bitwarden-web/localized.svg" alt="Crowdin" />
</a>
<a href="https://hub.docker.com/u/bitwarden/" target="_blank">
<img src="https://img.shields.io/docker/pulls/bitwarden/web.svg" alt="DockerHub" />
</a>
<a href="https://gitter.im/bitwarden/Lobby" target="_blank">
<img src="https://badges.gitter.im/bitwarden/Lobby.svg" alt="gitter chat" />
</a>
</p>
# bitwarden Web
## Build/Run
The bitwarden Web project is an AngularJS application that powers the web vault (https://vault.bitwarden.com/).
### Requirements
<img src="https://i.imgur.com/rxrykeX.png" alt="" width="791" height="739" />
- [Node.js](https://nodejs.org) v8.11 or greater
# Build/Run
### Run the app
**Requirements**
```
npm install
npm run build:watch
```
- Node.js
- Gulp
You can now access the web vault in your browser at `https://localhost:8080`. You can adjust your API endpoint settings in `src/app/services/services.module.ts` by altering the `apiService.setUrls` call. For example:
By default the application points to the production API. If you want to change that to point to a local instance of
the [Core](https://github.com/bitwarden/core) API, you can modify the `package.json` `env` property to `Development`
and then set your local endpoints in `settings.json`.
```typescript
await apiService.setUrls({
base: isDev ? null : window.location.origin,
api: isDev ? 'http://mylocalapi' : null,
identity: isDev ? 'http://mylocalidentity' : null,
});
```
Then run the following commands:
If you want to point the development web vault to the production APIs, you can set:
- `npm install`
- `gulp build`
- `gulp serve`
```typescript
await apiService.setUrls({
base: null,
api: 'https://api.bitwarden.com',
identity: 'https://identity.bitwarden.com',
});
```
You can now access the web vault at `http://localhost:4001`.
# Contribute
## Contribute
Code contributions are welcome! Please commit any pull requests against the `master` branch.

View File

@@ -1,4 +1,4 @@
bitwarden believes that working with security researchers across the globe is crucial to keeping our
Bitwarden believes that working with security researchers across the globe is crucial to keeping our
users safe. If you believe you've found a security issue in our product or service, we encourage you to
notify us. We welcome working with you to resolve the issue promptly. Thanks in advance!
@@ -16,7 +16,7 @@ notify us. We welcome working with you to resolve the issue promptly. Thanks in
# In-scope
- Security issues in any current release of bitwarden. This includes the web vault, browser extension,
- Security issues in any current release of Bitwarden. This includes the web vault, browser extension,
and mobile apps (iOS and Android). Product downloads are available at https://bitwarden.com. Source
code is available at https://github.com/bitwarden.
@@ -24,14 +24,14 @@ notify us. We welcome working with you to resolve the issue promptly. Thanks in
The following bug classes are out-of scope:
- Bugs that are already reported on any of bitwarden's issue trackers (https://github.com/bitwarden),
- Bugs that are already reported on any of Bitwarden's issue trackers (https://github.com/bitwarden),
or that we already know of. Note that some of our issue tracking is private.
- Issues in an upstream software dependency (ex: Xamarin, ASP.NET) which are already reported to the
upstream maintainer.
- Attacks requiring physical access to a user's device.
- Self-XSS
- Issues related to software or protocols not under bitwarden's control
- Vulnerabilities in outdated versions of bitwarden
- Issues related to software or protocols not under Bitwarden's control
- Vulnerabilities in outdated versions of Bitwarden
- Missing security best practices that do not directly lead to a vulnerability
- Issues that do not have any impact on the general public
@@ -39,7 +39,7 @@ While researching, we'd like to ask you to refrain from:
- Denial of service
- Spamming
- Social engineering (including phishing) of bitwarden staff or contractors
- Any physical attempts against bitwarden property or data centers
- Social engineering (including phishing) of Bitwarden staff or contractors
- Any physical attempts against Bitwarden property or data centers
Thank you for helping keep bitwarden and our users safe!
Thank you for helping keep Bitwarden and our users safe!

83
appveyor.yml Normal file
View File

@@ -0,0 +1,83 @@
image:
- Visual Studio 2017
- Ubuntu1804
branches:
except:
- l10n_master
- gh-pages
services:
- docker
stack: node 10
init:
- ps: |
if($isWindows) {
Install-Product node 10
}
install:
- ps: |
$env:PACKAGE_VERSION = (Get-Content -Raw -Path .\package.json | ConvertFrom-Json).version
$env:PUSH_DOCKER = "false"
$env:PROD_DEPLOY = "false"
$env:TAG_NAME = ""
if($env:APPVEYOR_REPO_TAG -eq "true" -and $env:APPVEYOR_RE_BUILD -eq "True") {
$env:PROD_DEPLOY = "true"
$env:TAG_NAME = $env:APPVEYOR_REPO_TAG_NAME.TrimStart("v")
echo "This is a production deployment for ${env:TAG_NAME}."
}
if("${env:DOCKER_USERNAME}" -ne "" -and "${env:DOCKER_PASSWORD}" -ne "") {
$env:PUSH_DOCKER = "true"
}
if($isWindows) {
choco install cloc --no-progress
cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
}
before_build:
- node --version
- npm --version
- sh: |
if [ "${PUSH_DOCKER}" == "true" ]
then
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
fi
- cmd: set "GIT_PATH=C:\Program Files\Git\mingw64\libexec\git-core"
- cmd: set "PATH=%GIT_PATH%;%PATH%"
build_script:
- sh: chmod +x ./build.sh
- ps: |
if($isLinux) {
./build.sh
./build.sh tag dev
if($env:PROD_DEPLOY -eq "true") {
./build.sh tag beta
./build.sh tag $env:TAG_NAME
}
docker images
if($env:PUSH_DOCKER -eq "true") {
./build.sh push dev
if($env:PROD_DEPLOY -eq "true") {
./build.sh push beta
./build.sh push latest
./build.sh push $env:TAG_NAME
}
}
}
- cmd: npm install
- cmd: npm run build:prod
after_build:
- sh: |
if [ "${PUSH_DOCKER}" == "true" ]
then
docker logout
fi

View File

@@ -1,39 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.9
MinimumVisualStudioVersion = 10.0.40219.1
Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "bitwarden-web", ".", "{25BEDEF4-2CAF-445A-807D-63C17FF85694}"
ProjectSection(WebsiteProperties) = preProject
TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.6.1"
Debug.AspNetCompiler.VirtualPath = "/localhost_15509"
Debug.AspNetCompiler.PhysicalPath = "."
Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_15509\"
Debug.AspNetCompiler.Updateable = "true"
Debug.AspNetCompiler.ForceOverwrite = "true"
Debug.AspNetCompiler.FixedNames = "false"
Debug.AspNetCompiler.Debug = "True"
Release.AspNetCompiler.VirtualPath = "/localhost_15509"
Release.AspNetCompiler.PhysicalPath = "."
Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_15509\"
Release.AspNetCompiler.Updateable = "true"
Release.AspNetCompiler.ForceOverwrite = "true"
Release.AspNetCompiler.FixedNames = "false"
Release.AspNetCompiler.Debug = "False"
VWDPort = "15509"
SlnRelativePath = "."
DefaultWebSiteLanguage = "Visual C#"
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{25BEDEF4-2CAF-445A-807D-63C17FF85694}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25BEDEF4-2CAF-445A-807D-63C17FF85694}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,13 +0,0 @@
$dir = Split-Path -Parent $MyInvocation.MyCommand.Path
echo "`n# Building Web"
echo "`nBuilding app"
echo "npm version $(npm --version)"
echo "gulp version $(gulp --version)"
npm install
gulp dist:selfHosted
echo "`nBuilding docker image"
docker --version
docker build -t bitwarden/web $dir\.

View File

@@ -22,9 +22,9 @@ else
echo ""
echo "Building app"
echo "npm version $(npm --version)"
echo "gulp version $(gulp --version)"
npm install
gulp dist:selfHosted
npm run sub:update
npm run dist:selfhost
echo ""
echo "Building docker image"

11
crowdin.yml Normal file
View File

@@ -0,0 +1,11 @@
files:
- source: /src/locales/en/messages.json
translation: /src/locales/%two_letters_code%/%original_file_name%
update_option: update_as_unapproved
languages_mapping:
two_letters_code:
pt-PT: pt_PT
pt-BR: pt_BR
zh-CN: zh_CN
zh-TW: zh_TW
en-GB: en_GB

45
dev-server.shared.pem Normal file
View File

@@ -0,0 +1,45 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDaEy1cPw07irjg
4wUgaxshW7oQrgVoNZYRROmdU20K22L+HyG2ahW6usiWw8+6fPgVve7Y1z+/GYsK
DhaDdY1Ket3JvZHxoAJ/+6lYY+05PhtmYnyEZzZlnuYx/tu3vyGpsXqMpzL3ZrX2
Mh2dWE7ZXKxsyig4wSDJhBPMrW8HKXLrLR/JPFhu/nz5MpRF5LfzWU13FEfmS43s
PEkBCn5ZxhVX4eNclQhTl7oOo5LU+KCWn+C/GPQir7pdmMoYF6D5j3qtbsq9irPe
qR7HsM9z6DnX+L0mF31P2S6OTgLT3kuWJn9vqLUwvQWGFvSSzpw7JgGBK3eX6zE9
2koGWP9NAgMBAAECggEAIpwCie5TykxU1RQSfzegYaXuHLGRmB1RCMKYFOjlmGCD
EHOeZRXnBvCX3x2KfT1SHhk7q9xVeJ20LE9aEVj5qIVhZ6AXZnKPkwI8uRN61afe
r1wYCOdcgbo7LFoXQs0pqYXKPkJW217IqB8CBjO6p9KGZumago9cBb9ZaRVpVohZ
c6YHeatrna2mPb/EUPHdT0RHHQ5Dz2ToPjCkDtxsNHLZLekR35WIMtCBlp0xY5hb
5h54ZxnaMihvHTLa8L/pgxGEUsP+XFpdXkM1oREzh8tDRFcUL8mUVZq8bGyzALn5
MxDhdXqxrnyD2cQ/cSqXLs1/2mh5eccU3g5IaNtrAQKBgQD0Q4K2UYXa8jWQu7jI
b37zwr2EypLFjeluqF4fxs+oz3UYEXeBDK0Td19/tze6/XieKibKDtFrOZQwDDKC
AVxD7Dm58T9Jf4LDHNYOfYL3X/E4H+JrVBh94s0B00jVJ6TnEQDMuLi+wMGtvTdW
huxoNefIWKf73ozvxIF+nsyeDQKBgQDkjYoXkBtfNgQR42RVA0/UdLLDWWctMU4F
sJYc1bLL3txbf+fK7QzbU/ggLMW0hv8/IdyirGJhW3G0K0yhpAOlPhe36qv4QyhD
o2nFlRrzfzvGJAgH9b1s+VcL/cSIuv4aCkbv97DAoQGPzAWEKv5gY1iw1DsGgrz5
svZUvd7WQQKBgQDPrp7yuTngQNP+bT3dXb9JLqjIwRwt0E1LgugUiIuDcnCSuDct
iEOYK4UNKBDAckcd46T7Y8H3MwumFpjTJKj4L1+dk1tF+J6Lmnb99wVlozOLjsCK
lQQF9NJt3OEuKvjwZeqSJfUeavHB8QGeFjXnHP4nwAmEA2M9cYzQxeAf+QKBgCbS
U+6Er+GQT0iqk1RNZ7XyzJqaCQiII3Sb9iOXuPMgO9Xe+ARkF5b5wF/Wuw5bD+gt
XEjVdzCKU9oCsNWUAnqC/Yxj9CoLXj9+9mx1U0qhBgo1/Jc9ipuEDuEejc+b06Wg
sUP5krBlqNpAEX/Nvb+poFsI8a29b1QKrgTe64cBAoGALg92rZBG60N2n8fTokou
f1fui8Ftb+vOVGv9CM6icmNuwXeMF40A33Hvx14XLFk6B5p5dtVyOR660rRv4HRV
cBUm5wwCZjwR5Aj83XGR0PRbTNFNngHbawQiutSo6dw8cNNKCZMywVh2KX29dsLh
0Yj++kb8+G1kzFonR8WWoC8=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICwzCCAaugAwIBAgIJAN5sbMfEx05qMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
BAMTCWxvY2FsaG9zdDAeFw0xODA2MDUwMzMxNDhaFw0yODA2MDIwMzMxNDhaMBQx
EjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBANoTLVw/DTuKuODjBSBrGyFbuhCuBWg1lhFE6Z1TbQrbYv4fIbZqFbq6yJbD
z7p8+BW97tjXP78ZiwoOFoN1jUp63cm9kfGgAn/7qVhj7Tk+G2ZifIRnNmWe5jH+
27e/IamxeoynMvdmtfYyHZ1YTtlcrGzKKDjBIMmEE8ytbwcpcustH8k8WG7+fPky
lEXkt/NZTXcUR+ZLjew8SQEKflnGFVfh41yVCFOXug6jktT4oJaf4L8Y9CKvul2Y
yhgXoPmPeq1uyr2Ks96pHsewz3PoOdf4vSYXfU/ZLo5OAtPeS5Ymf2+otTC9BYYW
9JLOnDsmAYErd5frMT3aSgZY/00CAwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxo
b3N0MA0GCSqGSIb3DQEBCwUAA4IBAQCBTn7szrcs+fSs1Q/a2O3ng35zcme6NRhp
T65RP0ooj3tPT9QlTJyKjo9Yb2RW2RGVbQO86mkYe9N9wcZkzurZ6KDqsfBn3FkI
eZA1G/za907Dt/25mOdrsav7NmFBwxo9iuZ/cozgneK1mAXOu4nDI5yYvAlvNA6E
iXgls4WX1LtHL5b9YV7Jz27d5tTmGxEimakMBo+zr10vCtMCsTlDs/ChamnI7ljN
7B4WIVUMI3xOZzqClLnSzFJNReAlapjtGtp1qH6Y+6aZ9OErIwZOjE9CYYvm6MbE
CblXQ9Uifpwrc09TA5S2Y/9+VxUBF9xlxh8hkcGLTzlNFDzVWdmR
-----END CERTIFICATE-----

1
dist/.publish vendored

Submodule dist/.publish deleted from 9d2a53eca0

View File

@@ -1,5 +1,38 @@
#!/bin/sh
#!/bin/bash
cp /etc/bitwarden/web/settings.js /app/js/settings.js
# Setup
GROUPNAME="bitwarden"
USERNAME="bitwarden"
LUID=${LOCAL_UID:-0}
LGID=${LOCAL_GID:-0}
# Step down from host root to well-known nobody/nogroup user
if [ $LUID -eq 0 ]
then
LUID=65534
fi
if [ $LGID -eq 0 ]
then
LGID=65534
fi
# Create user and group
groupadd -o -g $LGID $GROUPNAME >/dev/null 2>&1 ||
groupmod -o -g $LGID $GROUPNAME >/dev/null 2>&1
useradd -o -u $LUID -g $GROUPNAME -s /bin/false $USERNAME >/dev/null 2>&1 ||
usermod -o -u $LUID -g $GROUPNAME -s /bin/false $USERNAME >/dev/null 2>&1
mkhomedir_helper $USERNAME
# The rest...
chown -R $USERNAME:$GROUPNAME /etc/bitwarden
cp /etc/bitwarden/web/app-id.json /app/app-id.json
dotnet /bitwarden_server/Server.dll /contentRoot=/app /webRoot=. /serveUnknown=false
chown -R $USERNAME:$GROUPNAME /app
chown -R $USERNAME:$GROUPNAME /bitwarden_server
exec gosu $USERNAME:$GROUPNAME dotnet /bitwarden_server/Server.dll \
/contentRoot=/app /webRoot=. /serveUnknown=false /webVault=true

View File

@@ -1,486 +1,37 @@
/// <binding BeforeBuild='build, dist' Clean='clean' ProjectOpened='build. dist' />
const gulp = require('gulp');
const googleWebFonts = require('gulp-google-webfonts');
const del = require('del');
const package = require('./package.json');
const fs = require('fs');
var gulp = require('gulp'),
rimraf = require('rimraf'),
concat = require('gulp-concat'),
rename = require('gulp-rename'),
cssmin = require('gulp-cssmin'),
uglify = require('gulp-uglify'),
ghPages = require('gulp-gh-pages'),
less = require('gulp-less'),
connect = require('gulp-connect'),
ngAnnotate = require('gulp-ng-annotate'),
preprocess = require('gulp-preprocess'),
runSequence = require('run-sequence'),
merge = require('merge-stream'),
ngConfig = require('gulp-ng-config'),
settings = require('./settings.json'),
project = require('./package.json'),
jshint = require('gulp-jshint'),
_ = require('lodash'),
webpack = require('webpack-stream'),
browserify = require('browserify'),
derequire = require('gulp-derequire'),
source = require('vinyl-source-stream');
const paths = {
node_modules: './node_modules/',
src: './src/',
build: './build/',
cssDir: './src/css/',
};
var paths = {};
paths.dist = './dist/';
paths.webroot = './src/';
paths.js = paths.webroot + 'js/**/*.js';
paths.minJs = paths.webroot + 'js/**/*.min.js';
paths.concatJsDest = paths.webroot + 'js/bw.min.js';
paths.libDir = paths.webroot + 'lib/';
paths.npmDir = 'node_modules/';
paths.lessDir = paths.webroot + 'less/';
paths.cssDir = paths.webroot + 'css/';
paths.jsDir = paths.webroot + 'js/';
var randomString = Math.random().toString(36).substring(7);
gulp.task('lint', function () {
return gulp.src(paths.webroot + 'app/**/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
gulp.task('build', function (cb) {
return runSequence(
'clean',
['browserify', 'lib', 'webpack', 'less', 'settings', 'lint', 'min:js'],
cb);
});
gulp.task('clean:js', function (cb) {
return rimraf(paths.concatJsDest, cb);
});
gulp.task('clean:css', function (cb) {
return rimraf(paths.cssDir, cb);
});
gulp.task('clean:lib', function (cb) {
return rimraf(paths.libDir, cb);
});
gulp.task('clean', ['clean:js', 'clean:css', 'clean:lib', 'dist:clean']);
gulp.task('min:js', ['clean:js'], function () {
return gulp.src(
[
paths.js,
'!' + paths.minJs,
'!' + paths.jsDir + 'fallback*.js',
'!' + paths.jsDir + 'u2f-connector.js',
'!' + paths.jsDir + 'duo.js',
'!' + paths.jsDir + 'settings.js'
], { base: '.' })
.pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } }))
.pipe(concat(paths.concatJsDest))
.pipe(uglify())
.pipe(gulp.dest('.'));
});
gulp.task('min:css', [], function () {
return gulp.src([paths.cssDir + '**/*.css', '!' + paths.cssDir + '**/*.min.css'], { base: '.' })
.pipe(cssmin())
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest('.'));
});
gulp.task('min', ['min:js', 'min:css']);
gulp.task('lib', ['clean:lib'], function () {
var libs = [
{
src: [
paths.npmDir + 'bootstrap/dist/**/*',
'!' + paths.npmDir + 'bootstrap/dist/**/npm.js',
'!' + paths.npmDir + 'bootstrap/dist/**/css/*theme*'
],
dest: paths.libDir + 'bootstrap'
},
{
src: paths.npmDir + 'font-awesome/css/*',
dest: paths.libDir + 'font-awesome/css'
},
{
src: paths.npmDir + 'font-awesome/fonts/*',
dest: paths.libDir + 'font-awesome/fonts'
},
{
src: paths.npmDir + 'jquery/dist/*.js',
dest: paths.libDir + 'jquery'
},
{
src: paths.npmDir + 'admin-lte/dist/js/app*.js',
dest: paths.libDir + 'admin-lte/js'
},
{
src: paths.npmDir + 'angular/angular*.js',
dest: paths.libDir + 'angular'
},
{
src: paths.npmDir + 'angular-ui-bootstrap/dist/*tpls*.js',
dest: paths.libDir + 'angular-ui-bootstrap'
},
{
src: paths.npmDir + 'angular-bootstrap-show-errors/src/*.js',
dest: paths.libDir + 'angular-bootstrap-show-errors'
},
{
src: paths.npmDir + 'angular-cookies/*cookies*.js',
dest: paths.libDir + 'angular-cookies'
},
{
src: paths.npmDir + 'angular-jwt/dist/*.js',
dest: paths.libDir + 'angular-jwt'
},
{
src: paths.npmDir + 'angular-resource/*resource*.js',
dest: paths.libDir + 'angular-resource'
},
{
src: paths.npmDir + 'angular-sanitize/*sanitize*.js',
dest: paths.libDir + 'angular-sanitize'
},
{
src: [paths.npmDir + 'angular-toastr/dist/**/*.css', paths.npmDir + 'angular-toastr/dist/**/*.js'],
dest: paths.libDir + 'angular-toastr'
},
{
src: paths.npmDir + 'angular-ui-router/release/*.js',
dest: paths.libDir + 'angular-ui-router'
},
{
src: paths.npmDir + 'angular-messages/*messages*.js',
dest: paths.libDir + 'angular-messages'
},
{
src: paths.npmDir + 'ngstorage/*.js',
dest: paths.libDir + 'ngstorage'
},
{
src: paths.npmDir + 'papaparse/papaparse*.js',
dest: paths.libDir + 'papaparse'
},
{
src: paths.npmDir + 'ngclipboard/dist/ngclipboard*.js',
dest: paths.libDir + 'ngclipboard'
},
{
src: paths.npmDir + 'clipboard/dist/clipboard*.js',
dest: paths.libDir + 'clipboard'
},
{
src: paths.npmDir + 'node-forge/dist/prime.worker.*',
dest: paths.libDir + 'forge'
},
{
src: [
paths.npmDir + 'angulartics-google-analytics/lib/angulartics*.js',
paths.npmDir + 'angulartics/src/angulartics.js'
],
dest: paths.libDir + 'angulartics'
},
//{
// src: paths.npmDir + 'duo_web_sdk/index.js',
// dest: paths.libDir + 'duo'
//},
{
src: paths.jsDir + 'duo.js',
dest: paths.libDir + 'duo'
},
{
src: paths.npmDir + 'angular-promise-polyfill/index.js',
dest: paths.libDir + 'angular-promise-polyfill'
}
];
var tasks = libs.map(function (lib) {
return gulp.src(lib.src).pipe(gulp.dest(lib.dest));
});
return merge(tasks);
});
gulp.task('webpack', ['webpack:forge']);
gulp.task('webpack:forge', function () {
var forgeDir = paths.npmDir + '/node-forge/lib/';
return gulp.src([
forgeDir + 'pbkdf2.js',
forgeDir + 'aes.js',
forgeDir + 'rsa.js',
forgeDir + 'hmac.js',
forgeDir + 'sha256.js',
forgeDir + 'random.js',
forgeDir + 'forge.js'
]).pipe(webpack({
output: {
filename: 'forge.js',
library: 'forge',
libraryTarget: 'umd'
},
node: {
Buffer: false,
process: false,
crypto: false,
setImmediate: false
}
})).pipe(gulp.dest(paths.libDir + 'forge'));
});
gulp.task('settings', function () {
return config()
.pipe(gulp.dest(paths.webroot + 'app'));
});
function config() {
return gulp.src('./settings.json')
.pipe(ngConfig('bit', {
createModule: false,
constants: _.merge({}, {
appSettings: {
selfHosted: false,
version: project.version,
environment: project.env
}
}, require('./settings' + (project.env !== 'Development' ? ('.' + project.env) : '') + '.json') || {})
}));
function clean() {
return del([paths.cssDir]);
}
gulp.task('less', function () {
return gulp.src(paths.lessDir + 'vault.less')
.pipe(less())
function webfonts() {
return gulp.src('./webfonts.list')
.pipe(googleWebFonts({
fontsDir: 'webfonts',
cssFilename: 'webfonts.css',
format: 'woff',
}))
.pipe(gulp.dest(paths.cssDir));
});
};
gulp.task('watch', function () {
gulp.watch(paths.lessDir + '*.less', ['less']);
gulp.watch('./settings*.json', ['settings']);
});
gulp.task('browserify', ['browserify:stripe', 'browserify:cc']);
gulp.task('browserify:stripe', function () {
return browserify(paths.npmDir + 'angular-stripe/src/index.js',
{
entry: '.',
standalone: 'angularStripe',
global: true
})
.transform('exposify', { expose: { angular: 'angular' } })
.bundle()
.pipe(source('angular-stripe.js'))
.pipe(derequire())
.pipe(gulp.dest(paths.libDir + 'angular-stripe'));
});
gulp.task('browserify:cc', function () {
return browserify(paths.npmDir + 'angular-credit-cards/src/index.js',
{
entry: '.',
standalone: 'angularCreditCards'
})
.transform('exposify', { expose: { angular: 'angular' } })
.bundle()
.pipe(source('angular-credit-cards.js'))
.pipe(derequire())
.pipe(gulp.dest(paths.libDir + 'angular-credit-cards'));
});
gulp.task('dist:clean', function (cb) {
return rimraf(paths.dist + '**/*', cb);
});
gulp.task('dist:move', function () {
var moves = [
{
src: './CNAME',
dest: paths.dist
},
{
src: [
paths.npmDir + 'bootstrap/dist/**/bootstrap.min.js',
paths.npmDir + 'bootstrap/dist/**/bootstrap.min.css',
paths.npmDir + 'bootstrap/dist/**/fonts/**/*'
],
dest: paths.dist + 'lib/bootstrap'
},
{
src: [
paths.npmDir + 'font-awesome/**/font-awesome.min.css',
paths.npmDir + 'font-awesome/**/fonts/**/*'
],
dest: paths.dist + 'lib/font-awesome'
},
{
src: paths.npmDir + 'jquery/dist/jquery.min.js',
dest: paths.dist + 'lib/jquery'
},
{
src: paths.npmDir + 'angular/angular.min.js',
dest: paths.dist + 'lib/angular'
},
{
src: paths.npmDir + 'node-forge/dist/prime.worker.*',
dest: paths.dist + 'lib/forge'
},
//{
// src: paths.npmDir + 'duo_web_sdk/index.js',
// dest: paths.dist + 'lib/duo'
//},
{
src: paths.jsDir + 'duo.js',
dest: paths.dist + 'js'
},
{
src: paths.jsDir + 'settings.js',
dest: paths.dist + 'js'
},
{
src: paths.jsDir + 'bw.min.js',
dest: paths.dist + 'js'
},
{
src: [
paths.webroot + '**/app/**/*.html',
paths.webroot + '**/images/**/*',
paths.webroot + 'index.html',
paths.webroot + 'u2f-connector.html',
paths.webroot + 'duo-connector.html',
paths.webroot + 'favicon.ico',
paths.webroot + 'app-id.json'
],
dest: paths.dist
function version(cb) {
fs.writeFileSync(paths.build + 'version.json', '{"version":"' + package.version + '"}');
cb();
}
];
var tasks = moves.map(function (move) {
return gulp.src(move.src).pipe(gulp.dest(move.dest));
});
return merge(tasks);
});
gulp.task('dist:css', function () {
return gulp
.src([
paths.cssDir + '**/*.css',
'!' + paths.cssDir + '**/*.min.css'
])
.pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } }))
.pipe(cssmin())
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest(paths.dist + 'css'));
});
gulp.task('dist:js:app', function () {
var mainStream = gulp
.src([
paths.webroot + 'app/app.js',
'!' + paths.webroot + 'app/settings.js',
paths.webroot + 'app/**/*Module.js',
paths.webroot + 'app/**/*.js'
]);
merge(mainStream, config())
.pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } }))
.pipe(concat(paths.dist + '/js/app.min.js'))
.pipe(ngAnnotate())
.pipe(uglify())
.pipe(gulp.dest('.'));
});
gulp.task('dist:js:fallback', function () {
var mainStream = gulp
.src([
paths.jsDir + 'fallback*.js'
]);
merge(mainStream)
.pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } }))
.pipe(uglify())
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest(paths.dist + 'js'));
});
gulp.task('dist:js:u2f', function () {
var mainStream = gulp
.src([
paths.jsDir + 'u2f*.js'
]);
merge(mainStream)
.pipe(concat(paths.dist + '/js/u2f.min.js'))
.pipe(uglify())
.pipe(gulp.dest('.'));
});
gulp.task('dist:js:lib', function () {
return gulp
.src([
paths.libDir + 'angulartics/angulartics.js',
paths.libDir + '**/*.js',
'!' + paths.libDir + '**/*.min.js',
'!' + paths.libDir + 'angular/**/*',
'!' + paths.libDir + 'bootstrap/**/*',
'!' + paths.libDir + 'jquery/**/*'
])
.pipe(concat(paths.dist + '/js/lib.min.js'))
.pipe(uglify())
.pipe(gulp.dest('.'));
});
gulp.task('dist:preprocess', function () {
return gulp
.src([
paths.dist + '/**/*.html'
], { base: '.' })
.pipe(preprocess({ context: { cacheTag: randomString, selfHosted: selfHosted } }))
.pipe(gulp.dest('.'));
});
gulp.task('dist', ['build'], function (cb) {
return runSequence(
'dist:clean',
['dist:move', 'dist:css', 'dist:js:app', 'dist:js:lib', 'dist:js:fallback', 'dist:js:u2f'],
'dist:preprocess',
cb);
});
var selfHosted = false;
gulp.task('dist:selfHosted', function (cb) {
selfHosted = true;
return runSequence('dist', cb);
});
gulp.task('deploy', ['dist'], function () {
return gulp.src(paths.dist + '**/*')
.pipe(ghPages({ cacheDir: paths.dist + '.publish' }));
});
gulp.task('deploy-preview', ['dist'], function () {
return gulp.src(paths.dist + '**/*')
.pipe(ghPages({
cacheDir: paths.dist + '.publish',
remoteUrl: 'git@github.com:kspearrin/bitwarden-web-preview.git'
}));
});
gulp.task('serve', function () {
connect.server({
port: 4001,
root: ['src'],
//https: true,
middleware: function (connect, opt) {
return [function (req, res, next) {
if (req.originalUrl.indexOf('app-id.json') > -1) {
res.setHeader('Content-Type', 'application/fido.trusted-apps+json');
}
next();
}];
}
});
});
exports.clean = clean;
exports.webfonts = gulp.series(clean, webfonts);
exports.prebuild = gulp.series(clean, webfonts);
exports.version = version;
exports.postdist = version;

1
jslib Submodule

Submodule jslib added at 0a30c7eb1e

14902
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +1,99 @@
{
"name": "bitwarden",
"version": "1.20.0",
"env": "Production",
"name": "bitwarden-web",
"version": "2.13.1",
"scripts": {
"sub:init": "git submodule update --init --recursive",
"sub:update": "git submodule update --remote",
"sub:pull": "git submodule foreach git pull origin master",
"postinstall": "npm run sub:init",
"symlink:win": "rm -rf ./jslib && cmd /c mklink /J .\\jslib ..\\jslib",
"symlink:mac": "npm run symlink:lin",
"symlink:lin": "rm -rf ./jslib && ln -s ../jslib ./jslib",
"build": "gulp prebuild && webpack",
"build:watch": "gulp prebuild && webpack-dev-server",
"build:prod": "gulp prebuild && cross-env NODE_ENV=production webpack",
"build:prod:watch": "gulp prebuild && cross-env NODE_ENV=production webpack-dev-server",
"build:selfhost": "gulp prebuild && cross-env SELF_HOST=true webpack-dev-server",
"build:selfhost:watch": "gulp prebuild && cross-env SELF_HOST=true webpack-dev-server",
"build:selfhost:prod": "gulp prebuild && cross-env SELF_HOST=true NODE_ENV=production webpack",
"build:selfhost:prod:watch": "gulp prebuild && cross-env SELF_HOST=true NODE_ENV=production webpack-dev-server",
"clean:l10n": "git push origin --delete l10n_master",
"dist": "npm run build:prod && gulp postdist",
"dist:selfhost": "npm run build:selfhost:prod && gulp postdist",
"deploy": "npm run dist && gh-pages -d build",
"deploy:dev": "npm run dist && gh-pages -d build -r git@github.com:kspearrin/bitwarden-web-dev.git",
"lint": "tslint src/**/*.ts || true",
"lint:fix": "tslint src/**/*.ts --fix"
},
"devDependencies": {
"connect": "3.6.3",
"lodash": "4.17.4",
"gulp": "3.9.1",
"gulp-concat": "2.6.1",
"gulp-cssmin": "0.2.0",
"gulp-less": "3.3.2",
"gulp-rename": "1.2.2",
"gulp-uglify": "3.0.0",
"gulp-gh-pages": "0.5.4",
"gulp-preprocess": "2.0.0",
"gulp-ng-annotate": "2.0.0",
"gulp-ng-config": "1.4.0",
"gulp-connect": "5.0.0",
"jshint": "2.9.5",
"gulp-jshint": "2.0.4",
"rimraf": "2.6.1",
"run-sequence": "2.1.0",
"merge-stream": "1.0.1",
"jquery": "2.2.4",
"font-awesome": "4.7.0",
"bootstrap": "3.3.7",
"angular": "1.6.6",
"angular-resource": "1.6.6",
"angular-sanitize": "1.6.6",
"angular-ui-bootstrap": "2.5.0",
"angular-ui-router": "0.4.2",
"angular-jwt": "0.1.9",
"angular-cookies": "1.6.6",
"admin-lte": "2.3.11",
"angular-toastr": "2.1.1",
"angular-bootstrap-show-errors": "2.3.0",
"angular-messages": "1.6.6",
"ngstorage": "0.3.11",
"papaparse": "4.3.5",
"clipboard": "1.7.1",
"ngclipboard": "1.1.1",
"angulartics": "1.4.0",
"angulartics-google-analytics": "0.4.0",
"node-forge": "0.7.1",
"webpack-stream": "4.0.0",
"angular-stripe": "5.0.0",
"angular-credit-cards": "3.1.6",
"browserify": "14.4.0",
"vinyl-source-stream": "1.1.0",
"gulp-derequire": "2.1.0",
"exposify": "0.5.0",
"@angular/compiler-cli": "^7.2.11",
"@ngtools/webpack": "^7.2.2",
"@types/jquery": "^3.3.6",
"@types/lunr": "^2.1.6",
"@types/node-forge": "^0.7.5",
"@types/papaparse": "^4.5.3",
"@types/webcrypto": "^0.0.28",
"@types/webpack": "^4.4.11",
"@types/zxcvbn": "^4.4.0",
"angular2-template-loader": "^0.6.2",
"clean-webpack-plugin": "^0.1.19",
"copy-webpack-plugin": "^4.5.2",
"cross-env": "^5.2.0",
"css-loader": "^1.0.0",
"del": "^3.0.0",
"extract-text-webpack-plugin": "next",
"file-loader": "^2.0.0",
"gh-pages": "^1.2.0",
"gulp": "^4.0.0",
"gulp-google-webfonts": "^2.0.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.1",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.0",
"terser-webpack-plugin": "^1.2.3",
"ts-loader": "^5.3.3",
"tslint": "^5.12.1",
"tslint-loader": "^3.5.4",
"typescript": "3.2.4",
"webpack": "^4.29.0",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14"
},
"dependencies": {
"@angular/animations": "7.2.1",
"@angular/cdk": "7.2.1",
"@angular/common": "7.2.1",
"@angular/compiler": "7.2.1",
"@angular/core": "7.2.1",
"@angular/forms": "7.2.1",
"@angular/platform-browser": "7.2.1",
"@angular/platform-browser-dynamic": "7.2.1",
"@angular/router": "7.2.1",
"@angular/upgrade": "7.2.1",
"@microsoft/signalr": "3.1.0",
"@microsoft/signalr-protocol-msgpack": "3.1.0",
"angular2-toaster": "6.1.0",
"angulartics2": "6.3.0",
"big-integer": "1.6.36",
"bootstrap": "4.3.1",
"braintree-web-drop-in": "1.13.0",
"core-js": "2.6.2",
"duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git",
"angular-promise-polyfill": "0.0.4"
"font-awesome": "4.7.0",
"jquery": "3.4.1",
"lunr": "2.3.3",
"ngx-infinite-scroll": "7.0.1",
"node-forge": "0.7.6",
"papaparse": "4.6.0",
"popper.js": "1.14.4",
"qrious": "4.0.2",
"rxjs": "6.3.3",
"sweetalert2": "9.8.1",
"web-animations-js": "2.3.1",
"webcrypto-shim": "0.1.4",
"whatwg-fetch": "3.0.0",
"zone.js": "0.8.28",
"zxcvbn": "4.4.2"
}
}

View File

@@ -1,12 +0,0 @@
{
"appSettings": {
"apiUri": "https://preview-api.bitwarden.com",
"identityUri": "https://preview-identity.bitwarden.com",
"iconsUri": "https://icons.bitwarden.com",
"stripeKey": "pk_test_KPoCfZXu7mznb9uSCPZ2JpTD",
"braintreeKey": "sandbox_r72q8jq6_9pnxkwm75f87sdc2",
"whitelistDomains": [
"preview-api.bitwarden.com"
]
}
}

View File

@@ -1,12 +0,0 @@
{
"appSettings": {
"apiUri": "https://api.bitwarden.com",
"identityUri": "https://identity.bitwarden.com",
"iconsUri": "https://icons.bitwarden.com",
"stripeKey": "pk_live_bpN0P37nMxrMQkcaHXtAybJk",
"braintreeKey": "production_qfbsv8kc_njj2zjtyngtjmbjd",
"whitelistDomains": [
"api.bitwarden.com"
]
}
}

View File

@@ -1,12 +0,0 @@
{
"appSettings": {
"apiUri": "http://localhost:4000",
"identityUri": "http://localhost:33656",
"iconsUri": "https://icons.bitwarden.com",
"stripeKey": "pk_test_KPoCfZXu7mznb9uSCPZ2JpTD",
"braintreeKey": "sandbox_r72q8jq6_9pnxkwm75f87sdc2",
"whitelistDomains": [
"localhost"
]
}
}

0
src/.nojekyll Normal file
View File

View File

@@ -0,0 +1,35 @@
<div class="mt-5 d-flex justify-content-center" *ngIf="loading">
<div>
<img src="../../images/logo-dark@2x.png" class="mb-4 logo" alt="Bitwarden">
<p class="text-center">
<i class="fa fa-spinner fa-spin fa-2x text-muted" title="{{'loading' | i18n}}" aria-hidden="true"></i>
<span class="sr-only">{{'loading' | i18n}}</span>
</p>
</div>
</div>
<div class="container" *ngIf="!loading && !authed">
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<p class="lead text-center mb-4">{{'joinOrganization' | i18n}}</p>
<div class="card d-block">
<div class="card-body">
<p class="text-center">
{{orgName}}
<strong class="d-block mt-2">{{email}}</strong>
</p>
<p>{{'joinOrganizationDesc' | i18n}}</p>
<hr>
<div class="d-flex">
<a routerLink="/" [queryParams]="{email: email}" class="btn btn-primary btn-block">
{{'logIn' | i18n}}
</a>
<a routerLink="/register" [queryParams]="{email: email}"
class="btn btn-primary btn-block ml-2 mt-0">
{{'createAccount' | i18n}}
</a>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,95 @@
import {
Component,
OnInit,
} from '@angular/core';
import {
ActivatedRoute,
Router,
} from '@angular/router';
import {
Toast,
ToasterService,
} from 'angular2-toaster';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { StateService } from 'jslib/abstractions/state.service';
import { UserService } from 'jslib/abstractions/user.service';
import { OrganizationUserAcceptRequest } from 'jslib/models/request/organizationUserAcceptRequest';
@Component({
selector: 'app-accept-organization',
templateUrl: 'accept-organization.component.html',
})
export class AcceptOrganizationComponent implements OnInit {
loading = true;
authed = false;
orgName: string;
email: string;
actionPromise: Promise<any>;
constructor(private router: Router, private toasterService: ToasterService,
private i18nService: I18nService, private route: ActivatedRoute,
private apiService: ApiService, private userService: UserService,
private stateService: StateService) { }
ngOnInit() {
let fired = false;
this.route.queryParams.subscribe(async (qParams) => {
if (fired) {
return;
}
fired = true;
await this.stateService.remove('orgInvitation');
let error = qParams.organizationId == null || qParams.organizationUserId == null || qParams.token == null;
let errorMessage: string = null;
if (!error) {
this.authed = await this.userService.isAuthenticated();
if (this.authed) {
const request = new OrganizationUserAcceptRequest();
request.token = qParams.token;
try {
this.actionPromise = this.apiService.postOrganizationUserAccept(qParams.organizationId,
qParams.organizationUserId, request);
await this.actionPromise;
const toast: Toast = {
type: 'success',
title: this.i18nService.t('inviteAccepted'),
body: this.i18nService.t('inviteAcceptedDesc'),
timeout: 10000,
};
this.toasterService.popAsync(toast);
this.router.navigate(['/vault']);
} catch (e) {
error = true;
errorMessage = e.message;
}
} else {
await this.stateService.save('orgInvitation', qParams);
this.email = qParams.email;
this.orgName = qParams.organizationName;
if (this.orgName != null) {
// Fix URL encoding of space issue with Angular
this.orgName = this.orgName.replace(/\+/g, ' ');
}
}
}
if (error) {
const toast: Toast = {
type: 'error',
title: null,
body: errorMessage != null ? this.i18nService.t('inviteAcceptFailedShort', errorMessage) :
this.i18nService.t('inviteAcceptFailed'),
timeout: 10000,
};
this.toasterService.popAsync(toast);
this.router.navigate(['/']);
}
this.loading = false;
});
}
}

View File

@@ -1,278 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsLoginController', function ($scope, $rootScope, $cookies, apiService, cryptoService, authService,
$state, constants, $analytics, $uibModal, $timeout, $window, $filter, toastr) {
$scope.state = $state;
$scope.twoFactorProviderConstants = constants.twoFactorProvider;
$scope.rememberTwoFactor = { checked: false };
var stopU2fCheck = true;
$scope.returnState = $state.params.returnState;
$scope.stateEmail = $state.params.email;
if (!$scope.returnState && $state.params.org) {
$scope.returnState = {
name: 'backend.user.settingsCreateOrg',
params: { plan: $state.params.org }
};
}
else if (!$scope.returnState && $state.params.premium) {
$scope.returnState = {
name: 'backend.user.settingsPremium'
};
}
if ($state.current.name.indexOf('twoFactor') > -1 && (!$scope.twoFactorProviders || !$scope.twoFactorProviders.length)) {
$state.go('frontend.login.info', { returnState: $scope.returnState });
}
var rememberedEmail = $cookies.get(constants.rememberedEmailCookieName);
if (rememberedEmail || $scope.stateEmail) {
$scope.model = {
email: $scope.stateEmail || rememberedEmail,
rememberEmail: rememberedEmail !== null
};
$timeout(function () {
$("#masterPassword").focus();
});
}
else {
$timeout(function () {
$("#email").focus();
});
}
var _email,
_masterPassword;
$scope.twoFactorProviders = null;
$scope.twoFactorProvider = null;
$scope.login = function (model) {
$scope.loginPromise = authService.logIn(model.email, model.masterPassword).then(function (twoFactorProviders) {
if (model.rememberEmail) {
var cookieExpiration = new Date();
cookieExpiration.setFullYear(cookieExpiration.getFullYear() + 10);
$cookies.put(
constants.rememberedEmailCookieName,
model.email,
{ expires: cookieExpiration });
}
else {
$cookies.remove(constants.rememberedEmailCookieName);
}
if (twoFactorProviders && Object.keys(twoFactorProviders).length > 0) {
_email = model.email;
_masterPassword = model.masterPassword;
$scope.twoFactorProviders = cleanProviders(twoFactorProviders);
$scope.twoFactorProvider = getDefaultProvider($scope.twoFactorProviders);
$analytics.eventTrack('Logged In To Two-step');
$state.go('frontend.login.twoFactor', { returnState: $scope.returnState }).then(function () {
$timeout(function () {
$("#code").focus();
init();
});
});
}
else {
$analytics.eventTrack('Logged In');
loggedInGo();
}
model.masterPassword = '';
});
};
function getDefaultProvider(twoFactorProviders) {
var keys = Object.keys(twoFactorProviders);
var providerType = null;
var providerPriority = -1;
for (var i = 0; i < keys.length; i++) {
var provider = $filter('filter')(constants.twoFactorProviderInfo, { type: keys[i], active: true });
if (provider.length && provider[0].priority > providerPriority) {
if (provider[0].type === constants.twoFactorProvider.u2f && !u2f.isSupported) {
continue;
}
providerType = provider[0].type;
providerPriority = provider[0].priority;
}
}
if (providerType === null) {
return null;
}
return parseInt(providerType);
}
function cleanProviders(twoFactorProviders) {
if (canUseSecurityKey()) {
return twoFactorProviders;
}
var keys = Object.keys(twoFactorProviders);
for (var i = 0; i < keys.length; i++) {
var provider = $filter('filter')(constants.twoFactorProviderInfo, {
type: keys[i],
active: true,
requiresUsb: false
});
if (!provider.length) {
delete twoFactorProviders[keys[i]];
}
}
return twoFactorProviders;
}
// ref: https://stackoverflow.com/questions/11381673/detecting-a-mobile-browser
function canUseSecurityKey() {
var mobile = false;
(function (a) {
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) {
mobile = true;
}
})(navigator.userAgent || navigator.vendor || window.opera);
return !mobile && !navigator.userAgent.match(/iPad/i);
}
$scope.twoFactor = function (token) {
if ($scope.twoFactorProvider === constants.twoFactorProvider.email ||
$scope.twoFactorProvider === constants.twoFactorProvider.authenticator) {
token = token.replace(' ', '');
}
$scope.twoFactorPromise = authService.logIn(_email, _masterPassword, token, $scope.twoFactorProvider,
$scope.rememberTwoFactor.checked || false);
$scope.twoFactorPromise.then(function () {
$analytics.eventTrack('Logged In From Two-step');
loggedInGo();
}, function () {
if ($scope.twoFactorProvider === constants.twoFactorProvider.u2f) {
init();
}
});
};
$scope.anotherMethod = function () {
var modal = $uibModal.open({
animation: true,
templateUrl: 'app/accounts/views/accountsTwoFactorMethods.html',
controller: 'accountsTwoFactorMethodsController',
resolve: {
providers: function () { return $scope.twoFactorProviders; }
}
});
modal.result.then(function (provider) {
$scope.twoFactorProvider = provider;
$timeout(function () {
$("#code").focus();
init();
});
});
};
$scope.sendEmail = function (doToast) {
if ($scope.twoFactorProvider !== constants.twoFactorProvider.email) {
return;
}
return cryptoService.makeKeyAndHash(_email, _masterPassword).then(function (result) {
return apiService.twoFactor.sendEmailLogin({
email: _email,
masterPasswordHash: result.hash
}).$promise;
}).then(function () {
if (doToast) {
toastr.success('Verification email sent to ' + $scope.twoFactorEmail + '.');
}
}, function () {
toastr.error('Could not send verification email.');
});
};
$scope.$on('$destroy', function () {
stopU2fCheck = true;
});
function loggedInGo() {
if ($scope.returnState) {
$state.go($scope.returnState.name, $scope.returnState.params);
}
else {
$state.go('backend.user.vault');
}
}
function init() {
stopU2fCheck = true;
var params;
if ($scope.twoFactorProvider === constants.twoFactorProvider.duo) {
params = $scope.twoFactorProviders[constants.twoFactorProvider.duo];
$window.Duo.init({
host: params.Host,
sig_request: params.Signature,
submit_callback: function (theForm) {
var response = $(theForm).find('input[name="sig_response"]').val();
$scope.twoFactor(response);
}
});
}
else if ($scope.twoFactorProvider === constants.twoFactorProvider.u2f) {
stopU2fCheck = false;
params = $scope.twoFactorProviders[constants.twoFactorProvider.u2f];
var challenges = JSON.parse(params.Challenges);
initU2f(challenges);
}
else if ($scope.twoFactorProvider === constants.twoFactorProvider.email) {
params = $scope.twoFactorProviders[constants.twoFactorProvider.email];
$scope.twoFactorEmail = params.Email;
if (Object.keys($scope.twoFactorProviders).length > 1) {
$scope.sendEmail(false);
}
}
}
function initU2f(challenges) {
if (stopU2fCheck) {
return;
}
if (challenges.length < 1 || $scope.twoFactorProvider !== constants.twoFactorProvider.u2f) {
return;
}
console.log('listening for u2f key...');
$window.u2f.sign(challenges[0].appId, challenges[0].challenge, [{
version: challenges[0].version,
keyHandle: challenges[0].keyHandle
}], function (data) {
if ($scope.twoFactorProvider !== constants.twoFactorProvider.u2f) {
return;
}
if (data.errorCode) {
console.log(data.errorCode);
$timeout(function () {
initU2f(challenges);
}, data.errorCode === 5 ? 0 : 1000);
return;
}
$scope.twoFactor(JSON.stringify(data));
}, 10);
}
});

View File

@@ -1,8 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsLogoutController', function ($scope, authService, $state, $analytics) {
authService.logOut();
$analytics.eventTrack('Logged Out');
$state.go('frontend.login.info');
});

View File

@@ -1,2 +0,0 @@
angular
.module('bit.accounts', ['ui.bootstrap', 'ngCookies']);

View File

@@ -1,45 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsOrganizationAcceptController', function ($scope, $state, apiService, authService, toastr, $analytics) {
$scope.state = {
name: $state.current.name,
params: $state.params
};
if (!$state.params.organizationId || !$state.params.organizationUserId || !$state.params.token ||
!$state.params.email || !$state.params.organizationName) {
$state.go('frontend.login.info').then(function () {
toastr.error('Invalid parameters.');
});
return;
}
$scope.$on('$viewContentLoaded', function () {
if (authService.isAuthenticated()) {
$scope.accepting = true;
apiService.organizationUsers.accept(
{
orgId: $state.params.organizationId,
id: $state.params.organizationUserId
},
{
token: $state.params.token
}, function () {
$analytics.eventTrack('Accepted Invitation');
$state.go('backend.user.vault', null, { location: 'replace' }).then(function () {
toastr.success('You can access this organization once an administrator confirms your membership.' +
' We\'ll send an email when that happens.', 'Invite Accepted', { timeOut: 10000 });
});
}, function () {
$analytics.eventTrack('Failed To Accept Invitation');
$state.go('backend.user.vault', null, { location: 'replace' }).then(function () {
toastr.error('Unable to accept invitation.', 'Error');
});
});
}
else {
$scope.loading = false;
}
});
});

View File

@@ -1,13 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsPasswordHintController', function ($scope, $rootScope, apiService, $analytics) {
$scope.success = false;
$scope.submit = function (model) {
$scope.submitPromise = apiService.accounts.postPasswordHint({ email: model.email }, function () {
$analytics.eventTrack('Requested Password Hint');
$scope.success = true;
}).$promise;
};
});

View File

@@ -1,21 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsRecoverController', function ($scope, apiService, cryptoService, $analytics) {
$scope.success = false;
$scope.submit = function (model) {
var email = model.email.toLowerCase();
$scope.submitPromise = cryptoService.makeKeyAndHash(model.email, model.masterPassword).then(function (result) {
return apiService.twoFactor.recover({
email: email,
masterPasswordHash: result.hash,
recoveryCode: model.code.replace(/\s/g, '').toLowerCase()
}).$promise;
}).then(function () {
$analytics.eventTrack('Recovered 2FA');
$scope.success = true;
});
};
});

View File

@@ -1,13 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsRecoverDeleteController', function ($scope, $rootScope, apiService, $analytics) {
$scope.success = false;
$scope.submit = function (model) {
$scope.submitPromise = apiService.accounts.postDeleteRecover({ email: model.email }, function () {
$analytics.eventTrack('Started Delete Recovery');
$scope.success = true;
}).$promise;
};
});

View File

@@ -1,92 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsRegisterController', function ($scope, $location, apiService, cryptoService, validationService,
$analytics, $state, $timeout) {
var params = $location.search();
var stateParams = $state.params;
$scope.createOrg = stateParams.org;
if (!stateParams.returnState && stateParams.org) {
$scope.returnState = {
name: 'backend.user.settingsCreateOrg',
params: { plan: $state.params.org }
};
}
else if (!stateParams.returnState && stateParams.premium) {
$scope.returnState = {
name: 'backend.user.settingsPremium',
params: { plan: $state.params.org }
};
}
else {
$scope.returnState = stateParams.returnState;
}
$scope.success = false;
$scope.model = {
email: params.email ? params.email : stateParams.email
};
$scope.readOnlyEmail = stateParams.email !== null;
$timeout(function () {
if ($scope.model.email) {
$("#name").focus();
}
else {
$("#email").focus();
}
});
$scope.registerPromise = null;
$scope.register = function (form) {
var error = false;
if ($scope.model.masterPassword.length < 8) {
validationService.addError(form, 'MasterPassword', 'Master password must be at least 8 characters long.', true);
error = true;
}
if ($scope.model.masterPassword !== $scope.model.confirmMasterPassword) {
validationService.addError(form, 'ConfirmMasterPassword', 'Master password confirmation does not match.', true);
error = true;
}
if (error) {
return;
}
var email = $scope.model.email.toLowerCase();
var makeResult, encKey;
$scope.registerPromise = cryptoService.makeKeyAndHash(email, $scope.model.masterPassword).then(function (result) {
makeResult = result;
encKey = cryptoService.makeEncKey(result.key);
return cryptoService.makeKeyPair(encKey.encKey);
}).then(function (result) {
var request = {
name: $scope.model.name,
email: email,
masterPasswordHash: makeResult.hash,
masterPasswordHint: $scope.model.masterPasswordHint,
key: encKey.encKeyEnc,
keys: {
publicKey: result.publicKey,
encryptedPrivateKey: result.privateKeyEnc
}
};
return apiService.accounts.register(request).$promise;
}, function (errors) {
validationService.addError(form, null, 'Problem generating keys.', true);
return false;
}).then(function (result) {
if (result === false) {
return;
}
$scope.success = true;
$analytics.eventTrack('Registered');
});
};
});

View File

@@ -1,40 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsTwoFactorMethodsController', function ($scope, $uibModalInstance, $analytics, providers, constants) {
$analytics.eventTrack('accountsTwoFactorMethodsController', { category: 'Modal' });
$scope.providers = [];
if (providers.hasOwnProperty(constants.twoFactorProvider.authenticator)) {
add(constants.twoFactorProvider.authenticator);
}
if (providers.hasOwnProperty(constants.twoFactorProvider.yubikey)) {
add(constants.twoFactorProvider.yubikey);
}
if (providers.hasOwnProperty(constants.twoFactorProvider.email)) {
add(constants.twoFactorProvider.email);
}
if (providers.hasOwnProperty(constants.twoFactorProvider.duo)) {
add(constants.twoFactorProvider.duo);
}
if (providers.hasOwnProperty(constants.twoFactorProvider.u2f) && u2f.isSupported) {
add(constants.twoFactorProvider.u2f);
}
$scope.choose = function (provider) {
$uibModalInstance.close(provider.type);
};
$scope.close = function () {
$uibModalInstance.dismiss('close');
};
function add(type) {
for (var i = 0; i < constants.twoFactorProviderInfo.length; i++) {
if (constants.twoFactorProviderInfo[i].type === type) {
$scope.providers.push(constants.twoFactorProviderInfo[i]);
}
}
}
});

View File

@@ -1,28 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsVerifyEmailController', function ($scope, $state, apiService, toastr, $analytics) {
if (!$state.params.userId || !$state.params.token) {
$state.go('frontend.login.info').then(function () {
toastr.error('Invalid parameters.');
});
return;
}
$scope.$on('$viewContentLoaded', function () {
apiService.accounts.verifyEmailToken({},
{
token: $state.params.token,
userId: $state.params.userId
}, function () {
$analytics.eventTrack('Verified Email');
$state.go('frontend.login.info', null, { location: 'replace' }).then(function () {
toastr.success('Your email has been verified. Thank you.', 'Success');
});
}, function () {
$state.go('frontend.login.info', null, { location: 'replace' }).then(function () {
toastr.error('Unable to verify email.', 'Error');
});
});
});
});

View File

@@ -1,36 +0,0 @@
angular
.module('bit.accounts')
.controller('accountsVerifyRecoverDeleteController', function ($scope, $state, apiService, toastr, $analytics) {
if (!$state.params.userId || !$state.params.token || !$state.params.email) {
$state.go('frontend.login.info').then(function () {
toastr.error('Invalid parameters.');
});
return;
}
$scope.email = $state.params.email;
$scope.delete = function () {
if (!confirm('Are you sure you want to delete this account? This cannot be undone.')) {
return;
}
$scope.deleting = true;
apiService.accounts.postDeleteRecoverToken({},
{
token: $state.params.token,
userId: $state.params.userId
}, function () {
$analytics.eventTrack('Recovered Delete');
$state.go('frontend.login.info', null, { location: 'replace' }).then(function () {
toastr.success('Your account has been deleted. You can register a new account again if you like.',
'Success');
});
}, function () {
$state.go('frontend.login.info', null, { location: 'replace' }).then(function () {
toastr.error('Unable to delete account.', 'Error');
});
});
};
});

View File

@@ -0,0 +1,27 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate>
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<p class="lead text-center mb-4">{{'passwordHint' | i18n}}</p>
<div class="card d-block">
<div class="card-body">
<div class="form-group">
<label for="email">{{'emailAddress' | i18n}}</label>
<input id="email" class="form-control" type="text" name="Email" [(ngModel)]="email" required
appAutofocus inputmode="email" appInputVerbatim="false">
<small class="form-text text-muted">{{'enterEmailToGetHint' | i18n}}</small>
</div>
<hr>
<div class="d-flex">
<button type="submit" class="btn btn-primary btn-block btn-submit" [disabled]="form.loading">
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
</button>
<a routerLink="/" class="btn btn-outline-secondary btn-block ml-2 mt-0">
{{'cancel' | i18n}}
</a>
</div>
</div>
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,19 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { HintComponent as BaseHintComponent } from 'jslib/angular/components/hint.component';
@Component({
selector: 'app-hint',
templateUrl: 'hint.component.html',
})
export class HintComponent extends BaseHintComponent {
constructor(router: Router, i18nService: I18nService,
apiService: ApiService, platformUtilsService: PlatformUtilsService) {
super(router, i18nService, apiService, platformUtilsService);
}
}

View File

@@ -0,0 +1,40 @@
<form (ngSubmit)="submit()" class="container" ngNativeValidate>
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<p class="text-center mb-4">
<i class="fa fa-lock fa-4x text-muted" aria-hidden="true"></i>
</p>
<p class="lead text-center mx-4 mb-4">{{'yourVaultIsLocked' | i18n}}</p>
<div class="card d-block">
<div class="card-body">
<div class="form-group">
<label for="masterPassword">{{'masterPass' | i18n}}</label>
<div class="d-flex">
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
name="MasterPassword" class="text-monospace form-control" [(ngModel)]="masterPassword"
required appAutofocus appInputVerbatim>
<button type="button" class="ml-1 btn btn-link" appA11yTitle="{{'toggleVisibility' | i18n}}"
(click)="togglePassword()">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</button>
</div>
<small class="text-muted form-text">
{{'loggedInAsEmailOn' | i18n : email : webVaultHostname}}
</small>
</div>
<hr>
<div class="d-flex">
<button type="submit" class="btn btn-primary btn-block">
<i class="fa fa-unlock-alt" aria-hidden="true"></i>
{{'unlock' | i18n}}
</button>
<button type="button" class="btn btn-outline-secondary btn-block ml-2 mt-0" (click)="logOut()">
{{'logOut' | i18n}}
</button>
</div>
</div>
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,50 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LockService } from 'jslib/abstractions/lock.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { UserService } from 'jslib/abstractions/user.service';
import { RouterService } from '../services/router.service';
import { LockComponent as BaseLockComponent } from 'jslib/angular/components/lock.component';
@Component({
selector: 'app-lock',
templateUrl: 'lock.component.html',
})
export class LockComponent extends BaseLockComponent {
constructor(router: Router, i18nService: I18nService,
platformUtilsService: PlatformUtilsService, messagingService: MessagingService,
userService: UserService, cryptoService: CryptoService,
storageService: StorageService, lockService: LockService,
environmentService: EnvironmentService, private routerService: RouterService,
stateService: StateService) {
super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService,
storageService, lockService, environmentService, stateService);
}
async ngOnInit() {
await super.ngOnInit();
const authed = await this.userService.isAuthenticated();
if (!authed) {
this.router.navigate(['/']);
} else if (await this.cryptoService.hasKey()) {
this.router.navigate(['vault']);
}
this.onSuccessfulSubmit = () => {
const previousUrl = this.routerService.getPreviousUrl();
if (previousUrl !== '/' && previousUrl.indexOf('lock') === -1) {
this.successRoute = previousUrl;
}
this.router.navigate([this.successRoute]);
};
}
}

View File

@@ -0,0 +1,51 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate>
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<img src="../../images/logo-dark@2x.png" class="logo mb-2" alt="Bitwarden">
<p class="lead text-center mx-4 mb-4">{{'loginOrCreateNewAccount' | i18n}}</p>
<div class="card d-block">
<div class="card-body">
<div class="form-group">
<label for="email">{{'emailAddress' | i18n}}</label>
<input id="email" class="form-control" type="text" name="Email" [(ngModel)]="email" required
inputmode="email" appInputVerbatim="false">
</div>
<div class="form-group">
<label for="masterPassword">{{'masterPass' | i18n}}</label>
<div class="d-flex">
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
name="MasterPassword" class="text-monospace form-control" [(ngModel)]="masterPassword"
required appInputVerbatim>
<button type="button" class="ml-1 btn btn-link" appA11yTitle="{{'toggleVisibility' | i18n}}"
(click)="togglePassword()">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</button>
</div>
<small class="form-text">
<a routerLink="/hint">{{'getMasterPasswordHint' | i18n}}</a>
</small>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="rememberEmail" name="RememberEmail"
[(ngModel)]="rememberEmail">
<label class="form-check-label" for="rememberEmail">{{'rememberEmail' | i18n}}</label>
</div>
<hr>
<div class="d-flex">
<button type="submit" class="btn btn-primary btn-block btn-submit" [disabled]="form.loading">
<span>
<i class="fa fa-sign-in" aria-hidden="true"></i> {{'logIn' | i18n}}
</span>
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
</button>
<a routerLink="/register" [queryParams]="{email: email}"
class="btn btn-outline-secondary btn-block ml-2 mt-0">
<i class="fa fa-pencil-square-o" aria-hidden="true"></i> {{'createAccount' | i18n}}
</a>
</div>
</div>
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,60 @@
import { Component } from '@angular/core';
import {
ActivatedRoute,
Router,
} from '@angular/router';
import { AuthService } from 'jslib/abstractions/auth.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { LoginComponent as BaseLoginComponent } from 'jslib/angular/components/login.component';
@Component({
selector: 'app-login',
templateUrl: 'login.component.html',
})
export class LoginComponent extends BaseLoginComponent {
constructor(authService: AuthService, router: Router,
i18nService: I18nService, private route: ActivatedRoute,
storageService: StorageService, stateService: StateService,
platformUtilsService: PlatformUtilsService) {
super(authService, router, platformUtilsService, i18nService, storageService, stateService);
this.onSuccessfulLoginNavigate = this.goAfterLogIn;
}
async ngOnInit() {
const queryParamsSub = this.route.queryParams.subscribe(async (qParams) => {
if (qParams.email != null && qParams.email.indexOf('@') > -1) {
this.email = qParams.email;
}
if (qParams.premium != null) {
this.stateService.save('loginRedirect', { route: '/settings/premium' });
} else if (qParams.org != null) {
this.stateService.save('loginRedirect',
{ route: '/settings/create-organization', qParams: { plan: qParams.org } });
}
await super.ngOnInit();
if (queryParamsSub != null) {
queryParamsSub.unsubscribe();
}
});
}
async goAfterLogIn() {
const invite = await this.stateService.get<any>('orgInvitation');
if (invite != null) {
this.router.navigate(['accept-organization'], { queryParams: invite });
} else {
const loginRedirect = await this.stateService.get<any>('loginRedirect');
if (loginRedirect != null) {
this.router.navigate([loginRedirect.route], { queryParams: loginRedirect.qParams });
await this.stateService.remove('loginRedirect');
} else {
this.router.navigate([this.successRoute]);
}
}
}
}

View File

@@ -0,0 +1,27 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate>
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<p class="lead text-center mb-4">{{'deleteAccount' | i18n}}</p>
<div class="card">
<div class="card-body">
<p>{{'deleteRecoverDesc' | i18n}}</p>
<div class="form-group">
<label for="email">{{'emailAddress' | i18n}}</label>
<input id="email" class="form-control" type="text" name="Email" [(ngModel)]="email" required
appAutofocus inputmode="email" appInputVerbatim="false">
</div>
<hr>
<div class="d-flex">
<button type="submit" class="btn btn-primary btn-block btn-submit" [disabled]="form.loading">
<span>{{'submit' | i18n}}</span>
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
</button>
<a routerLink="/" class="btn btn-outline-secondary btn-block ml-2 mt-0">
{{'cancel' | i18n}}
</a>
</div>
</div>
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,36 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { DeleteRecoverRequest } from 'jslib/models/request/deleteRecoverRequest';
@Component({
selector: 'app-recover-delete',
templateUrl: 'recover-delete.component.html',
})
export class RecoverDeleteComponent {
email: string;
formPromise: Promise<any>;
constructor(private router: Router, private apiService: ApiService,
private analytics: Angulartics2, private toasterService: ToasterService,
private i18nService: I18nService) {
}
async submit() {
try {
const request = new DeleteRecoverRequest();
request.email = this.email.trim().toLowerCase();
this.formPromise = this.apiService.postAccountRecoverDelete(request);
await this.formPromise;
this.analytics.eventTrack.next({ action: 'Started Delete Recovery' });
this.toasterService.popAsync('success', null, this.i18nService.t('deleteRecoverEmailSent'));
this.router.navigate(['/']);
} catch { }
}
}

View File

@@ -0,0 +1,40 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate>
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<p class="lead text-center mb-4">{{'recoverAccountTwoStep' | i18n}}</p>
<div class="card">
<div class="card-body">
<p>{{'recoverAccountTwoStepDesc' | i18n}}
<a href="https://help.bitwarden.com/article/lost-two-step-device/" target="_blank"
rel="noopener">{{'learnMore' | i18n}}</a>
</p>
<div class="form-group">
<label for="email">{{'emailAddress' | i18n}}</label>
<input id="email" class="form-control" type="text" name="Email" [(ngModel)]="email" required
appAutofocus inputmode="email" appInputVerbatim="false">
</div>
<div class="form-group">
<label for="masterPassword">{{'masterPass' | i18n}}</label>
<input id="masterPassword" type="password" name="MasterPassword" class="form-control"
[(ngModel)]="masterPassword" required appInputVerbatim>
</div>
<div class="form-group">
<label for="recoveryCode">{{'recoveryCodeTitle' | i18n}}</label>
<input id="recoveryCode" class="text-monospace form-control" type="text" name="RecoveryCode"
[(ngModel)]="recoveryCode" required appInputVerbatim>
</div>
<hr>
<div class="d-flex">
<button type="submit" class="btn btn-primary btn-block btn-submit" [disabled]="form.loading">
<span>{{'submit' | i18n}}</span>
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
</button>
<a routerLink="/" class="btn btn-outline-secondary btn-block ml-2 mt-0">
{{'cancel' | i18n}}
</a>
</div>
</div>
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,43 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import { ApiService } from 'jslib/abstractions/api.service';
import { AuthService } from 'jslib/abstractions/auth.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { TwoFactorRecoveryRequest } from 'jslib/models/request/twoFactorRecoveryRequest';
@Component({
selector: 'app-recover-two-factor',
templateUrl: 'recover-two-factor.component.html',
})
export class RecoverTwoFactorComponent {
email: string;
masterPassword: string;
recoveryCode: string;
formPromise: Promise<any>;
constructor(private router: Router, private apiService: ApiService,
private analytics: Angulartics2, private toasterService: ToasterService,
private i18nService: I18nService, private cryptoService: CryptoService,
private authService: AuthService) { }
async submit() {
try {
const request = new TwoFactorRecoveryRequest();
request.recoveryCode = this.recoveryCode.replace(/\s/g, '').toLowerCase();
request.email = this.email.trim().toLowerCase();
const key = await this.authService.makePreloginKey(this.masterPassword, request.email);
request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, key);
this.formPromise = this.apiService.postTwoFactorRecover(request);
await this.formPromise;
this.analytics.eventTrack.next({ action: 'Recovered 2FA' });
this.toasterService.popAsync('success', null, this.i18nService.t('twoStepRecoverDisabled'));
this.router.navigate(['/']);
} catch { }
}
}

View File

@@ -0,0 +1,103 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate>
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<p class="lead text-center mb-4">{{'createAccount' | i18n}}</p>
<div class="card d-block">
<div class="card-body">
<app-callout title="{{'createOrganizationStep1' | i18n}}" type="info" icon="fa-thumb-tack"
*ngIf="showCreateOrgMessage">
{{'createOrganizationCreatePersonalAccount' | i18n}}
</app-callout>
<div class="form-group">
<label for="email">{{'emailAddress' | i18n}}</label>
<input id="email" class="form-control" type="text" name="Email" [(ngModel)]="email" required
[appAutofocus]="email === ''" inputmode="email" appInputVerbatim="false">
<small class="form-text text-muted">{{'emailAddressDesc' | i18n}}</small>
</div>
<div class="form-group">
<label for="name">{{'yourName' | i18n}}</label>
<input id="name" class="form-control" type="text" name="Name" [(ngModel)]="name"
[appAutofocus]="email !== ''">
<small class="form-text text-muted">{{'yourNameDesc' | i18n}}</small>
</div>
<div class="form-group">
<app-callout type="info" *ngIf="enforcedPolicyOptions">
{{'masterPasswordPolicyInEffect' | i18n}}
<ul class="mb-0">
<li *ngIf="enforcedPolicyOptions?.minComplexity > 0">
{{'policyInEffectMinComplexity' | i18n : getPasswordScoreAlertDisplay()}}
</li>
<li *ngIf="enforcedPolicyOptions?.minLength > 0">
{{'policyInEffectMinLength' | i18n : enforcedPolicyOptions?.minLength.toString()}}
</li>
<li *ngIf="enforcedPolicyOptions?.requireUpper">
{{'policyInEffectUppercase' | i18n}}</li>
<li *ngIf="enforcedPolicyOptions?.requireLower">
{{'policyInEffectLowercase' | i18n}}</li>
<li *ngIf="enforcedPolicyOptions?.requireNumbers">
{{'policyInEffectNumbers' | i18n}}</li>
<li *ngIf="enforcedPolicyOptions?.requireSpecial">
{{'policyInEffectSpecial' | i18n : '!@#$%^&*'}}</li>
</ul>
</app-callout>
<label for="masterPassword">{{'masterPass' | i18n}}</label>
<div class="d-flex">
<div class="w-100">
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
name="MasterPassword" class="text-monospace form-control mb-1"
[(ngModel)]="masterPassword" (input)="updatePasswordStrength()" required
appInputVerbatim>
<app-password-strength [score]="masterPasswordScore" [showText]="true">
</app-password-strength>
</div>
<div>
<button type="button" class="ml-1 btn btn-link"
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</button>
<div class="progress-bar invisible"></div>
</div>
</div>
<small class="form-text text-muted">{{'masterPassDesc' | i18n}}</small>
</div>
<div class="form-group">
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
<div class="d-flex">
<input id="masterPasswordRetype" type="{{showPassword ? 'text' : 'password'}}"
name="MasterPasswordRetype" class="text-monospace form-control"
[(ngModel)]="confirmMasterPassword" required appInputVerbatim>
<button type="button" class="ml-1 btn btn-link" appA11yTitle="{{'toggleVisibility' | i18n}}"
(click)="togglePassword(true)">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</button>
</div>
</div>
<div class="form-group">
<label for="hint">{{'masterPassHint' | i18n}}</label>
<input id="hint" class="form-control" type="text" name="Hint" [(ngModel)]="hint">
<small class="form-text text-muted">{{'masterPassHintDesc' | i18n}}</small>
</div>
<hr>
<div class="d-flex mb-2">
<button type="submit" class="btn btn-primary btn-block btn-submit" [disabled]="form.loading">
<span>{{'submit' | i18n}}</span>
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
</button>
<a routerLink="/" class="btn btn-outline-secondary btn-block ml-2 mt-0">
{{'cancel' | i18n}}
</a>
</div>
<small class="text-muted" *ngIf="showTerms">
{{'submitAgreePolicies' | i18n}}
<a href="https://bitwarden.com/terms/" target="_blank"
rel="noopener">{{'termsOfService' | i18n}}</a>,
<a href="https://bitwarden.com/privacy/" target="_blank"
rel="noopener">{{'privacyPolicy' | i18n}}</a>
</small>
</div>
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,108 @@
import { Component } from '@angular/core';
import {
ActivatedRoute,
Router,
} from '@angular/router';
import { ApiService } from 'jslib/abstractions/api.service';
import { AuthService } from 'jslib/abstractions/auth.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { StateService } from 'jslib/abstractions/state.service';
import { RegisterComponent as BaseRegisterComponent } from 'jslib/angular/components/register.component';
import { MasterPasswordPolicyOptions } from 'jslib/models/domain/masterPasswordPolicyOptions';
import { Policy } from 'jslib/models/domain/policy';
import { PolicyData } from 'jslib/models/data/policyData';
@Component({
selector: 'app-register',
templateUrl: 'register.component.html',
})
export class RegisterComponent extends BaseRegisterComponent {
showCreateOrgMessage = false;
showTerms = true;
enforcedPolicyOptions: MasterPasswordPolicyOptions;
private policies: Policy[];
constructor(authService: AuthService, router: Router,
i18nService: I18nService, cryptoService: CryptoService,
apiService: ApiService, private route: ActivatedRoute,
stateService: StateService, platformUtilsService: PlatformUtilsService,
passwordGenerationService: PasswordGenerationService, private policyService: PolicyService) {
super(authService, router, i18nService, cryptoService, apiService, stateService, platformUtilsService,
passwordGenerationService);
this.showTerms = !platformUtilsService.isSelfHost();
}
getPasswordScoreAlertDisplay() {
if (this.enforcedPolicyOptions == null) {
return '';
}
let str: string;
switch (this.enforcedPolicyOptions.minComplexity) {
case 4:
str = this.i18nService.t('strong');
break;
case 3:
str = this.i18nService.t('good');
break;
default:
str = this.i18nService.t('weak');
break;
}
return str + ' (' + this.enforcedPolicyOptions.minComplexity + ')';
}
async ngOnInit() {
const queryParamsSub = this.route.queryParams.subscribe((qParams) => {
if (qParams.email != null && qParams.email.indexOf('@') > -1) {
this.email = qParams.email;
}
if (qParams.premium != null) {
this.stateService.save('loginRedirect', { route: '/settings/premium' });
} else if (qParams.org != null) {
this.showCreateOrgMessage = true;
this.stateService.save('loginRedirect',
{ route: '/settings/create-organization', qParams: { plan: qParams.org } });
}
if (queryParamsSub != null) {
queryParamsSub.unsubscribe();
}
});
const invite = await this.stateService.get<any>('orgInvitation');
if (invite != null) {
try {
const policies = await this.apiService.getPoliciesByToken(invite.organizationId, invite.token,
invite.email, invite.organizationUserId);
if (policies.data != null) {
const policiesData = policies.data.map((p) => new PolicyData(p));
this.policies = policiesData.map((p) => new Policy(p));
}
} catch { }
}
if (this.policies != null) {
this.enforcedPolicyOptions = await this.policyService.getMasterPasswordPolicyOptions(this.policies);
}
}
async submit() {
if (this.enforcedPolicyOptions != null &&
!this.policyService.evaluateMasterPassword(this.masterPasswordScore, this.masterPassword,
this.enforcedPolicyOptions)) {
this.platformUtilsService.showToast('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('masterPasswordPolicyRequirementsNotMet'));
return;
}
await super.submit();
}
}

View File

@@ -0,0 +1,27 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="twoStepOptionsTitle">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="twoStepOptionsTitle">{{'twoStepOptions' | i18n}}</h2>
<button type="button" class="close" data-dismiss="modal" appA11yTitle="{{'close' | i18n}}">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="list-group list-group-flush">
<a href="#" appStopClick *ngFor="let p of providers" (click)="choose(p)"
class="list-group-item list-group-item-action">
<img [src]="'images/two-factor/' + p.type + '.png'" alt="" class="pull-right">
<h3>{{p.name}}</h3>
{{p.description}}
</a>
<a href="#" appStopClick class="list-group-item list-group-item-action" (click)="recover()">
<h3>{{'recoveryCodeTitle' | i18n}}</h3>
{{'recoveryCodeDesc' | i18n}}
</a>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">{{'close' | i18n}}</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,21 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from 'jslib/abstractions/auth.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import {
TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent,
} from 'jslib/angular/components/two-factor-options.component';
@Component({
selector: 'app-two-factor-options',
templateUrl: 'two-factor-options.component.html',
})
export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
constructor(authService: AuthService, router: Router,
i18nService: I18nService, platformUtilsService: PlatformUtilsService) {
super(authService, router, i18nService, platformUtilsService, window);
}
}

View File

@@ -0,0 +1,87 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate autocomplete="off">
<div class="row justify-content-md-center mt-5">
<div class="col-5"
[ngClass]="{'col-9': selectedProviderType === providerType.Duo || selectedProviderType === providerType.OrganizationDuo}">
<p class="lead text-center mb-4">{{title}}</p>
<div class="card d-block">
<div class="card-body">
<ng-container
*ngIf="selectedProviderType === providerType.Email || selectedProviderType === providerType.Authenticator">
<p *ngIf="selectedProviderType === providerType.Authenticator">
{{'enterVerificationCodeApp' | i18n}}</p>
<p *ngIf="selectedProviderType === providerType.Email">
{{'enterVerificationCodeEmail' | i18n : twoFactorEmail}}
</p>
<div class="form-group">
<label for="code" class="sr-only">{{'verificationCode' | i18n}}</label>
<input id="code" type="text" name="Code" class="form-control" [(ngModel)]="token" required
appAutofocus inputmode="tel" appInputVerbatim>
<small class="form-text" *ngIf="selectedProviderType === providerType.Email">
<a href="#" appStopClick (click)="sendEmail(true)" [appApiAction]="emailPromise"
*ngIf="selectedProviderType === providerType.Email">
{{'sendVerificationCodeEmailAgain' | i18n}}
</a>
</small>
</div>
</ng-container>
<ng-container *ngIf="selectedProviderType === providerType.Yubikey">
<p class="text-center">{{'insertYubiKey' | i18n}}</p>
<img src="../../images/yubikey.jpg" class="rounded img-fluid mb-3" alt="">
<div class="form-group">
<label for="code" class="sr-only">{{'verificationCode' | i18n}}</label>
<input id="code" type="password" name="Code" class="form-control" [(ngModel)]="token"
required appAutofocus appInputVerbatim autocomplete="new-password">
</div>
</ng-container>
<ng-container *ngIf="selectedProviderType === providerType.U2f">
<p class="text-center" *ngIf="!u2fReady">
<i class="fa fa-spinner fa-spin text-muted" title="{{'loading' | i18n}}"
aria-hidden="true"></i>
<span class="sr-only">{{'loading' | i18n}}</span>
</p>
<ng-container *ngIf="u2fReady">
<p class="text-center">{{'insertU2f' | i18n}}</p>
<img src="../../images/u2fkey.jpg" alt="" class="rounded img-fluid mb-3">
</ng-container>
</ng-container>
<ng-container *ngIf="selectedProviderType === providerType.Duo ||
selectedProviderType === providerType.OrganizationDuo">
<div id="duo-frame" class="mb-3">
<iframe id="duo_iframe"></iframe>
</div>
</ng-container>
<i class="fa fa-spinner text-muted fa-spin pull-right" title="{{'loading' | i18n}}"
*ngIf="form.loading && selectedProviderType === providerType.U2f" aria-hidden="true"></i>
<div class="form-check" *ngIf="selectedProviderType != null">
<input id="remember" type="checkbox" name="Remember" class="form-check-input"
[(ngModel)]="remember">
<label for="remember" class="form-check-label">{{'rememberMe' | i18n}}</label>
</div>
<ng-container *ngIf="selectedProviderType == null">
<p>{{'noTwoStepProviders' | i18n}}</p>
<p>{{'noTwoStepProviders2' | i18n}}</p>
</ng-container>
<hr>
<div class="d-flex mb-3">
<button type="submit" class="btn btn-primary btn-block btn-submit" [disabled]="form.loading"
*ngIf="selectedProviderType != null && selectedProviderType !== providerType.Duo &&
selectedProviderType !== providerType.OrganizationDuo && selectedProviderType !== providerType.U2f">
<span>
<i class="fa fa-sign-in" aria-hidden="true"></i> {{'continue' | i18n}}
</span>
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
</button>
<a routerLink="/" class="btn btn-outline-secondary btn-block ml-2 mt-0">
{{'cancel' | i18n}}
</a>
</div>
<div class="text-center">
<a href="#" appStopClick (click)="anotherMethod()">{{'useAnotherTwoStepMethod' | i18n}}</a>
</div>
</div>
</div>
</div>
</div>
</form>
<ng-template #twoFactorOptions></ng-template>
<iframe id="u2f_iframe" hidden></iframe>

View File

@@ -0,0 +1,73 @@
import {
Component,
ComponentFactoryResolver,
ViewChild,
ViewContainerRef,
} from '@angular/core';
import { Router } from '@angular/router';
import { TwoFactorOptionsComponent } from './two-factor-options.component';
import { ModalComponent } from '../modal.component';
import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType';
import { ApiService } from 'jslib/abstractions/api.service';
import { AuthService } from 'jslib/abstractions/auth.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib/angular/components/two-factor.component';
@Component({
selector: 'app-two-factor',
templateUrl: 'two-factor.component.html',
})
export class TwoFactorComponent extends BaseTwoFactorComponent {
@ViewChild('twoFactorOptions', { read: ViewContainerRef }) twoFactorOptionsModal: ViewContainerRef;
constructor(authService: AuthService, router: Router,
i18nService: I18nService, apiService: ApiService,
platformUtilsService: PlatformUtilsService, stateService: StateService,
environmentService: EnvironmentService, private componentFactoryResolver: ComponentFactoryResolver,
storageService: StorageService) {
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService,
stateService, storageService);
this.onSuccessfulLoginNavigate = this.goAfterLogIn;
}
anotherMethod() {
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
const modal = this.twoFactorOptionsModal.createComponent(factory).instance;
const childComponent = modal.show<TwoFactorOptionsComponent>(TwoFactorOptionsComponent,
this.twoFactorOptionsModal);
childComponent.onProviderSelected.subscribe(async (provider: TwoFactorProviderType) => {
modal.close();
this.selectedProviderType = provider;
await this.init();
});
childComponent.onRecoverSelected.subscribe(() => {
modal.close();
});
}
async goAfterLogIn() {
const invite = await this.stateService.get<any>('orgInvitation');
if (invite != null) {
this.router.navigate(['accept-organization'], { queryParams: invite });
} else {
const loginRedirect = await this.stateService.get<any>('loginRedirect');
if (loginRedirect != null) {
this.router.navigate([loginRedirect.route], { queryParams: loginRedirect.qParams });
await this.stateService.remove('loginRedirect');
} else {
this.router.navigate([this.successRoute]);
}
}
}
}

View File

@@ -0,0 +1,9 @@
<div class="mt-5 d-flex justify-content-center">
<div>
<img src="../../images/logo-dark@2x.png" class="mb-4 logo" alt="Bitwarden">
<p class="text-center">
<i class="fa fa-spinner fa-spin fa-2x text-muted" title="{{'loading' | i18n}}" aria-hidden="true"></i>
<span class="sr-only">{{'loading' | i18n}}</span>
</p>
</div>
</div>

View File

@@ -0,0 +1,51 @@
import {
Component,
OnInit,
} from '@angular/core';
import {
ActivatedRoute,
Router,
} from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { UserService } from 'jslib/abstractions/user.service';
import { VerifyEmailRequest } from 'jslib/models/request/verifyEmailRequest';
@Component({
selector: 'app-verify-email-token',
templateUrl: 'verify-email-token.component.html',
})
export class VerifyEmailTokenComponent implements OnInit {
constructor(private router: Router, private toasterService: ToasterService,
private i18nService: I18nService, private route: ActivatedRoute,
private apiService: ApiService, private userService: UserService) { }
ngOnInit() {
let fired = false;
this.route.queryParams.subscribe(async (qParams) => {
if (fired) {
return;
}
fired = true;
if (qParams.userId != null && qParams.token != null) {
try {
await this.apiService.postAccountVerifyEmailToken(
new VerifyEmailRequest(qParams.userId, qParams.token));
const authed = await this.userService.isAuthenticated();
if (authed) {
await this.apiService.refreshIdentityToken();
}
this.toasterService.popAsync('success', null, this.i18nService.t('emailVerified'));
this.router.navigate(['/']);
return;
} catch { }
}
this.toasterService.popAsync('error', null, this.i18nService.t('emailVerifiedFailed'));
this.router.navigate(['/']);
});
}
}

View File

@@ -0,0 +1,26 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate>
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<p class="lead text-center mb-4">{{'deleteAccount' | i18n}}</p>
<div class="card">
<div class="card-body">
<app-callout type="warning">{{'deleteAccountWarning' | i18n}}</app-callout>
<p class="text-center">
<strong>{{email}}</strong>
</p>
<p>{{'deleteRecoverConfirmDesc' | i18n}}</p>
<hr>
<div class="d-flex">
<button type="submit" class="btn btn-danger btn-block btn-submit" [disabled]="form.loading">
<span>{{'deleteAccount' | i18n}}</span>
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
</button>
<a routerLink="/" class="btn btn-outline-secondary btn-block ml-2 mt-0">
{{'cancel' | i18n}}
</a>
</div>
</div>
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,62 @@
import {
Component,
OnInit,
} from '@angular/core';
import {
ActivatedRoute,
Router,
} from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { VerifyDeleteRecoverRequest } from 'jslib/models/request/verifyDeleteRecoverRequest';
@Component({
selector: 'app-verify-recover-delete',
templateUrl: 'verify-recover-delete.component.html',
})
export class VerifyRecoverDeleteComponent implements OnInit {
email: string;
formPromise: Promise<any>;
private userId: string;
private token: string;
constructor(private router: Router, private apiService: ApiService,
private analytics: Angulartics2, private toasterService: ToasterService,
private i18nService: I18nService, private route: ActivatedRoute) {
}
ngOnInit() {
let fired = false;
this.route.queryParams.subscribe(async (qParams) => {
if (fired) {
return;
}
fired = true;
if (qParams.userId != null && qParams.token != null && qParams.email != null) {
this.userId = qParams.userId;
this.token = qParams.token;
this.email = qParams.email;
} else {
this.router.navigate(['/']);
}
});
}
async submit() {
try {
const request = new VerifyDeleteRecoverRequest(this.userId, this.token);
this.formPromise = this.apiService.postAccountRecoverDeleteToken(request);
await this.formPromise;
this.analytics.eventTrack.next({ action: 'Recovered Delete' });
this.toasterService.popAsync('success', this.i18nService.t('accountDeleted'),
this.i18nService.t('accountDeletedDesc'));
this.router.navigate(['/']);
} catch { }
}
}

View File

@@ -1,7 +0,0 @@
<div class="login-box">
<div class="login-logo">
<i class="fa fa-shield"></i> <b>bit</b>warden
</div>
<div class="login-box-body" ui-view>
</div>
</div>

View File

@@ -1,49 +0,0 @@
<p class="login-box-msg">Log in to access your vault.</p>
<form name="loginForm" ng-submit="loginForm.$valid && login(model)" api-form="loginPromise">
<div class="callout callout-danger validation-errors" ng-show="loginForm.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in loginForm.$errors">{{e}}</li>
</ul>
</div>
<div class="form-group has-feedback" show-errors>
<label for="email" class="sr-only">Email</label>
<input type="email" id="email" name="Email" class="form-control" placeholder="Email" ng-model="model.email"
required api-field />
<span class="fa fa-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback" show-errors>
<label for="masterPassword" class="sr-only">Master Password</label>
<input type="password" id="masterPassword" name="MasterPasswordHash" class="form-control" placeholder="Master Password"
ng-model="model.masterPassword"
required api-field />
<span class="fa fa-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-7">
<div class="checkbox">
<label>
<input type="checkbox" id="rememberEmail" ng-model="model.rememberEmail" /> Remember Email
</label>
</div>
</div>
<div class="col-xs-5">
<button type="submit" class="btn btn-primary btn-block btn-flat" ng-disabled="loginForm.$loading">
<i class="fa fa-refresh fa-spin loading-icon" ng-show="loginForm.$loading"></i>Log In
</button>
</div>
</div>
<hr />
<ul>
<li>
<a ui-sref="frontend.register({returnState: returnState, email: stateEmail})">
Create a new account
</a>
</li>
<li>
<a ui-sref="frontend.passwordHint">
Get master password hint
</a>
</li>
</ul>
</form>

View File

@@ -1,166 +0,0 @@
<div ng-if="twoFactorProvider === twoFactorProviderConstants.authenticator ||
twoFactorProvider === twoFactorProviderConstants.email">
<p class="login-box-msg" ng-if="twoFactorProvider === twoFactorProviderConstants.authenticator">
Enter the 6 digit verification code from your authenticator app.
</p>
<div ng-if="twoFactorProvider === twoFactorProviderConstants.email" class="text-center">
<p class="login-box-msg">
Enter the 6 digit verification code that was emailed to <b>{{twoFactorEmail}}</b>.
</p>
<p>
Didn't get the email?
<a href="#" stop-click ng-click="sendEmail(true)" ng-if="twoFactorProvider === twoFactorProviderConstants.email">
Send it again
</a>
</p>
</div>
<form name="twoFactorForm" ng-submit="twoFactorForm.$valid && twoFactor(token)" api-form="twoFactorPromise">
<div class="callout callout-danger validation-errors" ng-show="twoFactorForm.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in twoFactorForm.$errors">{{e}}</li>
</ul>
</div>
<div class="form-group has-feedback" show-errors>
<label for="code" class="sr-only">Code</label>
<input type="text" id="code" name="Code" class="form-control" placeholder="Verification code"
ng-model="token" required api-field autocomplete="off" autocorrect="off" autocapitalize="off"
spellcheck="false" />
<span class="fa fa-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-7">
<div class="checkbox">
<label>
<input type="checkbox" id="rememberMe" ng-model="rememberTwoFactor.checked" /> Remember Me
</label>
</div>
</div>
<div class="col-xs-5">
<button type="submit" class="btn btn-primary btn-block btn-flat" ng-disabled="twoFactorForm.$loading">
<i class="fa fa-refresh fa-spin loading-icon" ng-show="twoFactorForm.$loading"></i>Log In
</button>
</div>
</div>
</form>
</div>
<div ng-if="twoFactorProvider === twoFactorProviderConstants.yubikey">
<p class="login-box-msg">
Complete logging in with YubiKey.
</p>
<form name="twoFactorForm" ng-submit="twoFactorForm.$valid && twoFactor(token)" api-form="twoFactorPromise"
autocomplete="off">
<div class="callout callout-danger validation-errors" ng-show="twoFactorForm.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in twoFactorForm.$errors">{{e}}</li>
</ul>
</div>
<p>Insert your YubiKey into your computer's USB port, then touch its button.</p>
<p>
<img src="images/two-factor/yubikey.jpg" alt="" class="img-rounded img-responsive" />
</p>
<div class="form-group" show-errors>
<label for="code" class="sr-only">Token</label>
<input type="password" id="code" name="Token" class="form-control" ng-model="token" required api-field />
</div>
<div class="row">
<div class="col-xs-7">
<div class="checkbox">
<label>
<input type="checkbox" id="rememberMe" ng-model="rememberTwoFactor.checked" /> Remember Me
</label>
</div>
</div>
<div class="col-xs-5">
<button type="submit" class="btn btn-primary btn-block btn-flat" ng-disabled="twoFactorForm.$loading">
<i class="fa fa-refresh fa-spin loading-icon" ng-show="twoFactorForm.$loading"></i>Log In
</button>
</div>
</div>
</form>
</div>
<div ng-if="twoFactorProvider === twoFactorProviderConstants.duo">
<p class="login-box-msg">
Complete logging in with Duo.
</p>
<form name="twoFactorForm" ng-submit="twoFactorForm.$valid && twoFactor(token)" api-form="twoFactorPromise"
autocomplete="off">
<div class="callout callout-danger validation-errors" ng-show="twoFactorForm.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in twoFactorForm.$errors">{{e}}</li>
</ul>
</div>
<div id="duoFrameWrapper">
<iframe id="duo_iframe"></iframe>
</div>
<div class="row">
<div class="col-xs-7">
<div class="checkbox">
<label>
<input type="checkbox" id="rememberMe" ng-model="rememberTwoFactor.checked" /> Remember Me
</label>
</div>
</div>
<div class="col-xs-5">
<span ng-show="twoFactorForm.$loading">
<i class="fa fa-refresh fa-spin loading-icon"></i> Logging in...
</span>
</div>
</div>
</form>
</div>
<div ng-if="twoFactorProvider === twoFactorProviderConstants.u2f">
<p class="login-box-msg">
Complete logging in with FIDO U2F.
</p>
<form name="twoFactorForm" api-form="twoFactorPromise" autocomplete="off">
<div class="callout callout-danger validation-errors" ng-show="twoFactorForm.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in twoFactorForm.$errors">{{e}}</li>
</ul>
</div>
<p>Insert your Security Key into your computer's USB port. If it has a button, touch it.</p>
<p>
<img src="images/two-factor/u2fkey.jpg" alt="" class="img-rounded img-responsive" />
</p>
<div class="row">
<div class="col-xs-7">
<div class="checkbox">
<label>
<input type="checkbox" id="rememberMe" ng-model="rememberTwoFactor.checked" /> Remember Me
</label>
</div>
</div>
<div class="col-xs-5">
<span ng-show="twoFactorForm.$loading">
<i class="fa fa-refresh fa-spin loading-icon"></i> Logging in...
</span>
</div>
</div>
</form>
</div>
<div ng-if="twoFactorProvider === null">
<p>
This account has two-step login enabled, however, none of the configured two-step providers are supported by this
web browser.
</p>
Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported
across web browsers (such as an authenticator app).
</div>
<hr />
<ul>
<li>
<a stop-click href="#" ng-click="anotherMethod()">Use another two-step login method</a>
</li>
<li>
<a ui-sref="frontend.login.info({returnState: returnState})">Back to log in</a>
</li>
</ul>

View File

@@ -1,32 +0,0 @@
<div class="login-box">
<div class="login-logo">
<i class="fa fa-shield"></i> <b>bit</b>warden
</div>
<div class="login-box-body">
<div ng-show="loading">
Loading...
</div>
<div ng-show="accepting">
Accepting invitation...
</div>
<div ng-show="!loading && !accepting">
<p class="login-box-msg">Join {{state.params.organizationName}}</p>
<p class="text-center"><strong>{{state.params.email}}</strong></p>
<p>
You've been invited to join the organization listed above.
To accept the invitation, you need to log in or create a new bitwarden account.
</p>
<hr />
<div class="row">
<div class="col-sm-6">
<a ui-sref="frontend.login.info({returnState: state, email: state.params.email})"
class="btn btn-primary btn-block btn-flat">Log In</a>
</div>
<div class="col-sm-6">
<a ui-sref="frontend.register({returnState: state, email: state.params.email})"
class="btn btn-primary btn-block btn-flat">Create Account</a>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,39 +0,0 @@
<div class="login-box">
<div class="login-logo">
<i class="fa fa-shield"></i> <b>bit</b>warden
</div>
<div class="login-box-body">
<p class="login-box-msg">Get your master password hint.</p>
<div class="text-center" ng-show="success">
<div class="callout callout-success">
If your account exists ({{model.email}}) we've sent you an email with your master password hint.
</div>
<a ui-sref="frontend.login.info">Ready to log in?</a>
</div>
<form name="passwordHintForm" ng-submit="passwordHintForm.$valid && submit(model)" ng-show="!success"
api-form="submitPromise">
<div class="callout callout-danger validation-errors" ng-show="passwordHintForm.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in passwordHintForm.$errors">{{e}}</li>
</ul>
</div>
<div class="form-group has-feedback" show-errors>
<label for="email" class="sr-only">Your account email address</label>
<input type="email" id="email" name="Email" class="form-control" placeholder="Your account email address"
ng-model="model.email" required api-field />
<span class="fa fa-envelope form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-7">
<a ui-sref="frontend.login.info">Ready to log in?</a>
</div>
<div class="col-xs-5">
<button type="submit" class="btn btn-primary btn-block btn-flat" ng-disabled="passwordHintForm.$loading">
<i class="fa fa-refresh fa-spin loading-icon" ng-show="passwordHintForm.$loading"></i>Submit
</button>
</div>
</div>
</form>
</div>
</div>

View File

@@ -1,56 +0,0 @@
<div class="login-box">
<div class="login-logo">
<i class="fa fa-shield"></i> <b>bit</b>warden
</div>
<div class="login-box-body">
<p class="login-box-msg">
In the event that you cannot access your account through your normal two-step login methods, you can use your
two-step login recovery code to disable all two-step providers on your account.
<a href="https://help.bitwarden.com/article/lost-two-step-device/" target="_blank">Learn more</a>
</p>
<div class="text-center" ng-show="success">
<div class="callout callout-success">
Two-step login has been successfully disabled on your account.
</div>
<a ui-sref="frontend.login.info">Ready to log in?</a>
</div>
<form name="recoverForm" ng-submit="recoverForm.$valid && submit(model)" ng-show="!success"
api-form="submitPromise">
<div class="callout callout-danger validation-errors" ng-show="recoverForm.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in recoverForm.$errors">{{e}}</li>
</ul>
</div>
<div class="form-group has-feedback" show-errors>
<label for="email" class="sr-only">Email</label>
<input type="email" id="email" name="Email" class="form-control" placeholder="Email" ng-model="model.email"
required api-field />
<span class="fa fa-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback" show-errors>
<label for="masterPassword" class="sr-only">Master Password</label>
<input type="password" id="masterPassword" name="MasterPasswordHash" class="form-control" placeholder="Master Password"
ng-model="model.masterPassword"
required api-field />
<span class="fa fa-lock form-control-feedback"></span>
</div>
<div class="form-group has-feedback" show-errors>
<label for="code" class="sr-only">Recovery code</label>
<input type="text" id="code" name="RecoveryCode" class="form-control" placeholder="Recovery code"
ng-model="model.code" required api-field />
<span class="fa fa-key form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-7">
<a ui-sref="frontend.login.info">Ready to log in?</a>
</div>
<div class="col-xs-5">
<button type="submit" class="btn btn-primary btn-block btn-flat" ng-disabled="recoverForm.$loading">
<i class="fa fa-refresh fa-spin loading-icon" ng-show="recoverForm.$loading"></i>Submit
</button>
</div>
</div>
</form>
</div>
</div>

View File

@@ -1,39 +0,0 @@
<div class="login-box">
<div class="login-logo">
<i class="fa fa-shield"></i> <b>bit</b>warden
</div>
<div class="login-box-body">
<p class="login-box-msg">Enter your email address below to recover &amp; delete your bitwarden account.</p>
<div ng-show="success" class="text-center">
<div class="callout callout-success">
If your account exists ({{model.email}}) we've sent you an email with further instructions.
</div>
<a ui-sref="frontend.login.info">Return to log in</a>
</div>
<form name="form" ng-submit="form.$valid && submit(model)" ng-show="!success"
api-form="submitPromise">
<div class="callout callout-danger validation-errors" ng-show="form.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in form.$errors">{{e}}</li>
</ul>
</div>
<div class="form-group has-feedback" show-errors>
<label for="email" class="sr-only">Your account email address</label>
<input type="email" id="email" name="Email" class="form-control" placeholder="Your account email address"
ng-model="model.email" required api-field />
<span class="fa fa-envelope form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-7">
<a ui-sref="frontend.login.info">Return to log in</a>
</div>
<div class="col-xs-5">
<button type="submit" class="btn btn-primary btn-block btn-flat" ng-disabled="form.$loading">
<i class="fa fa-refresh fa-spin loading-icon" ng-show="form.$loading"></i>Submit
</button>
</div>
</div>
</form>
</div>
</div>

View File

@@ -1,82 +0,0 @@
<div class="register-box">
<div class="register-logo">
<i class="fa fa-shield"></i> <b>bit</b>warden
</div>
<div class="register-box-body">
<p class="login-box-msg">Create a new account.</p>
<div class="text-center" ng-show="success">
<div class="callout callout-success">
<h4>Account Created!</h4>
<p>You may now log in to your new account.</p>
</div>
<a ui-sref="frontend.login.info({returnState: returnState, email: model.email})">Ready to log in?</a>
</div>
<form name="registerForm" ng-submit="registerForm.$valid && register(registerForm)" ng-show="!success"
api-form="registerPromise">
<div class="callout callout-default" ng-show="createOrg">
<h4>Create Organization, Step 1</h4>
<p>Before creating your organization, you first need to create a free personal account.</p>
</div>
<div class="callout callout-danger validation-errors" ng-show="registerForm.$errors">
<h4>Errors have occurred</h4>
<ul>
<li ng-repeat="e in registerForm.$errors">{{e}}</li>
</ul>
</div>
<div class="form-group has-feedback" show-errors>
<label for="email" class="sr-only">Email</label>
<input type="email" id="email" name="Email" class="form-control" placeholder="Email" ng-model="model.email"
ng-readonly="readOnlyEmail" required api-field />
<span class="fa fa-envelope form-control-feedback"></span>
<p class="help-block">You'll use your email address to log in.</p>
</div>
<div class="form-group has-feedback" show-errors>
<label for="name" class="sr-only">Your Name</label>
<input type="text" id="name" name="Name" class="form-control" ng-model="model.name"
placeholder="Your Name" api-field>
<span class="fa fa-user form-control-feedback"></span>
<p class="help-block">What should we call you?</p>
</div>
<div class="form-group has-feedback" show-errors>
<label for="masterPassword" class="sr-only">Master Password</label>
<input type="password" id="masterPassword" name="MasterPasswordHash" class="form-control"
ng-model="model.masterPassword" placeholder="Master Password" required api-field>
<span class="fa fa-lock form-control-feedback"></span>
<p class="help-block">The master password is the password you use to access your vault.</p>
</div>
<div class="form-group has-feedback" show-errors>
<label form="confirmMasterPassword" class="sr-only">Re-type Master Password</label>
<input type="password" id="confirmMasterPassword" name="ConfirmMasterPassword" class="form-control"
placeholder="Re-type Master Password"
ng-model="model.confirmMasterPassword" required api-field>
<span class="fa fa-lock form-control-feedback"></span>
<p class="help-block">
It is very important that you do not forget your master password.
There is <u>no way</u> to recover the password in the event that you forget it.
</p>
</div>
<div class="form-group has-feedback" show-errors>
<label for="hint" class="sr-only">Master Password Hint (optional)</label>
<input type="text" id="hint" name="MasterPasswordHint" class="form-control" ng-model="model.masterPasswordHint"
placeholder="Master Password Hint (optional)" api-field>
<span class="fa fa-lightbulb-o form-control-feedback"></span>
<p class="help-block">A master password hint can help you remember your password if you forget it.</p>
</div>
<div class="row">
<div class="col-xs-7">
<a ui-sref="frontend.login.info({returnState: returnState})">Already have an account?</a>
</div>
<div class="col-xs-5">
<button type="submit" class="btn btn-primary btn-block btn-flat" ng-disabled="registerForm.$loading">
<i class="fa fa-refresh fa-spin loading-icon" ng-show="registerForm.$loading"></i>Submit
</button>
</div>
</div>
<hr />
By clicking the above "Submit" button, you are agreeing to the
<a href="https://bitwarden.com/terms/" target="_blank">Terms of Service</a>
and the
<a href="https://bitwarden.com/privacy/" target="_blank">Privacy Policy</a>.
</form>
</div>
</div>

View File

@@ -1,25 +0,0 @@
<div class="modal-header">
<button type="button" class="close" ng-click="close()" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><i class="fa fa-key"></i> Two-step Providers</h4>
</div>
<div class="modal-body">
<div class="list-group" ng-repeat="provider in providers | orderBy: 'displayOrder'">
<a href="#" stop-click class="list-group-item" ng-click="choose(provider)">
<img alt="{{::provider.name}}" ng-src="{{'images/two-factor/' + provider.image}}" class="pull-right hidden-xs" />
<h4 class="list-group-item-heading">{{::provider.name}}</h4>
<p class="list-group-item-text">{{::provider.description}}</p>
</a>
</div>
<div class="list-group" style="margin-bottom: 0;">
<a href="https://help.bitwarden.com/article/lost-two-step-device/" target="_blank" class="list-group-item">
<h4 class="list-group-item-heading">Recovery Code</h4>
<p class="list-group-item-text">
Lost access to all of your two-factor providers? Use your recovery code to disable
all two-factor providers from your account.
</p>
</a>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-flat" ng-click="close()">Close</button>
</div>

View File

@@ -1,8 +0,0 @@
<div class="login-box">
<div class="login-logo">
<i class="fa fa-shield"></i> <b>bit</b>warden
</div>
<div class="login-box-body">
Verifying email...
</div>
</div>

View File

@@ -1,21 +0,0 @@
<div class="login-box">
<div class="login-logo">
<i class="fa fa-shield"></i> <b>bit</b>warden
</div>
<div class="login-box-body">
<div ng-if="deleting">
Deleting account...
</div>
<div ng-if="!deleting">
<div class="callout callout-warning">
<h4><i class="fa fa-warning fa-fw"></i> Warning</h4>
This will permanently delete your account. This cannot be undone.
</div>
<p>
You have requested to delete your bitwarden account (<b>{{email}}</b>).
Click the button below to confirm and proceed.
</p>
<button ng-click="delete()" class="btn btn-danger btn-block btn-flat">Delete Account</button>
</div>
</div>
</div>

View File

@@ -1,29 +0,0 @@
angular
.module('bit')
.factory('apiInterceptor', function ($injector, $q, toastr) {
return {
request: function (config) {
return config;
},
response: function (response) {
if (response.status === 401 || response.status === 403) {
$injector.get('authService').logOut();
$injector.get('$state').go('frontend.login.info').then(function () {
toastr.warning('Your login session has expired.', 'Logged out');
});
}
return response || $q.when(response);
},
responseError: function (rejection) {
if (rejection.status === 401 || rejection.status === 403) {
$injector.get('authService').logOut();
$injector.get('$state').go('frontend.login.info').then(function () {
toastr.warning('Your login session has expired.', 'Logged out');
});
}
return $q.reject(rejection);
}
};
});

View File

@@ -0,0 +1,304 @@
import { NgModule } from '@angular/core';
import {
RouterModule,
Routes,
} from '@angular/router';
import { FrontendLayoutComponent } from './layouts/frontend-layout.component';
import { OrganizationLayoutComponent } from './layouts/organization-layout.component';
import { UserLayoutComponent } from './layouts/user-layout.component';
import { AcceptOrganizationComponent } from './accounts/accept-organization.component';
import { HintComponent } from './accounts/hint.component';
import { LockComponent } from './accounts/lock.component';
import { LoginComponent } from './accounts/login.component';
import { RecoverDeleteComponent } from './accounts/recover-delete.component';
import { RecoverTwoFactorComponent } from './accounts/recover-two-factor.component';
import { RegisterComponent } from './accounts/register.component';
import { TwoFactorComponent } from './accounts/two-factor.component';
import { VerifyEmailTokenComponent } from './accounts/verify-email-token.component';
import { VerifyRecoverDeleteComponent } from './accounts/verify-recover-delete.component';
import { CollectionsComponent as OrgManageCollectionsComponent } from './organizations/manage/collections.component';
import { EventsComponent as OrgEventsComponent } from './organizations/manage/events.component';
import { GroupsComponent as OrgGroupsComponent } from './organizations/manage/groups.component';
import { ManageComponent as OrgManageComponent } from './organizations/manage/manage.component';
import { PeopleComponent as OrgPeopleComponent } from './organizations/manage/people.component';
import { PoliciesComponent as OrgPoliciesComponent } from './organizations/manage/policies.component';
import { AccountComponent as OrgAccountComponent } from './organizations/settings/account.component';
import { OrganizationBillingComponent } from './organizations/settings/organization-billing.component';
import { OrganizationSubscriptionComponent } from './organizations/settings/organization-subscription.component';
import { SettingsComponent as OrgSettingsComponent } from './organizations/settings/settings.component';
import {
TwoFactorSetupComponent as OrgTwoFactorSetupComponent,
} from './organizations/settings/two-factor-setup.component';
import { ExportComponent as OrgExportComponent } from './organizations/tools/export.component';
import {
ExposedPasswordsReportComponent as OrgExposedPasswordsReportComponent,
} from './organizations/tools/exposed-passwords-report.component';
import { ImportComponent as OrgImportComponent } from './organizations/tools/import.component';
import {
InactiveTwoFactorReportComponent as OrgInactiveTwoFactorReportComponent,
} from './organizations/tools/inactive-two-factor-report.component';
import {
ReusedPasswordsReportComponent as OrgReusedPasswordsReportComponent,
} from './organizations/tools/reused-passwords-report.component';
import { ToolsComponent as OrgToolsComponent } from './organizations/tools/tools.component';
import {
UnsecuredWebsitesReportComponent as OrgUnsecuredWebsitesReportComponent,
} from './organizations/tools/unsecured-websites-report.component';
import {
WeakPasswordsReportComponent as OrgWeakPasswordsReportComponent,
} from './organizations/tools/weak-passwords-report.component';
import { VaultComponent as OrgVaultComponent } from './organizations/vault/vault.component';
import { AccountComponent } from './settings/account.component';
import { CreateOrganizationComponent } from './settings/create-organization.component';
import { DomainRulesComponent } from './settings/domain-rules.component';
import { OptionsComponent } from './settings/options.component';
import { OrganizationsComponent } from './settings/organizations.component';
import { PremiumComponent } from './settings/premium.component';
import { SettingsComponent } from './settings/settings.component';
import { TwoFactorSetupComponent } from './settings/two-factor-setup.component';
import { UserBillingComponent } from './settings/user-billing.component';
import { UserSubscriptionComponent } from './settings/user-subscription.component';
import { BreachReportComponent } from './tools/breach-report.component';
import { ExportComponent } from './tools/export.component';
import { ExposedPasswordsReportComponent } from './tools/exposed-passwords-report.component';
import { ImportComponent } from './tools/import.component';
import { InactiveTwoFactorReportComponent } from './tools/inactive-two-factor-report.component';
import { PasswordGeneratorComponent } from './tools/password-generator.component';
import { ReusedPasswordsReportComponent } from './tools/reused-passwords-report.component';
import { ToolsComponent } from './tools/tools.component';
import { UnsecuredWebsitesReportComponent } from './tools/unsecured-websites-report.component';
import { WeakPasswordsReportComponent } from './tools/weak-passwords-report.component';
import { VaultComponent } from './vault/vault.component';
import { OrganizationGuardService } from './services/organization-guard.service';
import { OrganizationTypeGuardService } from './services/organization-type-guard.service';
import { UnauthGuardService } from './services/unauth-guard.service';
import { AuthGuardService } from 'jslib/angular/services/auth-guard.service';
import { OrganizationUserType } from 'jslib/enums/organizationUserType';
const routes: Routes = [
{
path: '',
component: FrontendLayoutComponent,
children: [
{ path: '', pathMatch: 'full', component: LoginComponent, canActivate: [UnauthGuardService] },
{ path: '2fa', component: TwoFactorComponent, canActivate: [UnauthGuardService] },
{
path: 'register', component: RegisterComponent,
canActivate: [UnauthGuardService],
data: { titleId: 'createAccount' },
},
{
path: 'hint', component: HintComponent,
canActivate: [UnauthGuardService],
data: { titleId: 'passwordHint' },
},
{ path: 'lock', component: LockComponent },
{ path: 'verify-email', component: VerifyEmailTokenComponent },
{
path: 'accept-organization',
component: AcceptOrganizationComponent,
data: { titleId: 'joinOrganization' },
},
{ path: 'recover', pathMatch: 'full', redirectTo: 'recover-2fa' },
{
path: 'recover-2fa',
component: RecoverTwoFactorComponent,
canActivate: [UnauthGuardService],
data: { titleId: 'recoverAccountTwoStep' },
},
{
path: 'recover-delete',
component: RecoverDeleteComponent,
canActivate: [UnauthGuardService],
data: { titleId: 'deleteAccount' },
},
{
path: 'verify-recover-delete',
component: VerifyRecoverDeleteComponent,
canActivate: [UnauthGuardService],
data: { titleId: 'deleteAccount' },
},
],
},
{
path: '',
component: UserLayoutComponent,
canActivate: [AuthGuardService],
children: [
{ path: 'vault', component: VaultComponent, data: { titleId: 'myVault' } },
{
path: 'settings',
component: SettingsComponent,
children: [
{ path: '', pathMatch: 'full', redirectTo: 'account' },
{ path: 'account', component: AccountComponent, data: { titleId: 'myAccount' } },
{ path: 'options', component: OptionsComponent, data: { titleId: 'options' } },
{ path: 'domain-rules', component: DomainRulesComponent, data: { titleId: 'domainRules' } },
{ path: 'two-factor', component: TwoFactorSetupComponent, data: { titleId: 'twoStepLogin' } },
{ path: 'premium', component: PremiumComponent, data: { titleId: 'goPremium' } },
{ path: 'billing', component: UserBillingComponent, data: { titleId: 'billing' } },
{
path: 'subscription',
component: UserSubscriptionComponent,
data: { titleId: 'premiumMembership' },
},
{ path: 'organizations', component: OrganizationsComponent, data: { titleId: 'organizations' } },
{
path: 'create-organization',
component: CreateOrganizationComponent,
data: { titleId: 'newOrganization' },
},
],
},
{
path: 'tools',
component: ToolsComponent,
canActivate: [AuthGuardService],
children: [
{ path: '', pathMatch: 'full', redirectTo: 'generator' },
{ path: 'import', component: ImportComponent, data: { titleId: 'importData' } },
{ path: 'export', component: ExportComponent, data: { titleId: 'exportVault' } },
{
path: 'generator',
component: PasswordGeneratorComponent,
data: { titleId: 'passwordGenerator' },
},
{ path: 'breach-report', component: BreachReportComponent, data: { titleId: 'dataBreachReport' } },
{
path: 'reused-passwords-report',
component: ReusedPasswordsReportComponent,
data: { titleId: 'reusedPasswordsReport' },
},
{
path: 'unsecured-websites-report',
component: UnsecuredWebsitesReportComponent,
data: { titleId: 'unsecuredWebsitesReport' },
},
{
path: 'weak-passwords-report',
component: WeakPasswordsReportComponent,
data: { titleId: 'weakPasswordsReport' },
},
{
path: 'exposed-passwords-report',
component: ExposedPasswordsReportComponent,
data: { titleId: 'exposedPasswordsReport' },
},
{
path: 'inactive-two-factor-report',
component: InactiveTwoFactorReportComponent,
data: { titleId: 'inactive2faReport' },
},
],
},
],
},
{
path: 'organizations/:organizationId',
component: OrganizationLayoutComponent,
canActivate: [AuthGuardService, OrganizationGuardService],
children: [
{ path: '', pathMatch: 'full', redirectTo: 'vault' },
{ path: 'vault', component: OrgVaultComponent, data: { titleId: 'vault' } },
{
path: 'tools',
component: OrgToolsComponent,
canActivate: [OrganizationTypeGuardService],
data: { allowedTypes: [OrganizationUserType.Owner, OrganizationUserType.Admin] },
children: [
{ path: '', pathMatch: 'full', redirectTo: 'import' },
{ path: 'import', component: OrgImportComponent, data: { titleId: 'importData' } },
{ path: 'export', component: OrgExportComponent, data: { titleId: 'exportVault' } },
{
path: 'exposed-passwords-report',
component: OrgExposedPasswordsReportComponent,
data: { titleId: 'exposedPasswordsReport' },
},
{
path: 'inactive-two-factor-report',
component: OrgInactiveTwoFactorReportComponent,
data: { titleId: 'inactive2faReport' },
},
{
path: 'reused-passwords-report',
component: OrgReusedPasswordsReportComponent,
data: { titleId: 'reusedPasswordsReport' },
},
{
path: 'unsecured-websites-report',
component: OrgUnsecuredWebsitesReportComponent,
data: { titleId: 'unsecuredWebsitesReport' },
},
{
path: 'weak-passwords-report',
component: OrgWeakPasswordsReportComponent,
data: { titleId: 'weakPasswordsReport' },
},
],
},
{
path: 'manage',
component: OrgManageComponent,
canActivate: [OrganizationTypeGuardService],
data: {
allowedTypes: [
OrganizationUserType.Owner,
OrganizationUserType.Admin,
OrganizationUserType.Manager,
],
},
children: [
{ path: '', pathMatch: 'full', redirectTo: 'people' },
{ path: 'collections', component: OrgManageCollectionsComponent, data: { titleId: 'collections' } },
{ path: 'events', component: OrgEventsComponent, data: { titleId: 'eventLogs' } },
{ path: 'groups', component: OrgGroupsComponent, data: { titleId: 'groups' } },
{ path: 'people', component: OrgPeopleComponent, data: { titleId: 'people' } },
{ path: 'policies', component: OrgPoliciesComponent, data: { titleId: 'policies' } },
],
},
{
path: 'settings',
component: OrgSettingsComponent,
canActivate: [OrganizationTypeGuardService],
data: { allowedTypes: [OrganizationUserType.Owner] },
children: [
{ path: '', pathMatch: 'full', redirectTo: 'account' },
{ path: 'account', component: OrgAccountComponent, data: { titleId: 'myOrganization' } },
{ path: 'two-factor', component: OrgTwoFactorSetupComponent, data: { titleId: 'twoStepLogin' } },
{
path: 'billing',
component: OrganizationBillingComponent,
data: { titleId: 'billing' },
},
{
path: 'subscription',
component: OrganizationSubscriptionComponent,
data: { titleId: 'subscription' },
},
],
},
],
},
{ path: '**', redirectTo: '' },
];
@NgModule({
imports: [RouterModule.forRoot(routes, {
useHash: true,
/*enableTracing: true,*/
})],
exports: [RouterModule],
})
export class AppRoutingModule { }

View File

@@ -0,0 +1,2 @@
<toaster-container [toasterconfig]="toasterConfig" aria-live="polite"></toaster-container>
<router-outlet></router-outlet>

265
src/app/app.component.ts Normal file
View File

@@ -0,0 +1,265 @@
import * as jq from 'jquery';
import Swal from 'sweetalert2/src/sweetalert2.js';
import {
BodyOutputType,
Toast,
ToasterConfig,
ToasterContainerComponent,
ToasterService,
} from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
import {
Component,
NgZone,
OnDestroy,
OnInit,
SecurityContext,
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import {
NavigationEnd,
Router,
} from '@angular/router';
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { AuthService } from 'jslib/abstractions/auth.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { CollectionService } from 'jslib/abstractions/collection.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { EventService } from 'jslib/abstractions/event.service';
import { FolderService } from 'jslib/abstractions/folder.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LockService } from 'jslib/abstractions/lock.service';
import { NotificationsService } from 'jslib/abstractions/notifications.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { SearchService } from 'jslib/abstractions/search.service';
import { SettingsService } from 'jslib/abstractions/settings.service';
import { StateService } from 'jslib/abstractions/state.service';
import { SyncService } from 'jslib/abstractions/sync.service';
import { TokenService } from 'jslib/abstractions/token.service';
import { UserService } from 'jslib/abstractions/user.service';
import { ConstantsService } from 'jslib/services/constants.service';
import { RouterService } from './services/router.service';
const BroadcasterSubscriptionId = 'AppComponent';
const IdleTimeout = 60000 * 10; // 10 minutes
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
})
export class AppComponent implements OnDestroy, OnInit {
toasterConfig: ToasterConfig = new ToasterConfig({
showCloseButton: true,
mouseoverTimerStop: true,
animation: 'flyRight',
limit: 5,
});
private lastActivity: number = null;
private idleTimer: number = null;
private isIdle = false;
constructor(private angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics,
private broadcasterService: BroadcasterService, private userService: UserService,
private tokenService: TokenService, private folderService: FolderService,
private settingsService: SettingsService, private syncService: SyncService,
private passwordGenerationService: PasswordGenerationService, private cipherService: CipherService,
private authService: AuthService, private router: Router, private analytics: Angulartics2,
private toasterService: ToasterService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private ngZone: NgZone,
private lockService: LockService, private storageService: StorageService,
private cryptoService: CryptoService, private collectionService: CollectionService,
private sanitizer: DomSanitizer, private searchService: SearchService,
private notificationsService: NotificationsService, private routerService: RouterService,
private stateService: StateService, private eventService: EventService,
private policyService: PolicyService) { }
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
window.onmousemove = () => this.recordActivity();
window.onmousedown = () => this.recordActivity();
window.ontouchstart = () => this.recordActivity();
window.onclick = () => this.recordActivity();
window.onscroll = () => this.recordActivity();
window.onkeypress = () => this.recordActivity();
});
this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => {
this.ngZone.run(async () => {
switch (message.command) {
case 'loggedIn':
case 'loggedOut':
case 'unlocked':
this.notificationsService.updateConnection(false);
break;
case 'authBlocked':
this.router.navigate(['/']);
break;
case 'logout':
this.logOut(!!message.expired);
break;
case 'lockVault':
await this.lockService.lock();
break;
case 'locked':
this.notificationsService.updateConnection(false);
this.router.navigate(['lock']);
break;
case 'lockedUrl':
window.setTimeout(() => this.routerService.setPreviousUrl(message.url), 500);
break;
case 'syncStarted':
break;
case 'syncCompleted':
break;
case 'upgradeOrganization':
const upgradeConfirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('upgradeOrganizationDesc'), this.i18nService.t('upgradeOrganization'),
this.i18nService.t('upgradeOrganization'), this.i18nService.t('cancel'));
if (upgradeConfirmed) {
this.router.navigate(['organizations', message.organizationId, 'settings', 'billing']);
}
break;
case 'premiumRequired':
const premiumConfirmed = await this.platformUtilsService.showDialog(
this.i18nService.t('premiumRequiredDesc'), this.i18nService.t('premiumRequired'),
this.i18nService.t('learnMore'), this.i18nService.t('cancel'));
if (premiumConfirmed) {
this.router.navigate(['settings/premium']);
}
break;
case 'showToast':
this.showToast(message);
break;
case 'analyticsEventTrack':
this.analytics.eventTrack.next({
action: message.action,
properties: { label: message.label },
});
break;
default:
break;
}
});
});
this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
const modals = Array.from(document.querySelectorAll('.modal'));
for (const modal of modals) {
(jq(modal) as any).modal('hide');
}
if (document.querySelector('.swal-modal') != null) {
Swal.close(undefined);
}
}
});
}
ngOnDestroy() {
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
}
private async logOut(expired: boolean) {
await this.eventService.uploadEvents();
const userId = await this.userService.getUserId();
await Promise.all([
this.eventService.clearEvents(),
this.syncService.setLastSync(new Date(0)),
this.tokenService.clearToken(),
this.cryptoService.clearKeys(),
this.userService.clear(),
this.settingsService.clear(userId),
this.cipherService.clear(userId),
this.folderService.clear(userId),
this.collectionService.clear(userId),
this.policyService.clear(userId),
this.passwordGenerationService.clear(),
this.stateService.purge(),
]);
this.searchService.clearIndex();
this.authService.logOut(async () => {
this.analytics.eventTrack.next({ action: 'Logged Out' });
if (expired) {
this.toasterService.popAsync('warning', this.i18nService.t('loggedOut'),
this.i18nService.t('loginExpired'));
}
this.router.navigate(['/']);
});
}
private async recordActivity() {
const now = (new Date()).getTime();
if (this.lastActivity != null && now - this.lastActivity < 250) {
return;
}
this.lastActivity = now;
this.storageService.save(ConstantsService.lastActiveKey, now);
// Idle states
if (this.isIdle) {
this.isIdle = false;
this.idleStateChanged();
}
if (this.idleTimer != null) {
window.clearTimeout(this.idleTimer);
this.idleTimer = null;
}
this.idleTimer = window.setTimeout(() => {
if (!this.isIdle) {
this.isIdle = true;
this.idleStateChanged();
}
}, IdleTimeout);
}
private showToast(msg: any) {
const toast: Toast = {
type: msg.type,
title: msg.title,
};
if (typeof (msg.text) === 'string') {
toast.body = msg.text;
} else if (msg.text.length === 1) {
toast.body = msg.text[0];
} else {
let message = '';
msg.text.forEach((t: string) =>
message += ('<p>' + this.sanitizer.sanitize(SecurityContext.HTML, t) + '</p>'));
toast.body = message;
toast.bodyOutputType = BodyOutputType.TrustedHtml;
}
if (msg.options != null) {
if (msg.options.trustedHtml === true) {
toast.bodyOutputType = BodyOutputType.TrustedHtml;
}
if (msg.options.timeout != null && msg.options.timeout > 0) {
toast.timeout = msg.options.timeout;
}
}
this.toasterService.popAsync(toast);
}
private idleStateChanged() {
if (this.isIdle) {
this.notificationsService.disconnectFromInactivity();
} else {
this.notificationsService.reconnectFromActivity();
}
}
}

View File

@@ -1,27 +0,0 @@
angular
.module('bit', [
'ui.router',
'ngMessages',
'angular-jwt',
'ui.bootstrap.showErrors',
'toastr',
'angulartics',
// @if !selfHosted
'angulartics.google.analytics',
'angular-stripe',
'credit-cards',
// @endif
'angular-promise-polyfill',
'bit.directives',
'bit.filters',
'bit.services',
'bit.global',
'bit.accounts',
'bit.vault',
'bit.settings',
'bit.tools',
'bit.organization',
'bit.reports'
]);

413
src/app/app.module.ts Normal file
View File

@@ -0,0 +1,413 @@
import 'core-js';
import { ToasterModule } from 'angular2-toaster';
import { Angulartics2Module } from 'angulartics2';
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { AppRoutingModule } from './app-routing.module';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ServicesModule } from './services/services.module';
import { AppComponent } from './app.component';
import { ModalComponent } from './modal.component';
import { AvatarComponent } from './components/avatar.component';
import { PasswordStrengthComponent } from './components/password-strength.component';
import { FooterComponent } from './layouts/footer.component';
import { FrontendLayoutComponent } from './layouts/frontend-layout.component';
import { NavbarComponent } from './layouts/navbar.component';
import { OrganizationLayoutComponent } from './layouts/organization-layout.component';
import { UserLayoutComponent } from './layouts/user-layout.component';
import { AcceptOrganizationComponent } from './accounts/accept-organization.component';
import { HintComponent } from './accounts/hint.component';
import { LockComponent } from './accounts/lock.component';
import { LoginComponent } from './accounts/login.component';
import { RecoverDeleteComponent } from './accounts/recover-delete.component';
import { RecoverTwoFactorComponent } from './accounts/recover-two-factor.component';
import { RegisterComponent } from './accounts/register.component';
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
import { TwoFactorComponent } from './accounts/two-factor.component';
import { VerifyEmailTokenComponent } from './accounts/verify-email-token.component';
import { VerifyRecoverDeleteComponent } from './accounts/verify-recover-delete.component';
import {
CollectionAddEditComponent as OrgCollectionAddEditComponent,
} from './organizations/manage/collection-add-edit.component';
import { CollectionsComponent as OrgManageCollectionsComponent } from './organizations/manage/collections.component';
import { EntityEventsComponent as OrgEntityEventsComponent } from './organizations/manage/entity-events.component';
import { EntityUsersComponent as OrgEntityUsersComponent } from './organizations/manage/entity-users.component';
import { EventsComponent as OrgEventsComponent } from './organizations/manage/events.component';
import { GroupAddEditComponent as OrgGroupAddEditComponent } from './organizations/manage/group-add-edit.component';
import { GroupsComponent as OrgGroupsComponent } from './organizations/manage/groups.component';
import { ManageComponent as OrgManageComponent } from './organizations/manage/manage.component';
import { PeopleComponent as OrgPeopleComponent } from './organizations/manage/people.component';
import { PoliciesComponent as OrgPoliciesComponent } from './organizations/manage/policies.component';
import { PolicyEditComponent as OrgPolicyEditComponent } from './organizations/manage/policy-edit.component';
import { UserAddEditComponent as OrgUserAddEditComponent } from './organizations/manage/user-add-edit.component';
import { UserConfirmComponent as OrgUserConfirmComponent } from './organizations/manage/user-confirm.component';
import { UserGroupsComponent as OrgUserGroupsComponent } from './organizations/manage/user-groups.component';
import { AccountComponent as OrgAccountComponent } from './organizations/settings/account.component';
import { AdjustSeatsComponent } from './organizations/settings/adjust-seats.component';
import { ApiKeyComponent as OrgApiKeyComponent } from './organizations/settings/api-key.component';
import { ChangePlanComponent } from './organizations/settings/change-plan.component';
import { DeleteOrganizationComponent } from './organizations/settings/delete-organization.component';
import { DownloadLicenseComponent } from './organizations/settings/download-license.component';
import { OrganizationBillingComponent } from './organizations/settings/organization-billing.component';
import { OrganizationSubscriptionComponent } from './organizations/settings/organization-subscription.component';
import { RotateApiKeyComponent as OrgRotateApiKeyComponent } from './organizations/settings/rotate-api-key.component';
import { SettingsComponent as OrgSettingComponent } from './organizations/settings/settings.component';
import {
TwoFactorSetupComponent as OrgTwoFactorSetupComponent,
} from './organizations/settings/two-factor-setup.component';
import { ExportComponent as OrgExportComponent } from './organizations/tools/export.component';
import {
ExposedPasswordsReportComponent as OrgExposedPasswordsReportComponent,
} from './organizations/tools/exposed-passwords-report.component';
import { ImportComponent as OrgImportComponent } from './organizations/tools/import.component';
import {
InactiveTwoFactorReportComponent as OrgInactiveTwoFactorReportComponent,
} from './organizations/tools/inactive-two-factor-report.component';
import {
ReusedPasswordsReportComponent as OrgReusedPasswordsReportComponent,
} from './organizations/tools/reused-passwords-report.component';
import { ToolsComponent as OrgToolsComponent } from './organizations/tools/tools.component';
import {
UnsecuredWebsitesReportComponent as OrgUnsecuredWebsitesReportComponent,
} from './organizations/tools/unsecured-websites-report.component';
import {
WeakPasswordsReportComponent as OrgWeakPasswordsReportComponent,
} from './organizations/tools/weak-passwords-report.component';
import { AddEditComponent as OrgAddEditComponent } from './organizations/vault/add-edit.component';
import { AttachmentsComponent as OrgAttachmentsComponent } from './organizations/vault/attachments.component';
import { CiphersComponent as OrgCiphersComponent } from './organizations/vault/ciphers.component';
import { CollectionsComponent as OrgCollectionsComponent } from './organizations/vault/collections.component';
import { GroupingsComponent as OrgGroupingsComponent } from './organizations/vault/groupings.component';
import { VaultComponent as OrgVaultComponent } from './organizations/vault/vault.component';
import { AccountComponent } from './settings/account.component';
import { AddCreditComponent } from './settings/add-credit.component';
import { AdjustPaymentComponent } from './settings/adjust-payment.component';
import { AdjustStorageComponent } from './settings/adjust-storage.component';
import { ChangeEmailComponent } from './settings/change-email.component';
import { ChangeKdfComponent } from './settings/change-kdf.component';
import { ChangePasswordComponent } from './settings/change-password.component';
import { CreateOrganizationComponent } from './settings/create-organization.component';
import { DeauthorizeSessionsComponent } from './settings/deauthorize-sessions.component';
import { DeleteAccountComponent } from './settings/delete-account.component';
import { DomainRulesComponent } from './settings/domain-rules.component';
import { OptionsComponent } from './settings/options.component';
import { OrganizationPlansComponent } from './settings/organization-plans.component';
import { OrganizationsComponent } from './settings/organizations.component';
import { PaymentComponent } from './settings/payment.component';
import { PremiumComponent } from './settings/premium.component';
import { ProfileComponent } from './settings/profile.component';
import { PurgeVaultComponent } from './settings/purge-vault.component';
import { SettingsComponent } from './settings/settings.component';
import { TwoFactorAuthenticatorComponent } from './settings/two-factor-authenticator.component';
import { TwoFactorDuoComponent } from './settings/two-factor-duo.component';
import { TwoFactorEmailComponent } from './settings/two-factor-email.component';
import { TwoFactorRecoveryComponent } from './settings/two-factor-recovery.component';
import { TwoFactorSetupComponent } from './settings/two-factor-setup.component';
import { TwoFactorU2fComponent } from './settings/two-factor-u2f.component';
import { TwoFactorVerifyComponent } from './settings/two-factor-verify.component';
import { TwoFactorYubiKeyComponent } from './settings/two-factor-yubikey.component';
import { UpdateKeyComponent } from './settings/update-key.component';
import { UpdateLicenseComponent } from './settings/update-license.component';
import { UserBillingComponent } from './settings/user-billing.component';
import { UserSubscriptionComponent } from './settings/user-subscription.component';
import { VerifyEmailComponent } from './settings/verify-email.component';
import { BreachReportComponent } from './tools/breach-report.component';
import { ExportComponent } from './tools/export.component';
import { ExposedPasswordsReportComponent } from './tools/exposed-passwords-report.component';
import { ImportComponent } from './tools/import.component';
import { InactiveTwoFactorReportComponent } from './tools/inactive-two-factor-report.component';
import { PasswordGeneratorHistoryComponent } from './tools/password-generator-history.component';
import { PasswordGeneratorComponent } from './tools/password-generator.component';
import { ReusedPasswordsReportComponent } from './tools/reused-passwords-report.component';
import { ToolsComponent } from './tools/tools.component';
import { UnsecuredWebsitesReportComponent } from './tools/unsecured-websites-report.component';
import { WeakPasswordsReportComponent } from './tools/weak-passwords-report.component';
import { AddEditComponent } from './vault/add-edit.component';
import { AttachmentsComponent } from './vault/attachments.component';
import { BulkDeleteComponent } from './vault/bulk-delete.component';
import { BulkMoveComponent } from './vault/bulk-move.component';
import { BulkShareComponent } from './vault/bulk-share.component';
import { CiphersComponent } from './vault/ciphers.component';
import { CollectionsComponent } from './vault/collections.component';
import { FolderAddEditComponent } from './vault/folder-add-edit.component';
import { GroupingsComponent } from './vault/groupings.component';
import { ShareComponent } from './vault/share.component';
import { VaultComponent } from './vault/vault.component';
import { CalloutComponent } from 'jslib/angular/components/callout.component';
import { IconComponent } from 'jslib/angular/components/icon.component';
import { A11yTitleDirective } from 'jslib/angular/directives/a11y-title.directive';
import { ApiActionDirective } from 'jslib/angular/directives/api-action.directive';
import { AutofocusDirective } from 'jslib/angular/directives/autofocus.directive';
import { BlurClickDirective } from 'jslib/angular/directives/blur-click.directive';
import { BoxRowDirective } from 'jslib/angular/directives/box-row.directive';
import { FallbackSrcDirective } from 'jslib/angular/directives/fallback-src.directive';
import { InputVerbatimDirective } from 'jslib/angular/directives/input-verbatim.directive';
import { SelectCopyDirective } from 'jslib/angular/directives/select-copy.directive';
import { StopClickDirective } from 'jslib/angular/directives/stop-click.directive';
import { StopPropDirective } from 'jslib/angular/directives/stop-prop.directive';
import { TrueFalseValueDirective } from 'jslib/angular/directives/true-false-value.directive';
import { ColorPasswordPipe } from 'jslib/angular/pipes/color-password.pipe';
import { I18nPipe } from 'jslib/angular/pipes/i18n.pipe';
import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
import { SearchPipe } from 'jslib/angular/pipes/search.pipe';
import { registerLocaleData } from '@angular/common';
import localeCa from '@angular/common/locales/ca';
import localeCs from '@angular/common/locales/cs';
import localeDa from '@angular/common/locales/da';
import localeDe from '@angular/common/locales/de';
import localeEnGb from '@angular/common/locales/en-GB';
import localeEs from '@angular/common/locales/es';
import localeEt from '@angular/common/locales/et';
import localeFr from '@angular/common/locales/fr';
import localeHe from '@angular/common/locales/he';
import localeIt from '@angular/common/locales/it';
import localeJa from '@angular/common/locales/ja';
import localeKo from '@angular/common/locales/ko';
import localeNb from '@angular/common/locales/nb';
import localeNl from '@angular/common/locales/nl';
import localePl from '@angular/common/locales/pl';
import localePtBr from '@angular/common/locales/pt';
import localePtPt from '@angular/common/locales/pt-PT';
import localeRu from '@angular/common/locales/ru';
import localeSk from '@angular/common/locales/sk';
import localeSv from '@angular/common/locales/sv';
import localeUk from '@angular/common/locales/uk';
import localeZhCn from '@angular/common/locales/zh-Hans';
import localeZhTw from '@angular/common/locales/zh-Hant';
registerLocaleData(localeCa, 'ca');
registerLocaleData(localeCs, 'cs');
registerLocaleData(localeDa, 'da');
registerLocaleData(localeDe, 'de');
registerLocaleData(localeEnGb, 'en-GB');
registerLocaleData(localeEs, 'es');
registerLocaleData(localeEt, 'et');
registerLocaleData(localeFr, 'fr');
registerLocaleData(localeHe, 'he');
registerLocaleData(localeIt, 'it');
registerLocaleData(localeJa, 'ja');
registerLocaleData(localeKo, 'ko');
registerLocaleData(localeNb, 'nb');
registerLocaleData(localeNl, 'nl');
registerLocaleData(localePl, 'pl');
registerLocaleData(localePtBr, 'pt-BR');
registerLocaleData(localePtPt, 'pt-PT');
registerLocaleData(localeRu, 'ru');
registerLocaleData(localeSk, 'sk');
registerLocaleData(localeSv, 'sv');
registerLocaleData(localeUk, 'uk');
registerLocaleData(localeZhCn, 'zh-CN');
registerLocaleData(localeZhTw, 'zh-TW');
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
AppRoutingModule,
ServicesModule,
Angulartics2Module.forRoot([Angulartics2GoogleAnalytics], {
pageTracking: {
clearQueryParams: true,
},
}),
ToasterModule.forRoot(),
InfiniteScrollModule,
DragDropModule,
],
declarations: [
A11yTitleDirective,
AcceptOrganizationComponent,
AccountComponent,
AddCreditComponent,
AddEditComponent,
AdjustPaymentComponent,
AdjustSeatsComponent,
AdjustStorageComponent,
ApiActionDirective,
AppComponent,
AttachmentsComponent,
AutofocusDirective,
AvatarComponent,
BlurClickDirective,
BoxRowDirective,
BreachReportComponent,
BulkDeleteComponent,
BulkMoveComponent,
BulkShareComponent,
CalloutComponent,
ChangeEmailComponent,
ChangeKdfComponent,
ChangePasswordComponent,
ChangePlanComponent,
CiphersComponent,
CollectionsComponent,
ColorPasswordPipe,
CreateOrganizationComponent,
DeauthorizeSessionsComponent,
DeleteAccountComponent,
DeleteOrganizationComponent,
DomainRulesComponent,
DownloadLicenseComponent,
ExportComponent,
ExposedPasswordsReportComponent,
FallbackSrcDirective,
FolderAddEditComponent,
FooterComponent,
FrontendLayoutComponent,
GroupingsComponent,
HintComponent,
I18nPipe,
IconComponent,
ImportComponent,
InactiveTwoFactorReportComponent,
InputVerbatimDirective,
LockComponent,
LoginComponent,
ModalComponent,
NavbarComponent,
OptionsComponent,
OrgAccountComponent,
OrgAddEditComponent,
OrgApiKeyComponent,
OrganizationBillingComponent,
OrganizationPlansComponent,
OrganizationSubscriptionComponent,
OrgAttachmentsComponent,
OrgCiphersComponent,
OrgCollectionAddEditComponent,
OrgCollectionsComponent,
OrgEntityEventsComponent,
OrgEntityUsersComponent,
OrgEventsComponent,
OrgExportComponent,
OrgExposedPasswordsReportComponent,
OrgImportComponent,
OrgInactiveTwoFactorReportComponent,
OrgGroupAddEditComponent,
OrgGroupingsComponent,
OrgGroupsComponent,
OrgManageCollectionsComponent,
OrgManageComponent,
OrgPeopleComponent,
OrgPolicyEditComponent,
OrgPoliciesComponent,
OrgReusedPasswordsReportComponent,
OrgRotateApiKeyComponent,
OrgSettingComponent,
OrgToolsComponent,
OrgTwoFactorSetupComponent,
OrgUserAddEditComponent,
OrgUserConfirmComponent,
OrgUserGroupsComponent,
OrganizationsComponent,
OrganizationLayoutComponent,
OrgUnsecuredWebsitesReportComponent,
OrgVaultComponent,
OrgWeakPasswordsReportComponent,
PasswordGeneratorComponent,
PasswordGeneratorHistoryComponent,
PasswordStrengthComponent,
PaymentComponent,
PremiumComponent,
ProfileComponent,
PurgeVaultComponent,
RecoverDeleteComponent,
RecoverTwoFactorComponent,
RegisterComponent,
ReusedPasswordsReportComponent,
SearchCiphersPipe,
SearchPipe,
SelectCopyDirective,
SettingsComponent,
ShareComponent,
StopClickDirective,
StopPropDirective,
ToolsComponent,
TrueFalseValueDirective,
TwoFactorAuthenticatorComponent,
TwoFactorComponent,
TwoFactorDuoComponent,
TwoFactorEmailComponent,
TwoFactorOptionsComponent,
TwoFactorRecoveryComponent,
TwoFactorSetupComponent,
TwoFactorU2fComponent,
TwoFactorVerifyComponent,
TwoFactorYubiKeyComponent,
UnsecuredWebsitesReportComponent,
UpdateKeyComponent,
UpdateLicenseComponent,
UserBillingComponent,
UserLayoutComponent,
UserSubscriptionComponent,
VaultComponent,
VerifyEmailComponent,
VerifyEmailTokenComponent,
VerifyRecoverDeleteComponent,
WeakPasswordsReportComponent,
],
entryComponents: [
AddEditComponent,
AttachmentsComponent,
BulkDeleteComponent,
BulkMoveComponent,
BulkShareComponent,
CollectionsComponent,
DeauthorizeSessionsComponent,
DeleteAccountComponent,
DeleteOrganizationComponent,
FolderAddEditComponent,
ModalComponent,
OrgAddEditComponent,
OrgApiKeyComponent,
OrgAttachmentsComponent,
OrgCollectionAddEditComponent,
OrgCollectionsComponent,
OrgEntityEventsComponent,
OrgEntityUsersComponent,
OrgGroupAddEditComponent,
OrgPolicyEditComponent,
OrgRotateApiKeyComponent,
OrgUserAddEditComponent,
OrgUserConfirmComponent,
OrgUserGroupsComponent,
PasswordGeneratorHistoryComponent,
PurgeVaultComponent,
ShareComponent,
TwoFactorAuthenticatorComponent,
TwoFactorDuoComponent,
TwoFactorEmailComponent,
TwoFactorOptionsComponent,
TwoFactorRecoveryComponent,
TwoFactorU2fComponent,
TwoFactorYubiKeyComponent,
UpdateKeyComponent,
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule { }

View File

@@ -0,0 +1,128 @@
import {
Component,
Input,
OnChanges,
OnInit,
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
import { StateService } from 'jslib/abstractions/state.service';
import { Utils } from 'jslib/misc/utils';
@Component({
selector: 'app-avatar',
template: '<img [src]="sanitizer.bypassSecurityTrustResourceUrl(src)" title="{{data}}" ' +
'[ngClass]="{\'rounded-circle\': circle}">',
})
export class AvatarComponent implements OnChanges, OnInit {
@Input() data: string;
@Input() email: string;
@Input() size = 45;
@Input() charCount = 2;
@Input() textColor = '#ffffff';
@Input() fontSize = 20;
@Input() fontWeight = 300;
@Input() dynamic = false;
@Input() circle = false;
src: string;
constructor(public sanitizer: DomSanitizer, private cryptoFunctionService: CryptoFunctionService,
private stateService: StateService) { }
ngOnInit() {
if (!this.dynamic) {
this.generate();
}
}
ngOnChanges() {
if (this.dynamic) {
this.generate();
}
}
private async generate() {
const enableGravatars = await this.stateService.get<boolean>('enableGravatars');
if (enableGravatars && this.email != null) {
const hashBytes = await this.cryptoFunctionService.hash(this.email.toLowerCase().trim(), 'md5');
const hash = Utils.fromBufferToHex(hashBytes).toLowerCase();
this.src = 'https://www.gravatar.com/avatar/' + hash + '?s=' + this.size + '&r=pg&d=retro';
} else {
let chars: string = null;
const upperData = this.data.toUpperCase();
if (this.charCount > 1) {
chars = this.getFirstLetters(upperData, this.charCount);
}
if (chars == null) {
chars = upperData.substr(0, this.charCount);
}
const charObj = this.getCharText(chars);
const color = this.stringToColor(upperData);
const svg = this.getSvg(this.size, color);
svg.appendChild(charObj);
const html = window.document.createElement('div').appendChild(svg).outerHTML;
const svgHtml = window.btoa(unescape(encodeURIComponent(html)));
this.src = 'data:image/svg+xml;base64,' + svgHtml;
}
}
private stringToColor(str: string): string {
let hash = 0;
for (let i = 0; i < str.length; i++) {
// tslint:disable-next-line
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
let color = '#';
for (let i = 0; i < 3; i++) {
// tslint:disable-next-line
const value = (hash >> (i * 8)) & 0xFF;
color += ('00' + value.toString(16)).substr(-2);
}
return color;
}
private getFirstLetters(data: string, count: number): string {
const parts = data.split(' ');
if (parts.length > 1) {
let text = '';
for (let i = 0; i < count; i++) {
text += parts[i].substr(0, 1);
}
return text;
}
return null;
}
private getSvg(size: number, color: string): HTMLElement {
const svgTag = window.document.createElement('svg');
svgTag.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
svgTag.setAttribute('pointer-events', 'none');
svgTag.setAttribute('width', size.toString());
svgTag.setAttribute('height', size.toString());
svgTag.style.backgroundColor = color;
svgTag.style.width = size + 'px';
svgTag.style.height = size + 'px';
return svgTag;
}
private getCharText(character: string): HTMLElement {
const textTag = window.document.createElement('text');
textTag.setAttribute('text-anchor', 'middle');
textTag.setAttribute('y', '50%');
textTag.setAttribute('x', '50%');
textTag.setAttribute('dy', '0.35em');
textTag.setAttribute('pointer-events', 'auto');
textTag.setAttribute('fill', this.textColor);
textTag.setAttribute('font-family', '"Open Sans","Helvetica Neue",Helvetica,Arial,' +
'sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"');
textTag.textContent = character;
textTag.style.fontWeight = this.fontWeight.toString();
textTag.style.fontSize = this.fontSize + 'px';
return textTag;
}
}

View File

@@ -0,0 +1,8 @@
<div class="progress">
<div class="progress-bar {{color}}" role="progressbar" [ngStyle]="{width: (scoreWidth + '%')}"
attr.aria-valuenow="{{scoreWidth}}" aria-valuemin="0" aria-valuemax="100">
<ng-container *ngIf="showText && text">
{{text}}
</ng-container>
</div>
</div>

View File

@@ -0,0 +1,44 @@
import {
Component,
Input,
OnChanges,
} from '@angular/core';
import { I18nService } from 'jslib/abstractions/i18n.service';
@Component({
selector: 'app-password-strength',
templateUrl: 'password-strength.component.html',
})
export class PasswordStrengthComponent implements OnChanges {
@Input() score?: number;
@Input() showText = false;
scoreWidth = 0;
color = 'bg-danger';
text: string;
constructor(private i18nService: I18nService) { }
ngOnChanges(): void {
this.scoreWidth = this.score == null ? 0 : (this.score + 1) * 20;
switch (this.score) {
case 4:
this.color = 'bg-success';
this.text = this.i18nService.t('strong');
break;
case 3:
this.color = 'bg-primary';
this.text = this.i18nService.t('good');
break;
case 2:
this.color = 'bg-warning';
this.text = this.i18nService.t('weak');
break;
default:
this.color = 'bg-danger';
this.text = this.score != null ? this.i18nService.t('weak') : null;
break;
}
}
}

View File

@@ -1,390 +0,0 @@
angular
.module('bit')
.config(function ($stateProvider, $urlRouterProvider, $httpProvider, jwtInterceptorProvider, jwtOptionsProvider,
$uibTooltipProvider, toastrConfig, $locationProvider, $qProvider, appSettings
// @if !selfHosted
/* jshint ignore:start */
, stripeProvider
/* jshint ignore:end */
// @endif
) {
angular.extend(appSettings, window.bitwardenAppSettings);
$qProvider.errorOnUnhandledRejections(false);
$locationProvider.hashPrefix('');
var jwtConfig = {
whiteListedDomains: appSettings.whitelistDomains
};
if (!appSettings.selfHosted) {
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf('safari') > -1 && userAgent.indexOf('chrome') === -1) {
// Safari doesn't work with unconventional "Content-Language" header for CORS.
// See notes here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
jwtConfig.urlParam = 'access_token';
}
else {
// Using Content-Language header since it is unused and is a CORS-safelisted header. This avoids pre-flights.
jwtConfig.authHeader = 'Content-Language';
}
}
jwtOptionsProvider.config(jwtConfig);
var refreshPromise;
jwtInterceptorProvider.tokenGetter = /*@ngInject*/ function (options, tokenService, authService) {
if (options.url.indexOf(appSettings.apiUri) !== 0) {
return;
}
if (refreshPromise) {
return refreshPromise;
}
var token = tokenService.getToken();
if (!token) {
return;
}
if (!tokenService.tokenNeedsRefresh(token)) {
return token;
}
var p = authService.refreshAccessToken();
if (!p) {
return;
}
refreshPromise = p.then(function (newToken) {
refreshPromise = null;
return newToken || token;
});
return refreshPromise;
};
// @if !selfHosted
stripeProvider.setPublishableKey(appSettings.stripeKey);
// @endif
angular.extend(toastrConfig, {
closeButton: true,
progressBar: true,
showMethod: 'slideDown',
target: '.toast-target'
});
$uibTooltipProvider.options({
popupDelay: 600,
appendToBody: true
});
if ($httpProvider.defaults.headers.post) {
$httpProvider.defaults.headers.post = {};
}
$httpProvider.defaults.headers.post['Content-Type'] = 'text/plain; charset=utf-8';
// stop IE from caching get requests
if (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0) {
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
$httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
$httpProvider.defaults.headers.get.Pragma = 'no-cache';
}
$httpProvider.interceptors.push('apiInterceptor');
$httpProvider.interceptors.push('jwtInterceptor');
$urlRouterProvider.otherwise('/');
$stateProvider
// Backend
.state('backend', {
templateUrl: 'app/views/backendLayout.html',
abstract: true,
data: {
authorize: true
}
})
.state('backend.user', {
templateUrl: 'app/views/userLayout.html',
abstract: true
})
.state('backend.user.vault', {
url: '^/vault',
templateUrl: 'app/vault/views/vault.html',
controller: 'vaultController',
data: {
pageTitle: 'My Vault',
controlSidebar: true
},
params: {
refreshFromServer: false
}
})
.state('backend.user.shared', {
url: '^/shared',
templateUrl: 'app/vault/views/vaultShared.html',
controller: 'vaultSharedController',
data: { pageTitle: 'Shared' }
})
.state('backend.user.settings', {
url: '^/settings',
templateUrl: 'app/settings/views/settings.html',
controller: 'settingsController',
data: { pageTitle: 'Settings' }
})
.state('backend.user.settingsDomains', {
url: '^/settings/domains',
templateUrl: 'app/settings/views/settingsDomains.html',
controller: 'settingsDomainsController',
data: { pageTitle: 'Domain Settings' }
})
.state('backend.user.settingsTwoStep', {
url: '^/settings/two-step',
templateUrl: 'app/settings/views/settingsTwoStep.html',
controller: 'settingsTwoStepController',
data: { pageTitle: 'Two-step Login' }
})
.state('backend.user.settingsCreateOrg', {
url: '^/settings/create-organization',
templateUrl: 'app/settings/views/settingsCreateOrganization.html',
controller: 'settingsCreateOrganizationController',
data: { pageTitle: 'Create Organization' }
})
.state('backend.user.settingsBilling', {
url: '^/settings/billing',
templateUrl: 'app/settings/views/settingsBilling.html',
controller: 'settingsBillingController',
data: { pageTitle: 'Billing' }
})
.state('backend.user.settingsPremium', {
url: '^/settings/premium',
templateUrl: 'app/settings/views/settingsPremium.html',
controller: 'settingsPremiumController',
data: { pageTitle: 'Go Premium' }
})
.state('backend.user.tools', {
url: '^/tools',
templateUrl: 'app/tools/views/tools.html',
controller: 'toolsController',
data: { pageTitle: 'Tools' }
})
.state('backend.user.reportsBreach', {
url: '^/reports/breach',
templateUrl: 'app/reports/views/reportsBreach.html',
controller: 'reportsBreachController',
data: { pageTitle: 'Data Breach Report' }
})
.state('backend.user.apps', {
url: '^/apps',
templateUrl: 'app/views/apps.html',
controller: 'appsController',
data: { pageTitle: 'Get the Apps' }
})
.state('backend.org', {
templateUrl: 'app/views/organizationLayout.html',
abstract: true
})
.state('backend.org.dashboard', {
url: '^/organization/:orgId',
templateUrl: 'app/organization/views/organizationDashboard.html',
controller: 'organizationDashboardController',
data: { pageTitle: 'Organization Dashboard' }
})
.state('backend.org.people', {
url: '/organization/:orgId/people',
templateUrl: 'app/organization/views/organizationPeople.html',
controller: 'organizationPeopleController',
data: { pageTitle: 'Organization People' }
})
.state('backend.org.collections', {
url: '/organization/:orgId/collections',
templateUrl: 'app/organization/views/organizationCollections.html',
controller: 'organizationCollectionsController',
data: { pageTitle: 'Organization Collections' }
})
.state('backend.org.settings', {
url: '/organization/:orgId/settings',
templateUrl: 'app/organization/views/organizationSettings.html',
controller: 'organizationSettingsController',
data: { pageTitle: 'Organization Settings' }
})
.state('backend.org.billing', {
url: '/organization/:orgId/billing',
templateUrl: 'app/organization/views/organizationBilling.html',
controller: 'organizationBillingController',
data: { pageTitle: 'Organization Billing' }
})
.state('backend.org.vault', {
url: '/organization/:orgId/vault',
templateUrl: 'app/organization/views/organizationVault.html',
controller: 'organizationVaultController',
data: { pageTitle: 'Organization Vault' }
})
.state('backend.org.groups', {
url: '/organization/:orgId/groups',
templateUrl: 'app/organization/views/organizationGroups.html',
controller: 'organizationGroupsController',
data: { pageTitle: 'Organization Groups' }
})
// Frontend
.state('frontend', {
templateUrl: 'app/views/frontendLayout.html',
abstract: true,
data: {
authorize: false
}
})
.state('frontend.login', {
templateUrl: 'app/accounts/views/accountsLogin.html',
controller: 'accountsLoginController',
params: {
returnState: null,
email: null,
premium: null,
org: null
},
data: {
bodyClass: 'login-page'
}
})
.state('frontend.login.info', {
url: '^/?org&premium&email',
templateUrl: 'app/accounts/views/accountsLoginInfo.html',
data: {
pageTitle: 'Log In'
}
})
.state('frontend.login.twoFactor', {
url: '^/two-step?org&premium&email',
templateUrl: 'app/accounts/views/accountsLoginTwoFactor.html',
data: {
pageTitle: 'Log In (Two-step)'
}
})
.state('frontend.logout', {
url: '^/logout',
controller: 'accountsLogoutController',
data: {
authorize: true
}
})
.state('frontend.passwordHint', {
url: '^/password-hint',
templateUrl: 'app/accounts/views/accountsPasswordHint.html',
controller: 'accountsPasswordHintController',
data: {
pageTitle: 'Master Password Hint',
bodyClass: 'login-page'
}
})
.state('frontend.recover', {
url: '^/recover',
templateUrl: 'app/accounts/views/accountsRecover.html',
controller: 'accountsRecoverController',
data: {
pageTitle: 'Recover Account',
bodyClass: 'login-page'
}
})
.state('frontend.recover-delete', {
url: '^/recover-delete',
templateUrl: 'app/accounts/views/accountsRecoverDelete.html',
controller: 'accountsRecoverDeleteController',
data: {
pageTitle: 'Delete Account',
bodyClass: 'login-page'
}
})
.state('frontend.verify-recover-delete', {
url: '^/verify-recover-delete?userId&token&email',
templateUrl: 'app/accounts/views/accountsVerifyRecoverDelete.html',
controller: 'accountsVerifyRecoverDeleteController',
data: {
pageTitle: 'Confirm Delete Account',
bodyClass: 'login-page'
}
})
.state('frontend.register', {
url: '^/register?org&premium',
templateUrl: 'app/accounts/views/accountsRegister.html',
controller: 'accountsRegisterController',
params: {
returnState: null,
email: null,
org: null,
premium: null
},
data: {
pageTitle: 'Register',
bodyClass: 'register-page'
}
})
.state('frontend.organizationAccept', {
url: '^/accept-organization?organizationId&organizationUserId&token&email&organizationName',
templateUrl: 'app/accounts/views/accountsOrganizationAccept.html',
controller: 'accountsOrganizationAcceptController',
data: {
pageTitle: 'Accept Organization Invite',
bodyClass: 'login-page',
skipAuthorize: true
}
})
.state('frontend.verifyEmail', {
url: '^/verify-email?userId&token',
templateUrl: 'app/accounts/views/accountsVerifyEmail.html',
controller: 'accountsVerifyEmailController',
data: {
pageTitle: 'Verifying Email',
bodyClass: 'login-page',
skipAuthorize: true
}
});
})
.run(function ($rootScope, authService, $state) {
$rootScope.$on('$stateChangeSuccess', function () {
$('html, body').animate({ scrollTop: 0 }, 200);
});
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
if (!toState.data || !toState.data.authorize) {
if (toState.data && toState.data.skipAuthorize) {
return;
}
if (!authService.isAuthenticated()) {
return;
}
event.preventDefault();
$state.go('backend.user.vault');
return;
}
if (!authService.isAuthenticated()) {
event.preventDefault();
authService.logOut();
$state.go('frontend.login.info');
return;
}
// user is guaranteed to be authenticated becuase of previous check
if (toState.name.indexOf('backend.org.') > -1 && toParams.orgId) {
// clear vault rootScope when visiting org admin section
$rootScope.vaultCiphers = $rootScope.vaultFolders = null;
authService.getUserProfile().then(function (profile) {
var orgs = profile.organizations;
if (!orgs || !(toParams.orgId in orgs) || orgs[toParams.orgId].status !== 2 ||
orgs[toParams.orgId].type === 2) {
event.preventDefault();
$state.go('backend.user.vault');
}
});
}
});
});

View File

@@ -1,147 +0,0 @@
angular.module('bit')
.constant('constants', {
rememberedEmailCookieName: 'bit.rememberedEmail',
encType: {
AesCbc256_B64: 0,
AesCbc128_HmacSha256_B64: 1,
AesCbc256_HmacSha256_B64: 2,
Rsa2048_OaepSha256_B64: 3,
Rsa2048_OaepSha1_B64: 4,
Rsa2048_OaepSha256_HmacSha256_B64: 5,
Rsa2048_OaepSha1_HmacSha256_B64: 6
},
orgUserType: {
owner: 0,
admin: 1,
user: 2
},
orgUserStatus: {
invited: 0,
accepted: 1,
confirmed: 2
},
twoFactorProvider: {
u2f: 4,
yubikey: 3,
duo: 2,
authenticator: 0,
email: 1,
remember: 5
},
cipherType: {
login: 1,
secureNote: 2,
card: 3,
identity: 4
},
fieldType: {
text: 0,
hidden: 1,
boolean: 2
},
twoFactorProviderInfo: [
{
type: 0,
name: 'Authenticator App',
description: 'Use an authenticator app (such as Authy or Google Authenticator) to generate time-based ' +
'verification codes.',
enabled: false,
active: true,
free: true,
image: 'authapp.png',
displayOrder: 0,
priority: 1,
requiresUsb: false
},
{
type: 3,
name: 'YubiKey OTP Security Key',
description: 'Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices.',
enabled: false,
active: true,
image: 'yubico.png',
displayOrder: 1,
priority: 3,
requiresUsb: true
},
{
type: 2,
name: 'Duo',
description: 'Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.',
enabled: false,
active: true,
image: 'duo.png',
displayOrder: 2,
priority: 2,
requiresUsb: false
},
{
type: 4,
name: 'FIDO U2F Security Key',
description: 'Use any FIDO U2F enabled security key to access your account.',
enabled: false,
active: true,
image: 'fido.png',
displayOrder: 3,
priority: 4,
requiresUsb: true
},
{
type: 1,
name: 'Email',
description: 'Verification codes will be emailed to you.',
enabled: false,
active: true,
free: true,
image: 'gmail.png',
displayOrder: 4,
priority: 0,
requiresUsb: false
}
],
plans: {
free: {
basePrice: 0,
noAdditionalSeats: true,
noPayment: true,
upgradeSortOrder: -1
},
families: {
basePrice: 1,
annualBasePrice: 12,
baseSeats: 5,
noAdditionalSeats: true,
annualPlanType: 'familiesAnnually',
upgradeSortOrder: 1
},
teams: {
basePrice: 5,
annualBasePrice: 60,
monthlyBasePrice: 8,
baseSeats: 5,
seatPrice: 2,
annualSeatPrice: 24,
monthlySeatPrice: 2.5,
monthPlanType: 'teamsMonthly',
annualPlanType: 'teamsAnnually',
upgradeSortOrder: 2
},
enterprise: {
seatPrice: 3,
annualSeatPrice: 36,
monthlySeatPrice: 4,
monthPlanType: 'enterpriseMonthly',
annualPlanType: 'enterpriseAnnually',
upgradeSortOrder: 3
}
},
storageGb: {
price: 0.33,
monthlyPrice: 0.50,
yearlyPrice: 4
},
premium: {
price: 10,
yearlyPrice: 10
}
});

View File

@@ -1,30 +0,0 @@
angular
.module('bit.directives')
.directive('apiField', function () {
var linkFn = function (scope, element, attrs, ngModel) {
ngModel.$registerApiError = registerApiError;
ngModel.$validators.apiValidate = apiValidator;
function apiValidator() {
ngModel.$setValidity('api', true);
return true;
}
function registerApiError() {
ngModel.$setValidity('api', false);
}
};
return {
require: 'ngModel',
restrict: 'A',
compile: function (elem, attrs) {
if (!attrs.name || attrs.name === '') {
throw 'api-field element does not have a valid name attribute';
}
return linkFn;
}
};
});

View File

@@ -1,45 +0,0 @@
angular
.module('bit.directives')
.directive('apiForm', function ($rootScope, validationService, $timeout) {
return {
require: 'form',
restrict: 'A',
link: function (scope, element, attrs, formCtrl) {
var watchPromise = attrs.apiForm || null;
if (watchPromise !== void 0) {
scope.$watch(watchPromise, formSubmitted.bind(null, formCtrl, scope));
}
}
};
function formSubmitted(form, scope, promise) {
if (!promise || !promise.then) {
return;
}
// reset errors
form.$errors = null;
// start loading
form.$loading = true;
promise.then(function success(response) {
$timeout(function () {
form.$loading = false;
});
}, function failure(reason) {
$timeout(function () {
form.$loading = false;
if (typeof reason === 'string') {
validationService.addError(form, null, reason, true);
}
else {
validationService.addErrors(form, reason);
}
scope.$broadcast('show-errors-check-validity');
$('html, body').animate({ scrollTop: 0 }, 200);
});
});
}
});

View File

@@ -1,2 +0,0 @@
angular
.module('bit.directives', []);

View File

@@ -1,11 +0,0 @@
angular
.module('bit.directives')
.directive('fallbackSrc', function () {
return function (scope, element, attrs) {
var el = $(element);
el.bind('error', function (event) {
el.attr('src', attrs.fallbackSrc);
});
};
});

View File

@@ -1,151 +0,0 @@
angular
.module('bit.directives')
// adaptation of https://github.com/uttesh/ngletteravatar
.directive('letterAvatar', function () {
// ref: http://stackoverflow.com/a/16348977/1090359
function stringToColor(str) {
var hash = 0,
i = 0;
for (i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
var color = '#';
for (i = 0; i < 3; i++) {
var value = (hash >> (i * 8)) & 0xFF;
color += ('00' + value.toString(16)).substr(-2);
}
return color;
}
function getFirstLetters(data, count) {
var parts = data.split(' ');
if (parts && parts.length > 1) {
var text = '';
for (var i = 0; i < count; i++) {
text += parts[i].substr(0, 1);
}
return text;
}
return null;
}
function getSvg(width, height, color) {
var svgTag = angular.element('<svg></svg>')
.attr({
'xmlns': 'http://www.w3.org/2000/svg',
'pointer-events': 'none',
'width': width,
'height': height
})
.css({
'background-color': color,
'width': width + 'px',
'height': height + 'px'
});
return svgTag;
}
function getCharText(character, textColor, fontFamily, fontWeight, fontsize) {
var textTag = angular.element('<text text-anchor="middle"></text>')
.attr({
'y': '50%',
'x': '50%',
'dy': '0.35em',
'pointer-events': 'auto',
'fill': textColor,
'font-family': fontFamily
})
.text(character)
.css({
'font-weight': fontWeight,
'font-size': fontsize + 'px',
});
return textTag;
}
return {
restrict: 'AE',
replace: true,
scope: {
data: '@'
},
link: function (scope, element, attrs) {
var params = {
charCount: attrs.charcount || 2,
data: attrs.data,
textColor: attrs.textcolor || '#ffffff',
bgColor: attrs.bgcolor,
height: attrs.avheight || 45,
width: attrs.avwidth || 45,
fontSize: attrs.fontsize || 20,
fontWeight: attrs.fontweight || 300,
fontFamily: attrs.fontfamily || 'Open Sans, HelveticaNeue-Light, Helvetica Neue Light, ' +
'Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif',
round: attrs.round || 'true',
dynamic: attrs.dynamic || 'true',
class: attrs.avclass || '',
border: attrs.avborder || 'false',
borderStyle: attrs.borderstyle || '3px solid white'
};
if (params.dynamic === 'true') {
scope.$watch('data', function () {
generateLetterAvatar();
});
}
else {
generateLetterAvatar();
}
function generateLetterAvatar() {
var c = null,
upperData = scope.data.toUpperCase();
if (params.charCount > 1) {
c = getFirstLetters(upperData, params.charCount);
}
if (!c) {
c = upperData.substr(0, params.charCount);
}
var cobj = getCharText(c, params.textColor, params.fontFamily, params.fontWeight, params.fontSize);
var color = params.bgColor ? params.bgColor : stringToColor(upperData);
var svg = getSvg(params.width, params.height, color);
svg.append(cobj);
var lvcomponent = angular.element('<div>').append(svg).html();
var svgHtml = window.btoa(unescape(encodeURIComponent(lvcomponent)));
var src = 'data:image/svg+xml;base64,' + svgHtml;
var img = angular.element('<img>').attr({ src: src, title: scope.data });
if (params.round === 'true') {
img.css('border-radius', '50%');
}
if (params.border === 'true') {
img.css('border', params.borderStyle);
}
if (params.class) {
img.addClass(params.class);
}
if (params.dynamic === 'true') {
element.empty();
element.append(img);
}
else {
element.replaceWith(img);
}
}
}
};
});

View File

@@ -1,38 +0,0 @@
angular
.module('bit.directives')
.directive('masterPassword', function (cryptoService, authService) {
return {
require: 'ngModel',
restrict: 'A',
link: function (scope, elem, attr, ngModel) {
authService.getUserProfile().then(function (profile) {
// For DOM -> model validation
ngModel.$parsers.unshift(function (value) {
if (!value) {
return undefined;
}
return cryptoService.makeKey(value, profile.email).then(function (result) {
var valid = result.keyB64 === cryptoService.getKey().keyB64;
ngModel.$setValidity('masterPassword', valid);
return valid ? value : undefined;
});
});
// For model -> DOM validation
ngModel.$formatters.unshift(function (value) {
if (!value) {
return undefined;
}
return cryptoService.makeKey(value, profile.email).then(function (result) {
var valid = result.keyB64 === cryptoService.getKey().keyB64;
ngModel.$setValidity('masterPassword', valid);
return value;
});
});
});
}
};
});

View File

@@ -1,22 +0,0 @@
angular
.module('bit.directives')
.directive('pageTitle', function ($rootScope, $timeout, appSettings) {
return {
link: function (scope, element) {
var listener = function (event, toState, toParams, fromState, fromParams) {
// Default title
var title = 'bitwarden Web Vault';
if (toState.data && toState.data.pageTitle) {
title = toState.data.pageTitle + ' - ' + title;
}
$timeout(function () {
element.text(title);
});
};
$rootScope.$on('$stateChangeStart', listener);
}
};
});

View File

@@ -1,73 +0,0 @@
angular
.module('bit.directives')
.directive('passwordMeter', function () {
return {
template: '<div class="progress {{outerClass}}"><div class="progress-bar progress-bar-{{valueClass}}" ' +
'role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="100" ' +
'ng-style="{width : ( value + \'%\' ) }"><span class="sr-only">{{value}}%</span></div></div>',
restrict: 'A',
scope: {
password: '=passwordMeter',
username: '=passwordMeterUsername',
outerClass: '@?'
},
link: function (scope) {
var measureStrength = function (username, password) {
if (!password || password === username) {
return 0;
}
var strength = password.length;
if (username && username !== '') {
if (username.indexOf(password) !== -1) strength -= 15;
if (password.indexOf(username) !== -1) strength -= username.length;
}
if (password.length > 0 && password.length <= 4) strength += password.length;
else if (password.length >= 5 && password.length <= 7) strength += 6;
else if (password.length >= 8 && password.length <= 15) strength += 12;
else if (password.length >= 16) strength += 18;
if (password.match(/[a-z]/)) strength += 1;
if (password.match(/[A-Z]/)) strength += 5;
if (password.match(/\d/)) strength += 5;
if (password.match(/.*\d.*\d.*\d/)) strength += 5;
if (password.match(/[!,@,#,$,%,^,&,*,?,_,~]/)) strength += 5;
if (password.match(/.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~]/)) strength += 5;
if (password.match(/(?=.*[a-z])(?=.*[A-Z])/)) strength += 2;
if (password.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/)) strength += 2;
if (password.match(/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!,@,#,$,%,^,&,*,?,_,~])/)) strength += 2;
strength = Math.round(strength * 2);
return Math.max(0, Math.min(100, strength));
};
var getClass = function (strength) {
switch (Math.round(strength / 33)) {
case 0:
case 1:
return 'danger';
case 2:
return 'warning';
case 3:
return 'success';
}
};
var updateMeter = function (scope) {
scope.value = measureStrength(scope.username, scope.password);
scope.valueClass = getClass(scope.value);
};
scope.$watch('password', function () {
updateMeter(scope);
});
scope.$watch('username', function () {
updateMeter(scope);
});
},
};
});

View File

@@ -1,27 +0,0 @@
angular
.module('bit.directives')
.directive('passwordViewer', function () {
return {
restrict: 'A',
link: function (scope, element, attr) {
var passwordViewer = attr.passwordViewer;
if (!passwordViewer) {
return;
}
element.onclick = function (event) { };
element.on('click', function (event) {
var passwordElement = $(passwordViewer);
if (passwordElement && passwordElement.attr('type') === 'password') {
element.removeClass('fa-eye').addClass('fa-eye-slash');
passwordElement.attr('type', 'text');
}
else if (passwordElement && passwordElement.attr('type') === 'text') {
element.removeClass('fa-eye-slash').addClass('fa-eye');
passwordElement.attr('type', 'password');
}
});
}
};
});

View File

@@ -1,11 +0,0 @@
angular
.module('bit.directives')
// ref: https://stackoverflow.com/a/14165848/1090359
.directive('stopClick', function () {
return function (scope, element, attrs) {
$(element).click(function (event) {
event.preventDefault();
});
};
});

View File

@@ -1,10 +0,0 @@
angular
.module('bit.directives')
.directive('stopProp', function () {
return function (scope, element, attrs) {
$(element).click(function (event) {
event.stopPropagation();
});
};
});

View File

@@ -1,193 +0,0 @@
angular
.module('bit.directives')
.directive('totp', function ($timeout, $q) {
return {
template: '<div class="totp{{(low ? \' low\' : \'\')}}" ng-if="code">' +
'<span class="totp-countdown"><span class="totp-sec">{{sec}}</span>' +
'<svg><g><circle class="totp-circle inner" r="12.6" cy="16" cx="16" style="stroke-dashoffset: {{dash}}px;"></circle>' +
'<circle class="totp-circle outer" r="14" cy="16" cx="16"></circle></g></svg></span>' +
'<span class="totp-code" id="totp-code">{{codeFormatted}}</span>' +
'<a href="#" stop-click class="btn btn-link" ngclipboard ngclipboard-error="clipboardError(e)" ' +
'data-clipboard-text="{{code}}" uib-tooltip="Copy Code" tooltip-placement="right">' +
'<i class="fa fa-clipboard"></i></a>' +
'</div>',
restrict: 'A',
scope: {
key: '=totp'
},
link: function (scope) {
var interval = null;
var Totp = function () {
var b32Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
var leftpad = function (s, l, p) {
if (l + 1 >= s.length) {
s = Array(l + 1 - s.length).join(p) + s;
}
return s;
};
var dec2hex = function (d) {
return (d < 15.5 ? '0' : '') + Math.round(d).toString(16);
};
var hex2dec = function (s) {
return parseInt(s, 16);
};
var hex2bytes = function (s) {
var bytes = new Uint8Array(s.length / 2);
for (var i = 0; i < s.length; i += 2) {
bytes[i / 2] = parseInt(s.substr(i, 2), 16);
}
return bytes;
};
var buff2hex = function (buff) {
var bytes = new Uint8Array(buff);
var hex = [];
for (var i = 0; i < bytes.length; i++) {
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
}
return hex.join('');
};
var b32tohex = function (s) {
s = s.toUpperCase();
var cleanedInput = '';
var i;
for (i = 0; i < s.length; i++) {
if (b32Chars.indexOf(s[i]) < 0) {
continue;
}
cleanedInput += s[i];
}
s = cleanedInput;
var bits = '';
var hex = '';
for (i = 0; i < s.length; i++) {
var byteIndex = b32Chars.indexOf(s.charAt(i));
if (byteIndex < 0) {
continue;
}
bits += leftpad(byteIndex.toString(2), 5, '0');
}
for (i = 0; i + 4 <= bits.length; i += 4) {
var chunk = bits.substr(i, 4);
hex = hex + parseInt(chunk, 2).toString(16);
}
return hex;
};
var b32tobytes = function (s) {
return hex2bytes(b32tohex(s));
};
var sign = function (keyBytes, timeBytes) {
return window.crypto.subtle.importKey('raw', keyBytes,
{ name: 'HMAC', hash: { name: 'SHA-1' } }, false, ['sign']).then(function (key) {
return window.crypto.subtle.sign({ name: 'HMAC', hash: { name: 'SHA-1' } }, key, timeBytes);
}).then(function (signature) {
return buff2hex(signature);
}).catch(function (err) {
return null;
});
};
this.getCode = function (keyb32) {
var epoch = Math.round(new Date().getTime() / 1000.0);
var timeHex = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0');
var timeBytes = hex2bytes(timeHex);
var keyBytes = b32tobytes(keyb32);
if (!keyBytes.length || !timeBytes.length) {
return $q(function (resolve, reject) {
resolve(null);
});
}
return sign(keyBytes, timeBytes).then(function (hashHex) {
if (!hashHex) {
return null;
}
var offset = hex2dec(hashHex.substring(hashHex.length - 1));
var otp = (hex2dec(hashHex.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
otp = (otp).substr(otp.length - 6, 6);
return otp;
});
};
};
var totp = new Totp();
var updateCode = function (scope) {
totp.getCode(scope.key).then(function (code) {
$timeout(function () {
if (code) {
scope.codeFormatted = code.substring(0, 3) + ' ' + code.substring(3);
scope.code = code;
}
else {
scope.code = null;
if (interval) {
clearInterval(interval);
}
}
});
});
};
var tick = function (scope) {
$timeout(function () {
var epoch = Math.round(new Date().getTime() / 1000.0);
var mod = epoch % 30;
var sec = 30 - mod;
scope.sec = sec;
scope.dash = (2.62 * mod).toFixed(2);
scope.low = sec <= 7;
if (mod === 0) {
updateCode(scope);
}
});
};
scope.$watch('key', function () {
if (!scope.key) {
scope.code = null;
if (interval) {
clearInterval(interval);
}
return;
}
updateCode(scope);
tick(scope);
if (interval) {
clearInterval(interval);
}
interval = setInterval(function () {
tick(scope);
}, 1000);
});
scope.$on('$destroy', function () {
if (interval) {
clearInterval(interval);
}
});
scope.clipboardError = function (e) {
alert('Your web browser does not support easy clipboard copying.');
};
},
};
});

12
src/app/dummy.module.ts Normal file
View File

@@ -0,0 +1,12 @@
import { NgModule } from '@angular/core';
import { ModalComponent } from 'jslib/angular/components/modal.component';
@NgModule({
imports: [],
declarations: [
ModalComponent,
],
})
export class DummyModule {
}

View File

@@ -1,32 +0,0 @@
angular
.module('bit.filters')
.filter('enumLabelClass', function () {
return function (input, name) {
if (typeof input !== 'number') {
return input.toString();
}
var output;
switch (name) {
case 'OrgUserStatus':
switch (input) {
case 0:
output = 'label-default';
break;
case 1:
output = 'label-warning';
break;
case 2:
/* falls through */
default:
output = 'label-success';
}
break;
default:
output = 'label-default';
}
return output;
};
});

View File

@@ -1,46 +0,0 @@
angular
.module('bit.filters')
.filter('enumName', function () {
return function (input, name) {
if (typeof input !== 'number') {
return input.toString();
}
var output;
switch (name) {
case 'OrgUserStatus':
switch (input) {
case 0:
output = 'Invited';
break;
case 1:
output = 'Accepted';
break;
case 2:
/* falls through */
default:
output = 'Confirmed';
}
break;
case 'OrgUserType':
switch (input) {
case 0:
output = 'Owner';
break;
case 1:
output = 'Admin';
break;
case 2:
/* falls through */
default:
output = 'User';
}
break;
default:
output = input.toString();
}
return output;
};
});

View File

@@ -1,2 +0,0 @@
angular
.module('bit.filters', []);

View File

@@ -1,6 +0,0 @@
angular
.module('bit.global')
.controller('appsController', function ($scope, $state) {
});

View File

@@ -1,2 +0,0 @@
angular
.module('bit.global', []);

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