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

Compare commits

..

21 Commits

Author SHA1 Message Date
Joseph Flinn
daf641e978 fixing the release workflow (#1009) 2021-06-02 09:30:09 -07:00
Joseph Flinn
c052b7f319 bumping version 2.20.4 (#1008) 2021-06-02 09:04:30 -07:00
Joseph Flinn
b1246b65ee Release Workflow (#1007)
* spilting out the build workflow into build and release workflows. Solves the problem of the incorrect self-hosted version being released

* pinning action versions

* release workflow fixes

* removing unneeded env vars

* normalizing the naming conventions

* one more Docker
2021-06-02 08:37:51 -07:00
Hinton
23f063928c Version bump for webauthn hotfix 2021-05-21 15:40:03 +02:00
Oscar Hinton
9184ceefaf Correctly handle dash in locale, and add a fallback to en. (#988)
(cherry picked from commit 1098adc03d)
2021-05-21 15:39:31 +02:00
Matt Gibson
a73282b797 Version bump for org search hot fix 2021-05-19 11:50:43 -05:00
Matt Gibson
fc2250fdfd Set search index for limited collection org users (#983)
(cherry picked from commit 1c5ce23d35)
2021-05-19 11:12:45 -05:00
Vince Grassia
165944624a Fix docker tag version in workflow (#973) 2021-05-12 14:28:28 -07:00
Chad Scharf
11b96728f2 Version bump, 2.20.1 (#971) 2021-05-12 13:00:12 -04:00
Oscar Hinton
62e22ff149 Change WebAuthn connectors from using inline onclick to external (#969)
(cherry picked from commit a3506e833a)
2021-05-12 17:20:21 +02:00
Daniel James Smith
09968a18d0 Fix typo in webAuthnAuthenticate (#964) 2021-05-12 09:10:08 -04:00
Joseph Flinn
cc59d08a69 fixing docker push (#965)
* fixing docker push

* adding in the the missed vars
2021-05-11 12:51:02 -07:00
Joseph Flinn
ac45ac2eca Updating the docker signing key (#963)
* Updating the docker signing key

* restricting the Azure login to specific branches that use docker

* only retrieving secrets on specific branches
2021-05-11 12:05:58 -07:00
Kyle Spearrin
95c0e211c7 New Crowdin updates (#962)
* New translations messages.json (Romanian)

* New translations messages.json (Bengali)

* New translations messages.json (Swedish)

* New translations messages.json (Turkish)

* New translations messages.json (Ukrainian)

* New translations messages.json (Chinese Simplified)

* New translations messages.json (Chinese Traditional)

* New translations messages.json (Vietnamese)

* New translations messages.json (Portuguese, Brazilian)

* New translations messages.json (Indonesian)

* New translations messages.json (Croatian)

* New translations messages.json (Slovenian)

* New translations messages.json (Estonian)

* New translations messages.json (Latvian)

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

* New translations messages.json (Esperanto)

* New translations messages.json (Malayalam)

* New translations messages.json (Sinhala)

* New translations messages.json (Norwegian Bokmal)

* New translations messages.json (Serbian (Latin))

* New translations messages.json (Serbian (Cyrillic))

* New translations messages.json (Slovak)

* New translations messages.json (French)

* New translations messages.json (Greek)

* New translations messages.json (Spanish)

* New translations messages.json (Afrikaans)

* New translations messages.json (Belarusian)

* New translations messages.json (Bulgarian)

* New translations messages.json (Catalan)

* New translations messages.json (Czech)

* New translations messages.json (Danish)

* New translations messages.json (German)

* New translations messages.json (Finnish)

* New translations messages.json (Russian)

* New translations messages.json (Hebrew)

* New translations messages.json (Hungarian)

* New translations messages.json (Italian)

* New translations messages.json (Japanese)

* New translations messages.json (Korean)

* New translations messages.json (Dutch)

* New translations messages.json (Polish)

* New translations messages.json (Portuguese)

* New translations messages.json (English, India)
2021-05-11 13:51:49 -04:00
Oscar Hinton
fed8990a6a Add auto delete warning to trash page (#953)
* Add warning to trash page

(cherry picked from commit dd56c9bc87)
2021-04-27 19:24:34 +02:00
Matt Gibson
b8431f0101 Update jslib 2021-04-26 15:24:32 -05:00
Matt Gibson
af47e25ead Update jslib 2021-04-23 14:09:14 -05:00
Matt Gibson
a315370e5d update jslib 2021-04-23 10:32:22 -05:00
Matt Gibson
5a64b22190 Specify organization id as the indexing entity (#945)
* Specify organization id as the indexing entity

* Update jslib

(cherry picked from commit f6eec08b70)
2021-04-23 09:53:33 -05:00
Vincent Salucci
4b05bc981c [Version] Bumped to 2.20.0 (#944)
* [Version] Bumped to 2.20.0

* Updated package-lock version
2021-04-22 11:57:30 -05:00
Vincent Salucci
00f0dc3499 [Reset Password] Feature Flag (#943) 2021-04-22 09:49:27 -05:00
250 changed files with 11219 additions and 38801 deletions

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@v2
- name: Set up cloc
run: |
@@ -25,13 +25,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Node
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
uses: actions/setup-node@v1
with:
node-version: '14'
- name: Update NPM
run: |
npm install -g npm@7
node-version: '10.x'
- name: Print environment
run: |
@@ -78,7 +74,7 @@ jobs:
DCT_DELEGATE_KEY: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-key }}
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@v2
- name: Restore
run: dotnet tool restore
@@ -129,37 +125,34 @@ jobs:
runs-on: windows-latest
steps:
- name: Set up NuGet
uses: nuget/setup-nuget@04b0c2b8d1b97922f67eca497d7cf0bf17b8ffe1
uses: nuget/setup-nuget@v1
with:
nuget-version: 'latest'
- name: Set up MSBuild
uses: microsoft/setup-msbuild@c26a08ba26249b81327e26f6ef381897b6a8754d
uses: microsoft/setup-msbuild@v1
- name: Set up Node
uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea
uses: actions/setup-node@v1
with:
node-version: '14'
- name: Update NPM
run: |
npm install -g npm@7
node-version: '10.x'
- name: Print environment
run: |
nuget help | grep Version
nuget help
msbuild -version
dotnet --info
node --version
npm --version
echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT"
Write-Output "GitHub ref: $env:GITHUB_REF"
Write-Output "GitHub event: $env:GITHUB_EVENT"
shell: pwsh
env:
GITHUB_REF: ${{ github.ref }}
GITHUB_EVENT: ${{ github.event_name }}
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
uses: actions/checkout@v2
- name: npm install
run: npm install

View File

@@ -1,70 +0,0 @@
name: Deploy
on:
workflow_dispatch:
inputs:
release_version:
description: "Release Tag Version <vX.X.X>"
required: true
release:
types:
- published
jobs:
deploy:
name: Deploy Web Vault
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
with:
ref: gh-pages
- name: Get release version
id: release-version
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
echo "::set-output name=version::${{ github.event.release.tag_name }}"
else
echo "::set-output name=version::${{ github.event.inputs.release_version }}"
fi
- name: Create deploy branch
run: |
git switch -c deploy-${{ steps.release-version.outputs.version }}
git push -u origin deploy-${{ steps.release-version.outputs.version }}
- name: Checkout Repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
with:
ref: rc
- name: setup git config
run: |
git config user.name = "GitHub Action Bot"
git config user.email = "<>"
- name: Install and Build
run: |
npm ci
npm run dist
- name: Deploy GitHub Pages
uses: crazy-max/ghaction-github-pages@db4476a01402e1a7ce05f41832040eef16d14925 # v2.5.0
with:
target_branch: deploy-${{ steps.release-version.outputs.version }}
build_dir: build
keep_history: true
commit_message: "Staging deploy ${{ steps.release-version.outputs.version }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Deploy PR
run: |
gh pr create --title "Deploy $VERSION" --body "Deploying $VERSION" --base gh-pages --head "$PR_BRANCH"
env:
VERSION: ${{ steps.release-version.outputs.version }}
PR_BRANCH: deploy-${{ steps.release-version.outputs.version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -23,8 +23,7 @@
### Requirements
- [Node.js](https://nodejs.org) v14.17 or greater
- NPM v7
- [Node.js](https://nodejs.org) v8.11 or greater
### Run the app

View File

@@ -31,7 +31,6 @@ mkhomedir_helper $USERNAME
chown -R $USERNAME:$GROUPNAME /etc/bitwarden
cp /etc/bitwarden/web/app-id.json /app/app-id.json
cp /etc/bitwarden/web/assetlinks.json /app/assetlinks.json
chown -R $USERNAME:$GROUPNAME /app
chown -R $USERNAME:$GROUPNAME /bitwarden_server

2
jslib

Submodule jslib updated: 6f428e11c4...f6d91e2d92

26555
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,28 @@
{
"name": "bitwarden-web",
"version": "2.21.1",
"version": "2.20.4",
"license": "GPL-3.0",
"repository": "https://github.com/bitwarden/web",
"scripts": {
"sub:init": "git submodule update --init --recursive",
"sub:update": "git submodule update --remote",
"sub:pull": "git submodule foreach git pull origin master",
"preinstall": "npm run sub:init",
"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 serve",
"build:watch": "gulp prebuild && webpack-dev-server",
"build:dev": "gulp prebuild && cross-env ENV=development webpack",
"build:dev:watch": "gulp prebuild && cross-env ENV=development webpack serve",
"build:dev:watch": "gulp prebuild && cross-env ENV=development webpack-dev-server",
"build:qa": "gulp prebuild && cross-env NODE_ENV=production ENV=qa webpack",
"build:qa:watch": "gulp prebuild && cross-env NODE_ENV=production ENV=qa webpack serve",
"build:qa:watch": "gulp prebuild && cross-env NODE_ENV=production ENV=qa webpack-dev-server",
"build:prod": "gulp prebuild && cross-env NODE_ENV=production ENV=production webpack",
"build:prod:watch": "gulp prebuild && cross-env NODE_ENV=production ENV=production webpack serve",
"build:selfhost": "gulp prebuild && cross-env SELF_HOST=true webpack serve",
"build:selfhost:watch": "gulp prebuild && cross-env SELF_HOST=true webpack serve",
"build:prod:watch": "gulp prebuild && cross-env NODE_ENV=production 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 serve",
"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",
@@ -32,58 +32,76 @@
"lint:fix": "tslint 'src/**/*.ts' --fix"
},
"devDependencies": {
"@angular/compiler-cli": "^11.2.11",
"@ngtools/webpack": "^11.2.10",
"@types/duo_web_sdk": "^2.7.0",
"@angular/compiler-cli": "^9.1.12",
"@ngtools/webpack": "^9.1.12",
"@types/jquery": "^3.5.5",
"@types/node": "^14.17.2",
"@types/lunr": "^2.3.3",
"@types/node": "^10.17.28",
"@types/node-forge": "^0.9.7",
"@types/papaparse": "^5.2.0",
"@types/webcrypto": "^0.0.28",
"@types/webpack": "^4.4.27",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^6.4.0",
"cross-env": "^7.0.3",
"css-loader": "^5.2.3",
"del": "^6.0.0",
"file-loader": "^6.2.0",
"gh-pages": "^3.1.0",
"gulp": "^4.0.2",
"gulp-google-webfonts": "^4.0.0",
"html-loader": "^1.3.2",
"html-webpack-plugin": "^4.5.1",
"mini-css-extract-plugin": "^1.5.0",
"sass": "^1.32.10",
"sass-loader": "^10.1.1",
"style-loader": "^2.0.0",
"tapable": "^1.1.3",
"terser-webpack-plugin": "^4.2.3",
"ts-loader": "^8.1.0",
"@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": "^5.1.1",
"cross-env": "^5.2.0",
"css-loader": "^1.0.0",
"del": "^3.0.0",
"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",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.1",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.0",
"terser-webpack-plugin": "^1.2.3",
"ts-loader": "^7.0.5",
"tslint": "^6.1.3",
"tslint-loader": "^3.5.4",
"typescript": "4.1.5",
"webpack": "^4.46.0",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2"
"typescript": "3.8.3",
"webpack": "^4.29.0",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14"
},
"dependencies": {
"@bitwarden/jslib-angular": "file:jslib/angular",
"@bitwarden/jslib-common": "file:jslib/common",
"angular2-toaster": "11.0.1",
"bootstrap": "4.6.0",
"braintree-web-drop-in": "1.30.1",
"@angular/animations": "9.1.12",
"@angular/cdk": "9.2.4",
"@angular/common": "9.1.12",
"@angular/compiler": "9.1.12",
"@angular/core": "9.1.12",
"@angular/forms": "9.1.12",
"@angular/platform-browser": "9.1.12",
"@angular/platform-browser-dynamic": "9.1.12",
"@angular/router": "9.1.12",
"@microsoft/signalr": "3.1.13",
"@microsoft/signalr-protocol-msgpack": "3.1.13",
"angular2-toaster": "8.0.0",
"big-integer": "1.6.48",
"bootstrap": "4.3.1",
"braintree-web-drop-in": "1.13.0",
"browser-hrtime": "^1.1.8",
"core-js": "^3.11.0",
"core-js": "2.6.2",
"date-input-polyfill": "^2.14.0",
"duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git#5f9a1a8598d2cda494c4f5ee0e38b31474abfee9",
"duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git#410a9186cc34663c4913b17d6528067cd3331f1d",
"font-awesome": "4.7.0",
"jquery": "3.6.0",
"popper.js": "1.16.1",
"lunr": "2.3.3",
"ngx-infinite-scroll": "7.0.1",
"node-forge": "0.10.0",
"papaparse": "5.2.0",
"popper.js": "1.14.4",
"qrious": "4.0.2",
"sweetalert2": "^10.16.6",
"webcrypto-shim": "0.1.7",
"whatwg-fetch": "3.6.2"
},
"engines": {
"node": "~14",
"npm": "~7"
"rxjs": "6.6.2",
"sweetalert2": "10.15.4",
"tslib": "^2.0.1",
"web-animations-js": "2.3.1",
"webcrypto-shim": "0.1.4",
"whatwg-fetch": "3.0.0",
"zone.js": "0.10.3",
"zxcvbn": "4.4.2"
}
}

View File

@@ -12,11 +12,11 @@ import {
ToasterService,
} from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { EmergencyAccessAcceptRequest } from 'jslib-common/models/request/emergencyAccessAcceptRequest';
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 { EmergencyAccessAcceptRequest } from 'jslib/models/request/emergencyAccessAcceptRequest';
@Component({
selector: 'app-accept-emergency',

View File

@@ -2,7 +2,6 @@ import {
Component,
OnInit,
} from '@angular/core';
import {
ActivatedRoute,
Router,
@@ -13,18 +12,12 @@ import {
ToasterService,
} from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { UserService } from 'jslib-common/abstractions/user.service';
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-common/models/request/organizationUserAcceptRequest';
import { OrganizationUserResetPasswordEnrollmentRequest } from 'jslib-common/models/request/organizationUserResetPasswordEnrollmentRequest';
import { Utils } from 'jslib-common/misc/utils';
import { Policy } from 'jslib-common/models/domain/policy';
import { OrganizationUserAcceptRequest } from 'jslib/models/request/organizationUserAcceptRequest';
@Component({
selector: 'app-accept-organization',
@@ -40,8 +33,7 @@ export class AcceptOrganizationComponent implements OnInit {
constructor(private router: Router, private toasterService: ToasterService,
private i18nService: I18nService, private route: ActivatedRoute,
private apiService: ApiService, private userService: UserService,
private stateService: StateService, private cryptoService: CryptoService,
private policyService: PolicyService) { }
private stateService: StateService) { }
ngOnInit() {
let fired = false;
@@ -59,36 +51,8 @@ export class AcceptOrganizationComponent implements OnInit {
const request = new OrganizationUserAcceptRequest();
request.token = qParams.token;
try {
if (await this.performResetPasswordAutoEnroll(qParams)) {
this.actionPromise = this.apiService.postOrganizationUserAccept(qParams.organizationId,
qParams.organizationUserId, request).then(() => {
// Retrieve Public Key
return this.apiService.getOrganizationKeys(qParams.organizationId);
}).then(async response => {
if (response == null) {
throw new Error(this.i18nService.t('resetPasswordOrgKeysError'));
}
const publicKey = Utils.fromB64ToArray(response.publicKey);
// RSA Encrypt user's encKey.key with organization public key
const encKey = await this.cryptoService.getEncKey();
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer);
// Create request and execute enrollment
const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest();
resetRequest.resetPasswordKey = encryptedKey.encryptedString;
// Get User Id
const userId = await this.userService.getUserId();
return this.apiService.putOrganizationUserResetPasswordEnrollment(qParams.organizationId, userId, resetRequest);
});
} else {
this.actionPromise = this.apiService.postOrganizationUserAccept(qParams.organizationId,
qParams.organizationUserId, request);
}
this.actionPromise = this.apiService.postOrganizationUserAccept(qParams.organizationId,
qParams.organizationUserId, request);
await this.actionPromise;
const toast: Toast = {
type: 'success',
@@ -128,21 +92,4 @@ export class AcceptOrganizationComponent implements OnInit {
this.loading = false;
});
}
private async performResetPasswordAutoEnroll(qParams: any): Promise<boolean> {
let policyList: Policy[] = null;
try {
const policies = await this.apiService.getPoliciesByToken(qParams.organizationId, qParams.token,
qParams.email, qParams.organizationUserId);
policyList = this.policyService.mapPoliciesFromToken(policies);
} catch { }
if (policyList != null) {
const result = this.policyService.getResetPasswordPolicyOptions(policyList, qParams.organizationId);
// Return true if policy enabled and auto-enroll enabled
return result[1] && result[0].autoEnrollEnabled;
}
return false;
}
}

View File

@@ -1,11 +1,11 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
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';
import { HintComponent as BaseHintComponent } from 'jslib/angular/components/hint.component';
@Component({
selector: 'app-hint',

View File

@@ -1,20 +1,20 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.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 { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
import { RouterService } from '../services/router.service';
import { LockComponent as BaseLockComponent } from 'jslib-angular/components/lock.component';
import { LockComponent as BaseLockComponent } from 'jslib/angular/components/lock.component';
@Component({
selector: 'app-lock',

View File

@@ -5,10 +5,6 @@
<p class="lead text-center mx-4 mb-4">{{'loginOrCreateNewAccount' | i18n}}</p>
<div class="card d-block">
<div class="card-body">
<app-callout type="warning" title="{{'resetPasswordPolicyAutoEnroll' | i18n}}"
*ngIf="showResetPasswordAutoEnrollWarning">
{{'resetPasswordAutoEnrollInviteWarning' | 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

View File

@@ -4,35 +4,27 @@ import {
Router,
} from '@angular/router';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { AuthService } from 'jslib-common/abstractions/auth.service';
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { AuthService } from 'jslib/abstractions/auth.service';
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.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';
import { Policy } from 'jslib-common/models/domain/policy';
import { LoginComponent as BaseLoginComponent } from 'jslib/angular/components/login.component';
@Component({
selector: 'app-login',
templateUrl: 'login.component.html',
})
export class LoginComponent extends BaseLoginComponent {
showResetPasswordAutoEnrollWarning = false;
constructor(authService: AuthService, router: Router,
i18nService: I18nService, private route: ActivatedRoute,
storageService: StorageService, stateService: StateService,
platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService,
passwordGenerationService: PasswordGenerationService, cryptoFunctionService: CryptoFunctionService,
private apiService: ApiService, private policyService: PolicyService) {
passwordGenerationService: PasswordGenerationService, cryptoFunctionService: CryptoFunctionService) {
super(authService, router,
platformUtilsService, i18nService,
stateService, environmentService,
@@ -57,22 +49,6 @@ export class LoginComponent extends BaseLoginComponent {
queryParamsSub.unsubscribe();
}
});
const invite = await this.stateService.get<any>('orgInvitation');
if (invite != null) {
let policyList: Policy[] = null;
try {
const policies = await this.apiService.getPoliciesByToken(invite.organizationId, invite.token,
invite.email, invite.organizationUserId);
policyList = this.policyService.mapPoliciesFromToken(policies);
} catch { }
if (policyList != null) {
const result = this.policyService.getResetPasswordPolicyOptions(policyList, invite.organizationId);
// Set to true if policy enabled and auto-enroll enabled
this.showResetPasswordAutoEnrollWarning = result[1] && result[0].autoEnrollEnabled;
}
}
}
async goAfterLogIn() {

View File

@@ -3,10 +3,10 @@ import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { DeleteRecoverRequest } from 'jslib-common/models/request/deleteRecoverRequest';
import { DeleteRecoverRequest } from 'jslib/models/request/deleteRecoverRequest';
@Component({
selector: 'app-recover-delete',

View File

@@ -3,12 +3,12 @@ import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { AuthService } from 'jslib-common/abstractions/auth.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
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-common/models/request/twoFactorRecoveryRequest';
import { TwoFactorRecoveryRequest } from 'jslib/models/request/twoFactorRecoveryRequest';
@Component({
selector: 'app-recover-two-factor',

View File

@@ -4,22 +4,22 @@ import {
Router,
} from '@angular/router';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { AuthService } from 'jslib-common/abstractions/auth.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { StateService } from 'jslib-common/abstractions/state.service';
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 { RegisterComponent as BaseRegisterComponent } from 'jslib/angular/components/register.component';
import { MasterPasswordPolicyOptions } from 'jslib-common/models/domain/masterPasswordPolicyOptions';
import { Policy } from 'jslib-common/models/domain/policy';
import { MasterPasswordPolicyOptions } from 'jslib/models/domain/masterPasswordPolicyOptions';
import { Policy } from 'jslib/models/domain/policy';
import { PolicyData } from 'jslib-common/models/data/policyData';
import { ReferenceEventRequest } from 'jslib-common/models/request/referenceEventRequest';
import { PolicyData } from 'jslib/models/data/policyData';
import { ReferenceEventRequest } from 'jslib/models/request/referenceEventRequest';
@Component({
selector: 'app-register',

View File

@@ -4,19 +4,19 @@ import {
Router,
} from '@angular/router';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { SyncService } from 'jslib/abstractions/sync.service';
import { UserService } from 'jslib/abstractions/user.service';
import {
SetPasswordComponent as BaseSetPasswordComponent,
} from 'jslib-angular/components/set-password.component';
} from 'jslib/angular/components/set-password.component';
@Component({
selector: 'app-set-password',

View File

@@ -4,16 +4,16 @@ import {
Router,
} from '@angular/router';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { AuthService } from 'jslib-common/abstractions/auth.service';
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { AuthService } from 'jslib/abstractions/auth.service';
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { SsoComponent as BaseSsoComponent } from 'jslib-angular/components/sso.component';
import { SsoComponent as BaseSsoComponent } from 'jslib/angular/components/sso.component';
const IdentifierStorageKey = 'ssoOrgIdentifier';

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="twoStepOptionsTitle">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="twoStepOptionsTitle">{{'twoStepOptions' | i18n}}</h2>
@@ -7,19 +7,17 @@
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<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="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>

View File

@@ -1,13 +1,13 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from 'jslib-common/abstractions/auth.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
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';
} from 'jslib/angular/components/two-factor-options.component';
@Component({
selector: 'app-two-factor-options',

View File

@@ -14,17 +14,17 @@ import { TwoFactorOptionsComponent } from './two-factor-options.component';
import { ModalComponent } from '../modal.component';
import { TwoFactorProviderType } from 'jslib-common/enums/twoFactorProviderType';
import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { AuthService } from 'jslib-common/abstractions/auth.service';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
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';
import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib/angular/components/two-factor.component';
@Component({
selector: 'app-two-factor',

View File

@@ -9,11 +9,11 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { UserService } from 'jslib-common/abstractions/user.service';
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-common/models/request/verifyEmailRequest';
import { VerifyEmailRequest } from 'jslib/models/request/verifyEmailRequest';
@Component({
selector: 'app-verify-email-token',

View File

@@ -9,10 +9,10 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { VerifyDeleteRecoverRequest } from 'jslib-common/models/request/verifyDeleteRecoverRequest';
import { VerifyDeleteRecoverRequest } from 'jslib/models/request/verifyDeleteRecoverRequest';
@Component({
selector: 'app-verify-recover-delete',

View File

@@ -88,11 +88,11 @@ import { VaultComponent } from './vault/vault.component';
import { OrganizationGuardService } from './services/organization-guard.service';
import { OrganizationTypeGuardService } from './services/organization-type-guard.service';
import { AuthGuardService } from 'jslib-angular/services/auth-guard.service';
import { LockGuardService } from 'jslib-angular/services/lock-guard.service';
import { UnauthGuardService } from 'jslib-angular/services/unauth-guard.service';
import { AuthGuardService } from 'jslib/angular/services/auth-guard.service';
import { LockGuardService } from 'jslib/angular/services/lock-guard.service';
import { UnauthGuardService } from 'jslib/angular/services/unauth-guard.service';
import { Permissions } from 'jslib-common/enums/permissions';
import { Permissions } from 'jslib/enums/permissions';
import { EmergencyAccessViewComponent } from './settings/emergency-access-view.component';
import { EmergencyAccessComponent } from './settings/emergency-access.component';
@@ -200,12 +200,12 @@ const routes: Routes = [
{
path: '',
component: EmergencyAccessComponent,
data: { titleId: 'emergencyAccess' },
data: { titleId: 'emergencyAccess'},
},
{
path: ':id',
component: EmergencyAccessViewComponent,
data: { titleId: 'emergencyAccess' },
data: { titleId: 'emergencyAccess'},
},
],
},
@@ -390,7 +390,7 @@ const routes: Routes = [
canActivate: [OrganizationTypeGuardService],
data: {
titleId: 'people',
permissions: [Permissions.ManageUsers, Permissions.ManageUsersPassword],
permissions: [Permissions.ManageUsers],
},
},
{

View File

@@ -1,5 +1,5 @@
import * as jq from 'jquery';
import Swal from 'sweetalert2';
import Swal from 'sweetalert2/dist/sweetalert2.js';
import {
BodyOutputType,
@@ -21,30 +21,30 @@ import {
Router,
} from '@angular/router';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { AuthService } from 'jslib-common/abstractions/auth.service';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { CollectionService } from 'jslib-common/abstractions/collection.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { EventService } from 'jslib-common/abstractions/event.service';
import { FolderService } from 'jslib-common/abstractions/folder.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { NotificationsService } from 'jslib-common/abstractions/notifications.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { SearchService } from 'jslib-common/abstractions/search.service';
import { SettingsService } from 'jslib-common/abstractions/settings.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { TokenService } from 'jslib-common/abstractions/token.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.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 { 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 { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
import { ConstantsService } from 'jslib-common/services/constants.service';
import { ConstantsService } from 'jslib/services/constants.service';
import { RouterService } from './services/router.service';

View File

@@ -1,3 +1,5 @@
import 'core-js';
import { ToasterModule } from 'angular2-toaster';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
@@ -38,9 +40,6 @@ import { TwoFactorComponent } from './accounts/two-factor.component';
import { VerifyEmailTokenComponent } from './accounts/verify-email-token.component';
import { VerifyRecoverDeleteComponent } from './accounts/verify-recover-delete.component';
import { BulkConfirmComponent as OrgBulkConfirmComponent } from './organizations/manage/bulk/bulk-confirm.component';
import { BulkRemoveComponent as OrgBulkRemoveComponent } from './organizations/manage/bulk/bulk-remove.component';
import { BulkStatusComponent as OrgBulkStatusComponent } from './organizations/manage/bulk/bulk-status.component';
import {
CollectionAddEditComponent as OrgCollectionAddEditComponent,
} from './organizations/manage/collection-add-edit.component';
@@ -54,7 +53,6 @@ import { ManageComponent as OrgManageComponent } from './organizations/manage/ma
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 { ResetPasswordComponent as OrgResetPasswordComponent } from './organizations/manage/reset-password.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';
@@ -171,47 +169,40 @@ import { SendInfoComponent } from './vault/send-info.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 { 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 { 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 { 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 {
DatePipe,
registerLocaleData,
} from '@angular/common';
import localeBg from '@angular/common/locales/bg';
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 localeEl from '@angular/common/locales/el';
import localeEnGb from '@angular/common/locales/en-GB';
import localeEnIn from '@angular/common/locales/en-IN';
import localeEo from '@angular/common/locales/eo';
import localeEs from '@angular/common/locales/es';
import localeEt from '@angular/common/locales/et';
import localeFi from '@angular/common/locales/fi';
import localeFr from '@angular/common/locales/fr';
import localeHe from '@angular/common/locales/he';
import localeHr from '@angular/common/locales/hr';
import localeHu from '@angular/common/locales/hu';
import localeId from '@angular/common/locales/id';
import localeIt from '@angular/common/locales/it';
import localeJa from '@angular/common/locales/ja';
import localeKo from '@angular/common/locales/ko';
@@ -222,33 +213,23 @@ 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 localeRo from '@angular/common/locales/ro';
import localeRu from '@angular/common/locales/ru';
import localeSk from '@angular/common/locales/sk';
import localeSr from '@angular/common/locales/sr';
import localeSv from '@angular/common/locales/sv';
import localeTr from '@angular/common/locales/tr';
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(localeBg, 'bg');
registerLocaleData(localeDa, 'da');
registerLocaleData(localeDe, 'de');
registerLocaleData(localeEl, 'el');
registerLocaleData(localeEnGb, 'en-GB');
registerLocaleData(localeEnIn, 'en-IN');
registerLocaleData(localeEs, 'es');
registerLocaleData(localeEt, 'et');
registerLocaleData(localeEo, 'eo');
registerLocaleData(localeFi, 'fi');
registerLocaleData(localeFr, 'fr');
registerLocaleData(localeHe, 'he');
registerLocaleData(localeHr, 'hr');
registerLocaleData(localeHu, 'hu');
registerLocaleData(localeId, 'id');
registerLocaleData(localeIt, 'it');
registerLocaleData(localeJa, 'ja');
registerLocaleData(localeKo, 'ko');
@@ -259,12 +240,9 @@ registerLocaleData(localeNl, 'nl');
registerLocaleData(localePl, 'pl');
registerLocaleData(localePtBr, 'pt-BR');
registerLocaleData(localePtPt, 'pt-PT');
registerLocaleData(localeRo, 'ro');
registerLocaleData(localeRu, 'ru');
registerLocaleData(localeSk, 'sk');
registerLocaleData(localeSr, 'sr');
registerLocaleData(localeSv, 'sv');
registerLocaleData(localeTr, 'tr');
registerLocaleData(localeUk, 'uk');
registerLocaleData(localeZhCn, 'zh-CN');
registerLocaleData(localeZhTw, 'zh-TW');
@@ -352,9 +330,6 @@ registerLocaleData(localeZhTw, 'zh-TW');
OrganizationPlansComponent,
OrganizationSubscriptionComponent,
OrgAttachmentsComponent,
OrgBulkStatusComponent,
OrgBulkConfirmComponent,
OrgBulkRemoveComponent,
OrgCiphersComponent,
OrgCollectionAddEditComponent,
OrgCollectionsComponent,
@@ -373,7 +348,6 @@ registerLocaleData(localeZhTw, 'zh-TW');
OrgPeopleComponent,
OrgPolicyEditComponent,
OrgPoliciesComponent,
OrgResetPasswordComponent,
OrgReusedPasswordsReportComponent,
OrgSettingComponent,
OrgToolsComponent,
@@ -455,16 +429,12 @@ registerLocaleData(localeZhTw, 'zh-TW');
ModalComponent,
OrgAddEditComponent,
OrgAttachmentsComponent,
OrgBulkStatusComponent,
OrgBulkConfirmComponent,
OrgBulkRemoveComponent,
OrgCollectionAddEditComponent,
OrgCollectionsComponent,
OrgEntityEventsComponent,
OrgEntityUsersComponent,
OrgGroupAddEditComponent,
OrgPolicyEditComponent,
OrgResetPasswordComponent,
OrgUserAddEditComponent,
OrgUserConfirmComponent,
OrgUserGroupsComponent,
@@ -481,7 +451,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
TwoFactorYubiKeyComponent,
UpdateKeyComponent,
],
providers: [DatePipe, SearchPipe],
providers: [DatePipe],
bootstrap: [AppComponent],
})
export class AppModule { }

View File

@@ -6,10 +6,10 @@ import {
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
import { StateService } from 'jslib/abstractions/state.service';
import { Utils } from 'jslib-common/misc/utils';
import { Utils } from 'jslib/misc/utils';
@Component({
selector: 'app-avatar',

View File

@@ -4,7 +4,7 @@ import {
OnChanges,
} from '@angular/core';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
@Component({
selector: 'app-password-strength',

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

@@ -3,7 +3,7 @@ import {
OnInit,
} from '@angular/core';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
@Component({
selector: 'app-footer',

View File

@@ -4,7 +4,7 @@ import {
OnInit,
} from '@angular/core';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
@Component({
selector: 'app-frontend-layout',

View File

@@ -3,9 +3,9 @@ import {
OnInit,
} from '@angular/core';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { TokenService } from 'jslib-common/abstractions/token.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { TokenService } from 'jslib/abstractions/token.service';
@Component({
selector: 'app-navbar',

View File

@@ -7,14 +7,14 @@ import {
import { ActivatedRoute } from '@angular/router';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service';
import { Organization } from 'jslib-common/models/domain/organization';
import { Organization } from 'jslib/models/domain/organization';
const BroadcasterSubscriptionId = 'OrganizationLayoutComponent';

View File

@@ -7,10 +7,10 @@ import {
ViewContainerRef,
} from '@angular/core';
import { ModalComponent as BaseModalComponent } from 'jslib-angular/components/modal.component';
import { Utils } from 'jslib-common/misc/utils';
import { ModalComponent as BaseModalComponent } from 'jslib/angular/components/modal.component';
import { Utils } from 'jslib/misc/utils';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
@Component({
selector: 'app-modal',

View File

@@ -1,100 +0,0 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="bulkTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="bulkTitle">
{{'confirmUsers' | i18n}}
</h2>
<button type="button" class="close" data-dismiss="modal" appA11yTitle="{{'close' | i18n}}">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="card-body text-center" *ngIf="loading">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
{{'loading' | i18n}}
</div>
<app-callout type="danger" *ngIf="filteredUsers.length <= 0">
{{'noSelectedUsersApplicable' | i18n}}
</app-callout>
<app-callout type="error" *ngIf="error">
{{error}}
</app-callout>
<ng-container *ngIf="!loading && !done">
<p>
{{'fingerprintEnsureIntegrityVerify' | i18n}}
<a href="https://help.bitwarden.com/article/fingerprint-phrase/" target="_blank" rel="noopener">
{{'learnMore' | i18n}}</a>
</p>
<table class="table table-hover table-list">
<thead>
<tr>
<th colspan="2">{{'user' | i18n}}</th>
<th>{{'fingerprint' | i18n}}</th>
</tr>
</thead>
<tr *ngFor="let user of filteredUsers">
<td width="30">
<app-avatar [data]="user.name || user.email" [email]="user.email" size="25" [circle]="true"
[fontSize]="14"></app-avatar>
</td>
<td>
{{user.email}}
<small class="text-muted d-block" *ngIf="user.name">{{user.name}}</small>
</td>
<td>
{{fingerprints.get(user.id)}}
</td>
</tr>
<tr *ngFor="let user of excludedUsers">
<td width="30">
<app-avatar [data]="user.name || user.email" [email]="user.email" size="25" [circle]="true"
[fontSize]="14"></app-avatar>
</td>
<td>
{{user.email}}
<small class="text-muted d-block" *ngIf="user.name">{{user.name}}</small>
</td>
<td>
{{'bulkFilteredMessage' | i18n}}
</td>
</tr>
</table>
</ng-container>
<ng-container *ngIf="!loading && done">
<table class="table table-hover table-list">
<thead>
<tr>
<th colspan="2">{{'user' | i18n}}</th>
<th>{{'status' | i18n}}</th>
</tr>
</thead>
<tr *ngFor="let user of filteredUsers">
<td width="30">
<app-avatar [data]="user.name || user.email" [email]="user.email" size="25" [circle]="true"
[fontSize]="14"></app-avatar>
</td>
<td>
{{user.email}}
<small class="text-muted d-block" *ngIf="user.name">{{user.name}}</small>
</td>
<td *ngIf="statuses.has(user.id)">
{{statuses.get(user.id)}}
</td>
<td *ngIf="!statuses.has(user.id)">
{{'bulkFilteredMessage' | i18n}}
</td>
</tr>
</table>
</ng-container>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-submit" *ngIf="!done" [disabled]="loading" (click)="submit()">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
<span>{{'confirm' | i18n}}</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">{{'close' | i18n}}</button>
</div>
</div>
</div>
</div>

View File

@@ -1,95 +0,0 @@
import {
Component,
Input,
OnInit,
} from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { OrganizationUserBulkConfirmRequest } from 'jslib-common/models/request/organizationUserBulkConfirmRequest';
import { OrganizationUserBulkRequest } from 'jslib-common/models/request/organizationUserBulkRequest';
import { OrganizationUserUserDetailsResponse } from 'jslib-common/models/response/organizationUserResponse';
import { OrganizationUserStatusType } from 'jslib-common/enums/organizationUserStatusType';
import { Utils } from 'jslib-common/misc/utils';
@Component({
selector: 'app-bulk-confirm',
templateUrl: 'bulk-confirm.component.html',
})
export class BulkConfirmComponent implements OnInit {
@Input() organizationId: string;
@Input() users: OrganizationUserUserDetailsResponse[];
excludedUsers: OrganizationUserUserDetailsResponse[];
filteredUsers: OrganizationUserUserDetailsResponse[];
publicKeys: Map<string, Uint8Array> = new Map();
fingerprints: Map<string, string> = new Map();
statuses: Map<string, string> = new Map();
loading: boolean = true;
done: boolean = false;
error: string;
constructor(private cryptoService: CryptoService, private apiService: ApiService,
private i18nService: I18nService) { }
async ngOnInit() {
this.excludedUsers = this.users.filter(user => user.status !== OrganizationUserStatusType.Accepted);
this.filteredUsers = this.users.filter(user => user.status === OrganizationUserStatusType.Accepted);
if (this.filteredUsers.length <= 0) {
this.done = true;
}
const request = new OrganizationUserBulkRequest(this.filteredUsers.map(user => user.id));
const response = await this.apiService.postOrganizationUsersPublicKey(this.organizationId, request);
for (const entry of response.data) {
const publicKey = Utils.fromB64ToArray(entry.key);
const fingerprint = await this.cryptoService.getFingerprint(entry.userId, publicKey.buffer);
if (fingerprint != null) {
this.publicKeys.set(entry.id, publicKey);
this.fingerprints.set(entry.id, fingerprint.join('-'));
}
}
this.loading = false;
}
async submit() {
this.loading = true;
try {
const orgKey = await this.cryptoService.getOrgKey(this.organizationId);
const userIdsWithKeys: any[] = [];
for (const user of this.filteredUsers) {
const publicKey = this.publicKeys.get(user.id);
if (publicKey == null) {
continue;
}
const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey.buffer);
userIdsWithKeys.push({
id: user.id,
key: key.encryptedString,
});
}
const request = new OrganizationUserBulkConfirmRequest(userIdsWithKeys);
const response = await this.apiService.postOrganizationUserBulkConfirm(this.organizationId, request);
response.data.forEach(entry => {
const error = entry.error !== '' ? entry.error : this.i18nService.t('bulkConfirmMessage');
this.statuses.set(entry.id, error);
});
this.done = true;
} catch (e) {
this.error = e.message;
}
this.loading = false;
}
}

View File

@@ -1,81 +0,0 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="bulkTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="bulkTitle">
{{'removeUsers' | i18n}}
</h2>
<button type="button" class="close" data-dismiss="modal" appA11yTitle="{{'close' | i18n}}">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="card-body text-center" *ngIf="loading">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
{{'loading' | i18n}}
</div>
<app-callout type="danger" *ngIf="users.length <= 0">
{{'noSelectedUsersApplicable' | i18n}}
</app-callout>
<app-callout type="error" *ngIf="error">
{{error}}
</app-callout>
<ng-container *ngIf="!loading && !done">
<app-callout type="warning" *ngIf="users.length > 0 && !error">
{{'removeUsersWarning' | i18n}}
</app-callout>
<table class="table table-hover table-list">
<thead>
<tr>
<th colspan="2">{{'user' | i18n}}</th>
</tr>
</thead>
<tr *ngFor="let user of users">
<td width="30">
<app-avatar [data]="user.name || user.email" [email]="user.email" size="25" [circle]="true"
[fontSize]="14"></app-avatar>
</td>
<td>
{{user.email}}
<small class="text-muted d-block" *ngIf="user.name">{{user.name}}</small>
</td>
</tr>
</table>
</ng-container>
<ng-container *ngIf="!loading && done">
<table class="table table-hover table-list">
<thead>
<tr>
<th colspan="2">{{'user' | i18n}}</th>
<th>{{'status' | i18n}}</th>
</tr>
</thead>
<tr *ngFor="let user of users">
<td width="30">
<app-avatar [data]="user.name || user.email" [email]="user.email" size="25" [circle]="true"
[fontSize]="14"></app-avatar>
</td>
<td>
{{user.email}}
<small class="text-muted d-block" *ngIf="user.name">{{user.name}}</small>
</td>
<td *ngIf="statuses.has(user.id)">
{{statuses.get(user.id)}}
</td>
<td *ngIf="!statuses.has(user.id)">
{{'bulkFilteredMessage' | i18n}}
</td>
</tr>
</table>
</ng-container>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-submit" *ngIf="!done && users.length > 0" [disabled]="loading" (click)="submit()">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
<span>{{'removeUsers' | i18n}}</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">{{'close' | i18n}}</button>
</div>
</div>
</div>
</div>

View File

@@ -1,46 +0,0 @@
import {
Component,
Input,
} from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { OrganizationUserBulkRequest } from 'jslib-common/models/request/organizationUserBulkRequest';
import { OrganizationUserUserDetailsResponse } from 'jslib-common/models/response/organizationUserResponse';
@Component({
selector: 'app-bulk-remove',
templateUrl: 'bulk-remove.component.html',
})
export class BulkRemoveComponent {
@Input() organizationId: string;
@Input() users: OrganizationUserUserDetailsResponse[];
statuses: Map<string, string> = new Map();
loading: boolean = false;
done: boolean = false;
error: string;
constructor(private apiService: ApiService, private i18nService: I18nService) { }
async submit() {
this.loading = true;
try {
const request = new OrganizationUserBulkRequest(this.users.map(user => user.id));
const response = await this.apiService.deleteManyOrganizationUsers(this.organizationId, request);
response.data.forEach(entry => {
const error = entry.error !== '' ? entry.error : this.i18nService.t('bulkRemovedMessage');
this.statuses.set(entry.id, error);
});
this.done = true;
} catch (e) {
this.error = e.message;
}
this.loading = false;
}
}

View File

@@ -1,47 +0,0 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="bulkTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="bulkTitle">
{{'bulkConfirmStatus' | i18n}}
</h2>
<button type="button" class="close" data-dismiss="modal" appA11yTitle="{{'close' | i18n}}">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="card-body text-center" *ngIf="loading">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
{{'loading' | i18n}}
</div>
<table class="table table-hover table-list" *ngIf="!loading">
<thead>
<tr>
<th colspan="2">{{'user' | i18n}}</th>
<th>{{'status' | i18n}}</th>
</tr>
</thead>
<tr *ngFor="let item of users">
<td width="30">
<app-avatar [data]="item.user.name || item.user.email" [email]="item.user.email" size="25" [circle]="true"
[fontSize]="14"></app-avatar>
</td>
<td>
{{item.user.email}}
<small class="text-muted d-block" *ngIf="item.user.name">{{item.user.name}}</small>
</td>
<td class="text-danger" *ngIf="item.error">
{{item.message}}
</td>
<td *ngIf="!item.error">
{{item.message}}
</td>
</tr>
</table>
</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

@@ -1,20 +0,0 @@
import { Component } from '@angular/core';
import { OrganizationUserUserDetailsResponse } from 'jslib-common/models/response/organizationUserResponse';
type BulkStatusEntry = {
user: OrganizationUserUserDetailsResponse,
error: boolean,
message: string,
};
@Component({
selector: 'app-bulk-status',
templateUrl: 'bulk-status.component.html',
})
export class BulkStatusComponent {
users: BulkStatusEntry[];
loading: boolean = false;
}

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="collectionAddEditTitle">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-dialog" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
<div class="modal-header">
<h2 class="modal-title" id="collectionAddEditTitle">{{title}}</h2>

View File

@@ -8,19 +8,19 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service';
import { EncString } from 'jslib-common/models/domain/encString';
import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey';
import { CollectionRequest } from 'jslib-common/models/request/collectionRequest';
import { SelectionReadOnlyRequest } from 'jslib-common/models/request/selectionReadOnlyRequest';
import { GroupResponse } from 'jslib-common/models/response/groupResponse';
import { EncString } from 'jslib/models/domain/encString';
import { SymmetricCryptoKey } from 'jslib/models/domain/symmetricCryptoKey';
import { CollectionRequest } from 'jslib/models/request/collectionRequest';
import { SelectionReadOnlyRequest } from 'jslib/models/request/selectionReadOnlyRequest';
import { GroupResponse } from 'jslib/models/response/groupResponse';
import { Utils } from 'jslib-common/misc/utils';
import { Utils } from 'jslib/misc/utils';
@Component({
selector: 'app-collection-add-edit',

View File

@@ -9,21 +9,21 @@ import { ActivatedRoute } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CollectionService } from 'jslib-common/abstractions/collection.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { SearchService } from 'jslib-common/abstractions/search.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CollectionService } from 'jslib/abstractions/collection.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { SearchService } from 'jslib/abstractions/search.service';
import { UserService } from 'jslib/abstractions/user.service';
import { CollectionData } from 'jslib-common/models/data/collectionData';
import { Collection } from 'jslib-common/models/domain/collection';
import { CollectionData } from 'jslib/models/data/collectionData';
import { Collection } from 'jslib/models/domain/collection';
import {
CollectionDetailsResponse,
CollectionResponse,
} from 'jslib-common/models/response/collectionResponse';
import { ListResponse } from 'jslib-common/models/response/listResponse';
import { CollectionView } from 'jslib-common/models/view/collectionView';
} from 'jslib/models/response/collectionResponse';
import { ListResponse } from 'jslib/models/response/listResponse';
import { CollectionView } from 'jslib/models/view/collectionView';
import { ModalComponent } from '../../modal.component';
import { CollectionAddEditComponent } from './collection-add-edit.component';

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="eventLogsTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="eventLogsTitle">

View File

@@ -6,13 +6,13 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { EventService } from '../../services/event.service';
import { EventResponse } from 'jslib-common/models/response/eventResponse';
import { ListResponse } from 'jslib-common/models/response/listResponse';
import { EventResponse } from 'jslib/models/response/eventResponse';
import { ListResponse } from 'jslib/models/response/listResponse';
@Component({
selector: 'app-entity-events',
@@ -94,9 +94,9 @@ export class EntityEventsComponent implements OnInit {
} catch { }
this.continuationToken = response.continuationToken;
const events = await Promise.all(response.data.map(async r => {
const events = response.data.map(r => {
const userId = r.actingUserId == null ? r.userId : r.actingUserId;
const eventInfo = await this.eventService.getEventInfo(r);
const eventInfo = this.eventService.getEventInfo(r);
const user = this.showUser && userId != null && this.orgUsersUserIdMap.has(userId) ?
this.orgUsersUserIdMap.get(userId) : null;
return {
@@ -110,7 +110,7 @@ export class EntityEventsComponent implements OnInit {
ip: r.ipAddress,
type: r.type,
};
}));
});
if (!clearExisting && this.events != null && this.events.length > 0) {
this.events = this.events.concat(events);

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="userAccessTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-dialog modal-lg" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
<div class="modal-header">
<h2 class="modal-title" id="userAccessTitle">

View File

@@ -8,15 +8,15 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { OrganizationUserStatusType } from 'jslib-common/enums/organizationUserStatusType';
import { OrganizationUserType } from 'jslib-common/enums/organizationUserType';
import { SelectionReadOnlyRequest } from 'jslib-common/models/request/selectionReadOnlyRequest';
import { OrganizationUserUserDetailsResponse } from 'jslib-common/models/response/organizationUserResponse';
import { OrganizationUserStatusType } from 'jslib/enums/organizationUserStatusType';
import { OrganizationUserType } from 'jslib/enums/organizationUserType';
import { SelectionReadOnlyRequest } from 'jslib/models/request/selectionReadOnlyRequest';
import { OrganizationUserUserDetailsResponse } from 'jslib/models/response/organizationUserResponse';
import { Utils } from 'jslib-common/misc/utils';
import { Utils } from 'jslib/misc/utils';
@Component({
selector: 'app-entity-users',

View File

@@ -4,29 +4,17 @@
<div class="form-inline">
<label class="sr-only" for="start">{{'startDate' | i18n}}</label>
<input type="datetime-local" class="form-control form-control-sm" id="start"
placeholder="{{'startDate' | i18n}}" [(ngModel)]="start" placeholder="YYYY-MM-DDTHH:MM"
(change)="dirtyDates = true">
placeholder="{{'startDate' | i18n}}" [(ngModel)]="start" placeholder="YYYY-MM-DDTHH:MM">
<span class="mx-2">-</span>
<label class="sr-only" for="end">{{'endDate' | i18n}}</label>
<input type="datetime-local" class="form-control form-control-sm" id="end"
placeholder="{{'endDate' | i18n}}" [(ngModel)]="end" placeholder="YYYY-MM-DDTHH:MM"
(change)="dirtyDates = true">
placeholder="{{'endDate' | i18n}}" [(ngModel)]="end" placeholder="YYYY-MM-DDTHH:MM">
</div>
<form #refreshForm [appApiAction]="refreshPromise" class="d-inline">
<button type="button" class="btn btn-sm btn-outline-primary ml-3" (click)="loadEvents(true)"
[disabled]="loaded && refreshForm.loading">
<i class="fa fa-refresh fa-fw" aria-hidden="true" [ngClass]="{'fa-spin': loaded && refreshForm.loading}"></i>
{{'refresh' | i18n}}
</button>
</form>
<form #exportForm [appApiAction]="exportPromise" class="d-inline">
<button type="button" class="btn btn-sm btn-outline-primary btn-submit manual ml-3"
[ngClass]="{loading:exportForm.loading}" (click)="exportEvents()"
[disabled]="loaded && exportForm.loading || dirtyDates">
<i class="fa fa-spinner fa-spin" aria-hidden="true"></i>
<span>{{'export' | i18n}}</span>
</button>
</form>
<button #refreshBtn [appApiAction]="refreshPromise" type="button" class="btn btn-sm btn-outline-primary ml-3"
(click)="loadEvents(true)" [disabled]="loaded && refreshBtn.loading">
<i class="fa fa-refresh fa-fw" aria-hidden="true" [ngClass]="{'fa-spin': loaded && refreshBtn.loading}"></i>
{{'refresh' | i18n}}
</button>
</div>
</div>
<ng-container *ngIf="!loaded">

View File

@@ -6,18 +6,15 @@ import { ActivatedRoute, Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { ExportService } from 'jslib-common/abstractions/export.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { EventResponse } from 'jslib-common/models/response/eventResponse';
import { ListResponse } from 'jslib-common/models/response/listResponse';
import { EventView } from 'jslib-common/models/view/eventView';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { UserService } from 'jslib/abstractions/user.service';
import { EventService } from '../../services/event.service';
import { EventResponse } from 'jslib/models/response/eventResponse';
import { ListResponse } from 'jslib/models/response/listResponse';
@Component({
selector: 'app-org-events',
templateUrl: 'events.component.html',
@@ -26,21 +23,19 @@ export class EventsComponent implements OnInit {
loading = true;
loaded = false;
organizationId: string;
events: EventView[];
events: any[];
start: string;
end: string;
dirtyDates: boolean = true;
continuationToken: string;
refreshPromise: Promise<any>;
exportPromise: Promise<any>;
morePromise: Promise<any>;
private orgUsersUserIdMap = new Map<string, any>();
private orgUsersIdMap = new Map<string, any>();
constructor(private apiService: ApiService, private route: ActivatedRoute, private eventService: EventService,
private i18nService: I18nService, private toasterService: ToasterService, private userService: UserService,
private exportService: ExportService, private platformUtilsService: PlatformUtilsService,
constructor(private apiService: ApiService, private route: ActivatedRoute,
private eventService: EventService, private i18nService: I18nService,
private toasterService: ToasterService, private userService: UserService,
private router: Router) { }
async ngOnInit() {
@@ -69,91 +64,41 @@ export class EventsComponent implements OnInit {
this.loaded = true;
}
async exportEvents() {
if (this.appApiPromiseUnfulfilled() || this.dirtyDates) {
return;
}
this.loading = true;
const dates = this.parseDates();
if (dates == null) {
return;
}
try {
this.exportPromise = this.export(dates[0], dates[1]);
await this.exportPromise;
} catch { }
this.exportPromise = null;
this.loading = false;
}
async loadEvents(clearExisting: boolean) {
if (this.appApiPromiseUnfulfilled()) {
if (this.refreshPromise != null || this.morePromise != null) {
return;
}
const dates = this.parseDates();
if (dates == null) {
let dates: string[] = null;
try {
dates = this.eventService.formatDateFilters(this.start, this.end);
} catch (e) {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('invalidDateRange'));
return;
}
this.loading = true;
let events: EventView[] = [];
let response: ListResponse<EventResponse>;
try {
const promise = this.loadAndParseEvents(dates[0], dates[1], clearExisting ? null : this.continuationToken);
const promise = this.apiService.getEventsOrganization(this.organizationId, dates[0], dates[1],
clearExisting ? null : this.continuationToken);
if (clearExisting) {
this.refreshPromise = promise;
} else {
this.morePromise = promise;
}
const result = await promise;
this.continuationToken = result.continuationToken;
events = result.events;
response = await promise;
} catch { }
if (!clearExisting && this.events != null && this.events.length > 0) {
this.events = this.events.concat(events);
} else {
this.events = events;
}
this.dirtyDates = false;
this.loading = false;
this.morePromise = null;
this.refreshPromise = null;
}
private async export(start: string, end: string) {
let continuationToken = this.continuationToken;
let events = [].concat(this.events);
while (continuationToken != null) {
const result = await this.loadAndParseEvents(start, end, continuationToken);
continuationToken = result.continuationToken;
events = events.concat(result.events);
}
const data = await this.exportService.getEventExport(events);
const fileName = this.exportService.getFileName('org-events', 'csv');
this.platformUtilsService.saveFile(window, data, { type: 'text/plain' }, fileName);
}
private async loadAndParseEvents(startDate: string, endDate: string, continuationToken: string) {
const response = await this.apiService.getEventsOrganization(this.organizationId, startDate, endDate,
continuationToken);
const events = await Promise.all(response.data.map(async r => {
this.continuationToken = response.continuationToken;
const events = response.data.map(r => {
const userId = r.actingUserId == null ? r.userId : r.actingUserId;
const eventInfo = await this.eventService.getEventInfo(r);
const eventInfo = this.eventService.getEventInfo(r);
const user = userId != null && this.orgUsersUserIdMap.has(userId) ?
this.orgUsersUserIdMap.get(userId) : null;
return new EventView({
return {
message: eventInfo.message,
humanReadableMessage: eventInfo.humanReadableMessage,
appIcon: eventInfo.appIcon,
appName: eventInfo.appName,
userId: userId,
@@ -162,24 +107,17 @@ export class EventsComponent implements OnInit {
date: r.date,
ip: r.ipAddress,
type: r.type,
});
}));
return { continuationToken: response.continuationToken, events: events };
}
};
});
private parseDates() {
let dates: string[] = null;
try {
dates = this.eventService.formatDateFilters(this.start, this.end);
} catch (e) {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('invalidDateRange'));
return null;
if (!clearExisting && this.events != null && this.events.length > 0) {
this.events = this.events.concat(events);
} else {
this.events = events;
}
return dates;
}
private appApiPromiseUnfulfilled() {
return this.refreshPromise != null || this.morePromise != null || this.exportPromise != null;
this.loading = false;
this.morePromise = null;
this.refreshPromise = null;
}
}

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="groupAddEditTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-dialog modal-lg" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
<div class="modal-header">
<h2 class="modal-title" id="groupAddEditTitle">{{title}}</h2>

View File

@@ -8,17 +8,17 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CollectionService } from 'jslib-common/abstractions/collection.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CollectionService } from 'jslib/abstractions/collection.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { CollectionData } from 'jslib-common/models/data/collectionData';
import { Collection } from 'jslib-common/models/domain/collection';
import { GroupRequest } from 'jslib-common/models/request/groupRequest';
import { SelectionReadOnlyRequest } from 'jslib-common/models/request/selectionReadOnlyRequest';
import { CollectionDetailsResponse } from 'jslib-common/models/response/collectionResponse';
import { CollectionView } from 'jslib-common/models/view/collectionView';
import { CollectionData } from 'jslib/models/data/collectionData';
import { Collection } from 'jslib/models/domain/collection';
import { GroupRequest } from 'jslib/models/request/groupRequest';
import { SelectionReadOnlyRequest } from 'jslib/models/request/selectionReadOnlyRequest';
import { CollectionDetailsResponse } from 'jslib/models/response/collectionResponse';
import { CollectionView } from 'jslib/models/view/collectionView';
@Component({
selector: 'app-group-add-edit',

View File

@@ -12,15 +12,15 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { SearchService } from 'jslib-common/abstractions/search.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { SearchService } from 'jslib/abstractions/search.service';
import { UserService } from 'jslib/abstractions/user.service';
import { GroupResponse } from 'jslib-common/models/response/groupResponse';
import { GroupResponse } from 'jslib/models/response/groupResponse';
import { Utils } from 'jslib-common/misc/utils';
import { Utils } from 'jslib/misc/utils';
import { ModalComponent } from '../../modal.component';
import { EntityUsersComponent } from './entity-users.component';

View File

@@ -4,9 +4,9 @@ import {
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { UserService } from 'jslib-common/abstractions/user.service';
import { UserService } from 'jslib/abstractions/user.service';
import { Organization } from 'jslib-common/models/domain/organization';
import { Organization } from 'jslib/models/domain/organization';
@Component({
selector: 'app-org-manage',

View File

@@ -25,36 +25,6 @@
<input type="search" class="form-control form-control-sm" id="search" placeholder="{{'search' | i18n}}"
[(ngModel)]="searchText">
</div>
<div class="dropdown ml-3" appListDropdown>
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="bulkActionsButton"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" appA11yTitle="{{'options' | i18n}}">
<i class="fa fa-cog" aria-hidden="true"></i>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="bulkActionsButton">
<button class="dropdown-item" appStopClick (click)="bulkReinvite()">
<i class="fa fa-fw fa-envelope-o" aria-hidden="true"></i>
{{'reinviteSelected' | i18n}}
</button>
<button class="dropdown-item text-success" appStopClick (click)="bulkConfirm()"
*ngIf="showBulkConfirmUsers">
<i class="fa fa-fw fa-check" aria-hidden="true"></i>
{{'confirmSelected' | i18n}}
</button>
<button class="dropdown-item text-danger" appStopClick (click)="bulkRemove()">
<i class="fa fa-fw fa-remove" aria-hidden="true"></i>
{{'remove' | i18n}}
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item" appStopClick (click)="selectAll(true)">
<i class="fa fa-fw fa-check-square-o" aria-hidden="true"></i>
{{'selectAll' | i18n}}
</button>
<button class="dropdown-item" appStopClick (click)="selectAll(false)">
<i class="fa fa-fw fa-minus-square-o" aria-hidden="true"></i>
{{'unselectAll' | i18n}}
</button>
</div>
</div>
<button type="button" class="btn btn-sm btn-outline-primary ml-3" (click)="invite()">
<i class="fa fa-plus fa-fw" aria-hidden="true"></i>
{{'inviteUser' | i18n}}
@@ -76,9 +46,6 @@
[infiniteScrollDisabled]="!isPaging()" (scrolled)="loadMore()">
<tbody>
<tr *ngFor="let u of searchedUsers">
<td (click)="checkUser(u)" class="table-list-checkbox">
<input type="checkbox" [(ngModel)]="u.checked" appStopProp>
</td>
<td width="30">
<app-avatar [data]="u.name || u.email" [email]="u.email" size="25" [circle]="true"
[fontSize]="14"></app-avatar>
@@ -96,10 +63,6 @@
<i class="fa fa-lock" title="{{'userUsingTwoStep' | i18n}}" aria-hidden="true"></i>
<span class="sr-only">{{'userUsingTwoStep' | i18n}}</span>
</ng-container>
<ng-container *ngIf="showEnrolledStatus(u)">
<i class="fa fa-key" title="{{'enrolledPasswordReset' | i18n}}" aria-hidden="true"></i>
<span class="sr-only">{{'enrolledPasswordReset' | i18n}}</span>
</ng-container>
</td>
<td>
<span *ngIf="u.type === organizationUserType.Owner">{{'owner' | i18n}}</span>
@@ -135,11 +98,6 @@
<i class="fa fa-fw fa-file-text-o" aria-hidden="true"></i>
{{'eventLogs' | i18n}}
</a>
<a class="dropdown-item" href="#" appStopClick (click)="resetPassword(u)"
*ngIf="allowResetPassword(u)">
<i class="fa fa-fw fa-key" aria-hidden="true"></i>
{{'resetPassword' | i18n}}
</a>
<a class="dropdown-item text-danger" href="#" appStopClick (click)="remove(u)">
<i class="fa fa-fw fa-remove" aria-hidden="true"></i>
{{'remove' | i18n}}
@@ -156,7 +114,3 @@
<ng-template #groupsTemplate></ng-template>
<ng-template #eventsTemplate></ng-template>
<ng-template #confirmTemplate></ng-template>
<ng-template #resetPasswordTemplate></ng-template>
<ng-template #bulkStatusTemplate></ng-template>
<ng-template #bulkConfirmTemplate></ng-template>
<ng-template #bulkRemoveTemplate></ng-template>

View File

@@ -5,7 +5,6 @@ import {
ViewChild,
ViewContainerRef,
} from '@angular/core';
import {
ActivatedRoute,
Router,
@@ -13,47 +12,32 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ValidationService } from 'jslib-angular/services/validation.service';
import { ConstantsService } from 'jslib-common/services/constants.service';
import { ValidationService } from 'jslib/angular/services/validation.service';
import { ConstantsService } from 'jslib/services/constants.service';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { SearchService } from 'jslib-common/abstractions/search.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { SearchService } from 'jslib/abstractions/search.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { UserService } from 'jslib/abstractions/user.service';
import { OrganizationKeysRequest } from 'jslib-common/models/request/organizationKeysRequest';
import { OrganizationUserBulkRequest } from 'jslib-common/models/request/organizationUserBulkRequest';
import { OrganizationUserConfirmRequest } from 'jslib-common/models/request/organizationUserConfirmRequest';
import { OrganizationUserConfirmRequest } from 'jslib/models/request/organizationUserConfirmRequest';
import { ListResponse } from 'jslib-common/models/response/listResponse';
import { OrganizationUserBulkResponse } from 'jslib-common/models/response/organizationUserBulkResponse';
import { OrganizationUserUserDetailsResponse } from 'jslib-common/models/response/organizationUserResponse';
import { OrganizationUserUserDetailsResponse } from 'jslib/models/response/organizationUserResponse';
import { OrganizationUserStatusType } from 'jslib-common/enums/organizationUserStatusType';
import { OrganizationUserType } from 'jslib-common/enums/organizationUserType';
import { PolicyType } from 'jslib-common/enums/policyType';
import { OrganizationUserStatusType } from 'jslib/enums/organizationUserStatusType';
import { OrganizationUserType } from 'jslib/enums/organizationUserType';
import { SearchPipe } from 'jslib-angular/pipes/search.pipe';
import { Utils } from 'jslib-common/misc/utils';
import { Utils } from 'jslib/misc/utils';
import { ModalComponent } from '../../modal.component';
import { BulkConfirmComponent } from './bulk/bulk-confirm.component';
import { BulkRemoveComponent } from './bulk/bulk-remove.component';
import { BulkStatusComponent } from './bulk/bulk-status.component';
import { EntityEventsComponent } from './entity-events.component';
import { ResetPasswordComponent } from './reset-password.component';
import { UserAddEditComponent } from './user-add-edit.component';
import { UserConfirmComponent } from './user-confirm.component';
import { UserGroupsComponent } from './user-groups.component';
const MaxCheckedCount = 500;
@Component({
selector: 'app-org-people',
templateUrl: 'people.component.html',
@@ -63,10 +47,6 @@ export class PeopleComponent implements OnInit {
@ViewChild('groupsTemplate', { read: ViewContainerRef, static: true }) groupsModalRef: ViewContainerRef;
@ViewChild('eventsTemplate', { read: ViewContainerRef, static: true }) eventsModalRef: ViewContainerRef;
@ViewChild('confirmTemplate', { read: ViewContainerRef, static: true }) confirmModalRef: ViewContainerRef;
@ViewChild('resetPasswordTemplate', { read: ViewContainerRef, static: true }) resetPasswordModalRef: ViewContainerRef;
@ViewChild('bulkStatusTemplate', { read: ViewContainerRef, static: true }) bulkStatusModalRef: ViewContainerRef;
@ViewChild('bulkConfirmTemplate', { read: ViewContainerRef, static: true }) bulkConfirmModalRef: ViewContainerRef;
@ViewChild('bulkRemoveTemplate', { read: ViewContainerRef, static: true }) bulkRemoveModalRef: ViewContainerRef;
loading = true;
organizationId: string;
@@ -80,11 +60,6 @@ export class PeopleComponent implements OnInit {
actionPromise: Promise<any>;
accessEvents = false;
accessGroups = false;
canResetPassword = false; // User permission (admin/custom)
orgUseResetPassword = false; // Org plan ability
orgHasKeys = false; // Org public/private keys
orgResetPasswordPolicyEnabled = false;
callingUserType: OrganizationUserType = null;
protected didScroll = false;
protected pageSize = 100;
@@ -98,8 +73,7 @@ export class PeopleComponent implements OnInit {
private platformUtilsService: PlatformUtilsService, private toasterService: ToasterService,
private cryptoService: CryptoService, private userService: UserService, private router: Router,
private storageService: StorageService, private searchService: SearchService,
private validationService: ValidationService, private policyService: PolicyService,
private searchPipe: SearchPipe, private syncService: SyncService) { }
private validationService: ValidationService) { }
async ngOnInit() {
this.route.parent.parent.params.subscribe(async params => {
@@ -111,25 +85,6 @@ export class PeopleComponent implements OnInit {
}
this.accessEvents = organization.useEvents;
this.accessGroups = organization.useGroups;
this.canResetPassword = organization.canManageUsersPassword;
this.orgUseResetPassword = organization.useResetPassword;
this.callingUserType = organization.type;
this.orgHasKeys = organization.hasPublicAndPrivateKeys;
// Backfill pub/priv key if necessary
if (this.canResetPassword && !this.orgHasKeys) {
const orgShareKey = await this.cryptoService.getOrgKey(this.organizationId);
const orgKeys = await this.cryptoService.makeKeyPair(orgShareKey);
const request = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
const response = await this.apiService.postOrganizationKeys(this.organizationId, request);
if (response != null) {
this.orgHasKeys = response.publicKey != null && response.privateKey != null;
await this.syncService.fullSync(true); // Replace oganizations with new data
} else {
throw new Error(this.i18nService.t('resetPasswordOrgKeysError'));
}
}
await this.load();
const queryParamsSub = this.route.queryParams.subscribe(async qParams => {
@@ -160,38 +115,9 @@ export class PeopleComponent implements OnInit {
}
});
this.filter(this.status);
const policies = await this.policyService.getAll(PolicyType.ResetPassword);
this.orgResetPasswordPolicyEnabled = policies.some(p => p.organizationId === this.organizationId && p.enabled);
this.loading = false;
}
allowResetPassword(orgUser: OrganizationUserUserDetailsResponse): boolean {
// Hierarchy check
let callingUserHasPermission = false;
switch (this.callingUserType) {
case OrganizationUserType.Owner:
callingUserHasPermission = true;
break;
case OrganizationUserType.Admin:
callingUserHasPermission = orgUser.type !== OrganizationUserType.Owner;
break;
case OrganizationUserType.Custom:
callingUserHasPermission = orgUser.type !== OrganizationUserType.Owner
&& orgUser.type !== OrganizationUserType.Admin;
break;
}
// Final
return this.canResetPassword && callingUserHasPermission && this.orgUseResetPassword && this.orgHasKeys
&& orgUser.resetPasswordEnrolled && this.orgResetPasswordPolicyEnabled
&& orgUser.status === OrganizationUserStatusType.Confirmed;
}
showEnrolledStatus(orgUser: OrganizationUserUserDetailsResponse): boolean {
return this.orgUseResetPassword && orgUser.resetPasswordEnrolled && this.orgResetPasswordPolicyEnabled;
}
filter(status: OrganizationUserStatusType) {
this.status = status;
if (this.status != null) {
@@ -199,8 +125,6 @@ export class PeopleComponent implements OnInit {
} else {
this.users = this.allUsers;
}
// Reset checkbox selecton
this.selectAll(false);
this.resetPaging();
}
@@ -244,10 +168,6 @@ export class PeopleComponent implements OnInit {
this.confirmedCount > 0 && this.confirmedCount < 3 && this.acceptedCount > 0;
}
get showBulkConfirmUsers(): boolean {
return this.acceptedCount > 0;
}
edit(user: OrganizationUserUserDetailsResponse) {
if (this.modal != null) {
this.modal.close();
@@ -309,101 +229,23 @@ export class PeopleComponent implements OnInit {
return false;
}
this.actionPromise = this.apiService.deleteOrganizationUser(this.organizationId, user.id);
try {
await this.actionPromise;
await this.apiService.deleteOrganizationUser(this.organizationId, user.id);
this.toasterService.popAsync('success', null, this.i18nService.t('removedUserId', user.name || user.email));
this.removeUser(user);
} catch (e) {
this.validationService.showError(e);
}
this.actionPromise = null;
} catch { }
}
async reinvite(user: OrganizationUserUserDetailsResponse) {
if (this.actionPromise != null) {
return;
}
this.actionPromise = this.apiService.postOrganizationUserReinvite(this.organizationId, user.id);
try {
await this.actionPromise;
this.toasterService.popAsync('success', null, this.i18nService.t('hasBeenReinvited', user.name || user.email));
} catch (e) {
this.validationService.showError(e);
}
await this.actionPromise;
this.toasterService.popAsync('success', null, this.i18nService.t('hasBeenReinvited', user.name || user.email));
this.actionPromise = null;
}
async bulkRemove() {
if (this.actionPromise != null) {
return;
}
if (this.modal != null) {
this.modal.close();
}
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
this.modal = this.bulkRemoveModalRef.createComponent(factory).instance;
const childComponent = this.modal.show(BulkRemoveComponent, this.bulkRemoveModalRef);
childComponent.organizationId = this.organizationId;
childComponent.users = this.getCheckedUsers();
this.modal.onClosed.subscribe(async () => {
await this.load();
this.modal = null;
});
}
async bulkReinvite() {
if (this.actionPromise != null) {
return;
}
const users = this.getCheckedUsers();
const filteredUsers = users.filter(u => u.status === OrganizationUserStatusType.Invited);
if (filteredUsers.length <= 0) {
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('noSelectedUsersApplicable'));
return;
}
try {
const request = new OrganizationUserBulkRequest(filteredUsers.map(user => user.id));
const response = this.apiService.postManyOrganizationUserReinvite(this.organizationId, request);
this.showBulkStatus(users, filteredUsers, response, this.i18nService.t('bulkReinviteMessage'));
} catch (e) {
this.validationService.showError(e);
}
this.actionPromise = null;
}
async bulkConfirm() {
if (this.actionPromise != null) {
return;
}
if (this.modal != null) {
this.modal.close();
}
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
this.modal = this.bulkConfirmModalRef.createComponent(factory).instance;
const childComponent = this.modal.show(BulkConfirmComponent, this.bulkConfirmModalRef);
childComponent.organizationId = this.organizationId;
childComponent.users = this.getCheckedUsers();
this.modal.onClosed.subscribe(async () => {
await this.load();
this.modal = null;
});
}
async confirm(user: OrganizationUserUserDetailsResponse) {
function updateUser(self: PeopleComponent) {
user.status = OrganizationUserStatusType.Confirmed;
@@ -516,101 +358,6 @@ export class PeopleComponent implements OnInit {
return !searching && this.users && this.users.length > this.pageSize;
}
async resetPassword(user: OrganizationUserUserDetailsResponse) {
if (this.modal != null) {
this.modal.close();
}
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
this.modal = this.resetPasswordModalRef.createComponent(factory).instance;
const childComponent = this.modal.show<ResetPasswordComponent>(
ResetPasswordComponent, this.resetPasswordModalRef);
childComponent.name = user != null ? user.name || user.email : null;
childComponent.email = user != null ? user.email : null;
childComponent.organizationId = this.organizationId;
childComponent.id = user != null ? user.id : null;
childComponent.onPasswordReset.subscribe(() => {
this.modal.close();
this.load();
});
this.modal.onClosed.subscribe(() => {
this.modal = null;
});
}
checkUser(user: OrganizationUserUserDetailsResponse, select?: boolean) {
(user as any).checked = select == null ? !(user as any).checked : select;
}
selectAll(select: boolean) {
if (select) {
this.selectAll(false);
}
const filteredUsers = this.searchPipe.transform(this.users, this.searchText, 'name', 'email', 'id');
const selectCount = select && filteredUsers.length > MaxCheckedCount
? MaxCheckedCount
: filteredUsers.length;
for (let i = 0; i < selectCount; i++) {
this.checkUser(filteredUsers[i], select);
}
}
private async showBulkStatus(users: OrganizationUserUserDetailsResponse[], filteredUsers: OrganizationUserUserDetailsResponse[],
request: Promise<ListResponse<OrganizationUserBulkResponse>>, successfullMessage: string) {
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
this.modal = this.bulkStatusModalRef.createComponent(factory).instance;
const childComponent = this.modal.show<BulkStatusComponent>(
BulkStatusComponent, this.bulkStatusModalRef);
childComponent.loading = true;
// Workaround to handle closing the modal shortly after it has been opened
let close = false;
this.modal.onShown.subscribe(() => {
if (close) {
this.modal.close();
}
});
this.modal.onClosed.subscribe(() => {
this.modal = null;
});
try {
const response = await request;
if (this.modal) {
const keyedErrors: any = response.data.filter(r => r.error !== '').reduce((a, x) => ({ ...a, [x.id]: x.error }), {});
const keyedFilteredUsers: any = filteredUsers.reduce((a, x) => ({ ...a, [x.id]: x }), {});
childComponent.users = users.map(user => {
let message = keyedErrors[user.id] ?? successfullMessage;
if (!keyedFilteredUsers.hasOwnProperty(user.id)) {
message = this.i18nService.t('bulkFilteredMessage');
}
return {
user: user,
error: keyedErrors.hasOwnProperty(user.id),
message: message,
};
});
childComponent.loading = false;
}
} catch {
close = true;
if (this.modal) {
this.modal.close();
}
}
}
private async doConfirmation(user: OrganizationUserUserDetailsResponse, publicKey: Uint8Array) {
const orgKey = await this.cryptoService.getOrgKey(this.organizationId);
const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey.buffer);
@@ -644,8 +391,4 @@ export class PeopleComponent implements OnInit {
}
}
}
private getCheckedUsers() {
return this.users.filter(u => (u as any).checked);
}
}

View File

@@ -10,15 +10,15 @@ import {
Router,
} from '@angular/router';
import { PolicyType } from 'jslib-common/enums/policyType';
import { PolicyType } from 'jslib/enums/policyType';
import { EnvironmentService } from 'jslib-common/abstractions';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { EnvironmentService } from 'jslib/abstractions';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service';
import { PolicyResponse } from 'jslib-common/models/response/policyResponse';
import { PolicyResponse } from 'jslib/models/response/policyResponse';
import { ModalComponent } from '../../modal.component';
@@ -115,12 +115,6 @@ export class PoliciesComponent implements OnInit {
type: PolicyType.SendOptions,
enabled: false,
display: true,
}, {
name: this.i18nService.t('resetPasswordPolicy'),
description: this.i18nService.t('resetPasswordPolicyDescription'),
type: PolicyType.ResetPassword,
enabled: false,
display: organization.useResetPassword,
},
];
await this.load();

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="policiesEditTitle">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-dialog" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
<div class="modal-header">
<h2 class="modal-title" id="policiesEditTitle">{{'editPolicy' | i18n}} - {{name}}</h2>
@@ -38,9 +38,6 @@
<app-callout type="warning" *ngIf="type === policyType.SendOptions">
{{'sendOptionsExemption' | i18n}}
</app-callout>
<app-callout type="warning" *ngIf="type === policyType.ResetPassword">
{{'resetPasswordPolicyWarning' | i18n}}
</app-callout>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="enabled" [(ngModel)]="enabled"
@@ -156,33 +153,19 @@
<ng-container *ngIf="type === policyType.SendOptions">
<h3 class="mt-4">{{'options' | i18n}}</h3>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="sendDisableHideEmail"
[(ngModel)]="sendDisableHideEmail" name="SendDisableHideEmail">
<input class="form-check-input" type="checkbox" id="sendDisableHideEmail" [(ngModel)]="sendDisableHideEmail"
name="SendDisableHideEmail">
<label class="form-check-label" for="sendDisableHideEmail">{{'disableHideEmail' | i18n}}</label>
</div>
</ng-container>
<ng-container *ngIf="type === policyType.ResetPassword">
<h3 class="mt-4">{{'resetPasswordPolicyAutoEnroll' | i18n}}</h3>
<p>{{'resetPasswordPolicyAutoEnrollDescription' | i18n}}</p>
<app-callout type="warning">
{{'resetPasswordPolicyAutoEnrollWarning' | i18n}}
</app-callout>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="autoEnrollEnabled"
[(ngModel)]="resetPasswordAutoEnroll" name="AutoEnrollEnabled">
<label class="form-check-label"
for="autoEnrollEnabled">{{'resetPasswordPolicyAutoEnrollCheckbox' | i18n }}</label>
</div>
</ng-container>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
<span>{{'save' | i18n}}</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
{{'cancel' | i18n}}
</button>
<button type="button" class="btn btn-outline-secondary"
data-dismiss="modal">{{'cancel' | i18n}}</button>
</div>
</form>
</div>

View File

@@ -8,14 +8,14 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PolicyType } from 'jslib-common/enums/policyType';
import { PolicyType } from 'jslib/enums/policyType';
import { PolicyRequest } from 'jslib-common/models/request/policyRequest';
import { PolicyRequest } from 'jslib/models/request/policyRequest';
import { PolicyResponse } from 'jslib-common/models/response/policyResponse';
import { PolicyResponse } from 'jslib/models/response/policyResponse';
@Component({
selector: 'app-policy-edit',
@@ -60,9 +60,6 @@ export class PolicyEditComponent implements OnInit {
// Send options
sendDisableHideEmail?: boolean;
// Reset Password
resetPasswordAutoEnroll?: boolean;
private policy: PolicyResponse;
constructor(private apiService: ApiService, private i18nService: I18nService,
@@ -119,9 +116,6 @@ export class PolicyEditComponent implements OnInit {
case PolicyType.SendOptions:
this.sendDisableHideEmail = this.policy.data.disableHideEmail;
break;
case PolicyType.ResetPassword:
this.resetPasswordAutoEnroll = this.policy.data.autoEnrollEnabled;
break;
default:
break;
}
@@ -173,11 +167,6 @@ export class PolicyEditComponent implements OnInit {
disableHideEmail: this.sendDisableHideEmail,
};
break;
case PolicyType.ResetPassword:
request.data = {
autoEnrollEnabled: this.resetPasswordAutoEnroll,
};
break;
default:
break;
}

View File

@@ -1,78 +0,0 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="resetPasswordTitle">
<div class="modal-dialog" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
<div class="modal-header">
<h2 class="modal-title" id="resetPasswordTitle">
{{'resetPassword' | i18n}}
<small class="text-muted" *ngIf="name">{{name}}</small>
</h2>
<button type="button" class="close" data-dismiss="modal" appA11yTitle="{{'close' | i18n}}">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<app-callout type="warning">{{'resetPasswordLoggedOutWarning' | i18n: loggedOutWarningName}}
</app-callout>
<app-callout type="info" *ngIf="enforcedPolicyOptions">
{{'resetPasswordMasterPasswordPolicyInEffect' | 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>
<div class="row">
<div class="col form-group">
<div class="d-flex">
<label for="newPassword">{{'newPassword' | i18n}}</label>
<div class="ml-auto d-flex">
<a href="#" class="d-block mr-2 fa-icon-above-input" appStopClick
appA11yTitle="{{'generatePassword' | i18n}}" (click)="generatePassword()">
<i class="fa fa-lg fa-fw fa-refresh" aria-hidden="true"></i>
</a>
</div>
</div>
<div class="input-group mb-1">
<input id="newPassword" class="form-control text-monospace" appAutofocus
type="{{showPassword ? 'text' : 'password'}}" name="NewPassword"
[(ngModel)]="newPassword" required appInputVerbatim autocomplete="new-password"
(input)="updatePasswordStrength()">
<div class="input-group-append">
<button type="button" class="btn btn-outline-secondary"
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
<i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</button>
<button type="button" class="btn btn-outline-secondary"
appA11yTitle="{{'copyPassword' | i18n}}" (click)="copy(newPassword)">
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
</button>
</div>
</div>
<app-password-strength [score]="masterPasswordScore" [showText]="true">
</app-password-strength>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
<span>{{'save' | i18n}}</span>
</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">{{'cancel' |
i18n}}</button>
</div>
</form>
</div>
</div>

View File

@@ -1,191 +0,0 @@
import {
AfterViewInit,
Component,
EventEmitter,
Input,
OnInit,
Output,
} from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { EncString } from 'jslib-common/models/domain/encString';
import { MasterPasswordPolicyOptions } from 'jslib-common/models/domain/masterPasswordPolicyOptions';
import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey';
import { OrganizationUserResetPasswordRequest } from 'jslib-common/models/request/organizationUserResetPasswordRequest';
@Component({
selector: 'app-reset-password',
templateUrl: 'reset-password.component.html',
})
export class ResetPasswordComponent implements OnInit {
@Input() name: string;
@Input() email: string;
@Input() id: string;
@Input() organizationId: string;
@Output() onPasswordReset = new EventEmitter();
enforcedPolicyOptions: MasterPasswordPolicyOptions;
newPassword: string = null;
showPassword: boolean = false;
masterPasswordScore: number;
formPromise: Promise<any>;
private newPasswordStrengthTimeout: any;
constructor(private apiService: ApiService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private passwordGenerationService: PasswordGenerationService,
private policyService: PolicyService, private cryptoService: CryptoService) { }
async ngOnInit() {
// Get Enforced Policy Options
this.enforcedPolicyOptions = await this.policyService.getMasterPasswordPolicyOptions();
}
get loggedOutWarningName() {
return this.name != null ? this.name : this.i18nService.t('thisUser');
}
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 generatePassword() {
const options = (await this.passwordGenerationService.getOptions())[0];
this.newPassword = await this.passwordGenerationService.generatePassword(options);
this.updatePasswordStrength();
}
togglePassword() {
this.showPassword = !this.showPassword;
document.getElementById('newPassword').focus();
}
copy(value: string) {
if (value == null) {
return;
}
this.platformUtilsService.copyToClipboard(value, { window: window });
this.platformUtilsService.showToast('info', null,
this.i18nService.t('valueCopied', this.i18nService.t('password')));
}
async submit() {
// Validation
if (this.newPassword == null || this.newPassword === '') {
this.platformUtilsService.showToast('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('masterPassRequired'));
return false;
}
if (this.newPassword.length < 8) {
this.platformUtilsService.showToast('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('masterPassLength'));
return false;
}
if (this.enforcedPolicyOptions != null &&
!this.policyService.evaluateMasterPassword(this.masterPasswordScore, this.newPassword,
this.enforcedPolicyOptions)) {
this.platformUtilsService.showToast('error', this.i18nService.t('errorOccurred'),
this.i18nService.t('masterPasswordPolicyRequirementsNotMet'));
return;
}
if (this.masterPasswordScore < 3) {
const result = await this.platformUtilsService.showDialog(this.i18nService.t('weakMasterPasswordDesc'),
this.i18nService.t('weakMasterPassword'), this.i18nService.t('yes'), this.i18nService.t('no'),
'warning');
if (!result) {
return false;
}
}
// Get user Information (kdf type, kdf iterations, resetPasswordKey, private key) and change password
try {
this.formPromise = this.apiService.getOrganizationUserResetPasswordDetails(this.organizationId, this.id)
.then(async response => {
if (response == null) {
throw new Error(this.i18nService.t('resetPasswordDetailsError'));
}
const kdfType = response.kdf;
const kdfIterations = response.kdfIterations;
const resetPasswordKey = response.resetPasswordKey;
const encryptedPrivateKey = response.encryptedPrivateKey;
// Decrypt Organization's encrypted Private Key with org key
const orgSymKey = await this.cryptoService.getOrgKey(this.organizationId);
const decPrivateKey = await this.cryptoService.decryptToBytes(new EncString(encryptedPrivateKey), orgSymKey);
// Decrypt User's Reset Password Key to get EncKey
const decValue = await this.cryptoService.rsaDecrypt(resetPasswordKey, decPrivateKey);
const userEncKey = new SymmetricCryptoKey(decValue);
// Create new key and hash new password
const newKey = await this.cryptoService.makeKey(this.newPassword, this.email.trim().toLowerCase(),
kdfType, kdfIterations);
const newPasswordHash = await this.cryptoService.hashPassword(this.newPassword, newKey);
// Create new encKey for the User
const newEncKey = await this.cryptoService.remakeEncKey(newKey, userEncKey);
// Create request
const request = new OrganizationUserResetPasswordRequest();
request.key = newEncKey[1].encryptedString;
request.newMasterPasswordHash = newPasswordHash;
// Change user's password
return this.apiService.putOrganizationUserResetPassword(this.organizationId, this.id, request);
});
await this.formPromise;
this.platformUtilsService.showToast('success', null, this.i18nService.t('resetPasswordSuccess'));
this.onPasswordReset.emit();
} catch { }
}
updatePasswordStrength() {
if (this.newPasswordStrengthTimeout != null) {
clearTimeout(this.newPasswordStrengthTimeout);
}
this.newPasswordStrengthTimeout = setTimeout(() => {
const strengthResult = this.passwordGenerationService.passwordStrength(this.newPassword,
this.getPasswordStrengthUserInput());
this.masterPasswordScore = strengthResult == null ? null : strengthResult.score;
}, 300);
}
private getPasswordStrengthUserInput() {
let userInput: string[] = [];
const atPosition = this.email.indexOf('@');
if (atPosition > -1) {
userInput = userInput.concat(this.email.substr(0, atPosition).trim().toLowerCase().split(/[^A-Za-z0-9]/));
}
if (this.name != null && this.name !== '') {
userInput = userInput.concat(this.name.trim().toLowerCase().split(' '));
}
return userInput;
}
}

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="userAddEditTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-dialog modal-lg" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
<div class="modal-header">
<h2 class="modal-title" id="userAddEditTitle">
@@ -172,8 +172,7 @@
<div class="form-group mb-0">
<div class="form-check mt-1 form-check-block">
<input class="form-check-input" type="checkbox" name="manageUsers"
id="manageUsers" [(ngModel)]="permissions.manageUsers"
(change)="handleDependentPermissions()">
id="manageUsers" [(ngModel)]="permissions.manageUsers">
<label class="form-check-label font-weight-normal" for="manageUsers">
{{'manageUsers' | i18n}}
</label>
@@ -182,8 +181,7 @@
<div class="form-group mb-0">
<div class="form-check mt-1 form-check-block">
<input class="form-check-input" type="checkbox" name="manageResetPassword"
id="manageResetPassword" [(ngModel)]="permissions.manageResetPassword"
(change)="handleDependentPermissions()">
id="manageResetPassword" [(ngModel)]="permissions.manageResetPassword">
<label class="form-check-label font-weight-normal" for="manageResetPassword">
{{'manageResetPassword' | i18n}}
</label>

View File

@@ -8,21 +8,21 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CollectionService } from 'jslib-common/abstractions/collection.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CollectionService } from 'jslib/abstractions/collection.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { CollectionData } from 'jslib-common/models/data/collectionData';
import { Collection } from 'jslib-common/models/domain/collection';
import { OrganizationUserInviteRequest } from 'jslib-common/models/request/organizationUserInviteRequest';
import { OrganizationUserUpdateRequest } from 'jslib-common/models/request/organizationUserUpdateRequest';
import { SelectionReadOnlyRequest } from 'jslib-common/models/request/selectionReadOnlyRequest';
import { CollectionDetailsResponse } from 'jslib-common/models/response/collectionResponse';
import { CollectionView } from 'jslib-common/models/view/collectionView';
import { CollectionData } from 'jslib/models/data/collectionData';
import { Collection } from 'jslib/models/domain/collection';
import { OrganizationUserInviteRequest } from 'jslib/models/request/organizationUserInviteRequest';
import { OrganizationUserUpdateRequest } from 'jslib/models/request/organizationUserUpdateRequest';
import { SelectionReadOnlyRequest } from 'jslib/models/request/selectionReadOnlyRequest';
import { CollectionDetailsResponse } from 'jslib/models/response/collectionResponse';
import { CollectionView } from 'jslib/models/view/collectionView';
import { OrganizationUserType } from 'jslib-common/enums/organizationUserType';
import { PermissionsApi } from 'jslib-common/models/api/permissionsApi';
import { OrganizationUserType } from 'jslib/enums/organizationUserType';
import { PermissionsApi } from 'jslib/models/api/permissionsApi';
@Component({
selector: 'app-user-add-edit',
@@ -143,15 +143,6 @@ export class UserAddEditComponent implements OnInit {
return p;
}
handleDependentPermissions() {
// Manage Password Reset must have Manage Users enabled
if (this.permissions.manageResetPassword && !this.permissions.manageUsers) {
this.permissions.manageUsers = true;
(document.getElementById('manageUsers') as HTMLInputElement).checked = true;
this.platformUtilsService.showToast('info', null, this.i18nService.t('resetPasswordManageUsers'));
}
}
async submit() {
let collections: SelectionReadOnlyRequest[] = null;
if (this.access !== 'all') {

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="confirmUserTitle">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-dialog" role="document">
<form class="modal-content" #form (ngSubmit)="submit()">
<div class="modal-header">
<h2 class="modal-title" id="confirmUserTitle">

View File

@@ -6,13 +6,13 @@ import {
Output,
} from '@angular/core';
import { ConstantsService } from 'jslib-common/services/constants.service';
import { ConstantsService } from 'jslib/services/constants.service';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { Utils } from 'jslib-common/misc/utils';
import { Utils } from 'jslib/misc/utils';
@Component({
selector: 'app-user-confirm',

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="groupAccessTitle">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-dialog" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
<div class="modal-header">
<h2 class="modal-title" id="groupAccessTitle">

View File

@@ -8,13 +8,13 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { OrganizationUserUpdateGroupsRequest } from 'jslib-common/models/request/organizationUserUpdateGroupsRequest';
import { GroupResponse } from 'jslib-common/models/response/groupResponse';
import { OrganizationUserUpdateGroupsRequest } from 'jslib/models/request/organizationUserUpdateGroupsRequest';
import { GroupResponse } from 'jslib/models/response/groupResponse';
import { Utils } from 'jslib-common/misc/utils';
import { Utils } from 'jslib/misc/utils';
@Component({
selector: 'app-user-groups',

View File

@@ -4,28 +4,22 @@ import {
ViewChild,
ViewContainerRef,
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { SyncService } from 'jslib/abstractions/sync.service';
import { OrganizationKeysRequest } from 'jslib-common/models/request/organizationKeysRequest';
import { OrganizationUpdateRequest } from 'jslib-common/models/request/organizationUpdateRequest';
import { OrganizationResponse } from 'jslib-common/models/response/organizationResponse';
import { OrganizationUpdateRequest } from 'jslib/models/request/organizationUpdateRequest';
import { OrganizationResponse } from 'jslib/models/response/organizationResponse';
import { ModalComponent } from '../../modal.component';
import { ApiKeyComponent } from '../../settings/api-key.component';
import { PurgeVaultComponent } from '../../settings/purge-vault.component';
import { TaxInfoComponent } from '../../settings/tax-info.component';
import { DeleteOrganizationComponent } from './delete-organization.component';
@Component({
@@ -52,8 +46,7 @@ export class AccountComponent {
constructor(private componentFactoryResolver: ComponentFactoryResolver,
private apiService: ApiService, private i18nService: I18nService,
private toasterService: ToasterService, private route: ActivatedRoute,
private syncService: SyncService, private platformUtilsService: PlatformUtilsService,
private cryptoService: CryptoService) { }
private syncService: SyncService, private platformUtilsService: PlatformUtilsService) { }
async ngOnInit() {
this.selfHosted = this.platformUtilsService.isSelfHost();
@@ -74,14 +67,6 @@ export class AccountComponent {
request.businessName = this.org.businessName;
request.billingEmail = this.org.billingEmail;
request.identifier = this.org.identifier;
// Backfill pub/priv key if necessary
if (!this.org.hasPublicAndPrivateKeys) {
const orgShareKey = await this.cryptoService.getOrgKey(this.organizationId);
const orgKeys = await this.cryptoService.makeKeyPair(orgShareKey);
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
}
this.formPromise = this.apiService.putOrganization(this.organizationId, request).then(() => {
return this.syncService.fullSync(true);
});

View File

@@ -13,10 +13,10 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { SeatRequest } from 'jslib-common/models/request/seatRequest';
import { SeatRequest } from 'jslib/models/request/seatRequest';
import { PaymentComponent } from '../../settings/payment.component';

View File

@@ -5,11 +5,11 @@ import {
Output,
} from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PlanType } from 'jslib-common/enums/planType';
import { ProductType } from 'jslib-common/enums/productType';
import { PlanType } from 'jslib/enums/planType';
import { ProductType } from 'jslib/enums/productType';
@Component({
selector: 'app-change-plan',

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="deleteOrganizationTitle">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-dialog" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
<div class="modal-header">
<h2 class="modal-title" id="deleteOrganizationTitle">{{'deleteOrganization' | i18n}}</h2>

View File

@@ -3,11 +3,11 @@ import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PasswordVerificationRequest } from 'jslib-common/models/request/passwordVerificationRequest';
import { PasswordVerificationRequest } from 'jslib/models/request/passwordVerificationRequest';
@Component({
selector: 'app-delete-organization',

View File

@@ -5,8 +5,8 @@ import {
Output,
} from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
@Component({
selector: 'app-download-license',

View File

@@ -6,9 +6,9 @@ import { ActivatedRoute } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserBillingComponent } from '../../settings/user-billing.component';

View File

@@ -6,14 +6,14 @@ import { ActivatedRoute } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { OrganizationSubscriptionResponse } from 'jslib-common/models/response/organizationSubscriptionResponse';
import { OrganizationSubscriptionResponse } from 'jslib/models/response/organizationSubscriptionResponse';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PlanType } from 'jslib-common/enums/planType';
import { PlanType } from 'jslib/enums/planType';
@Component({
selector: 'app-org-subscription',

View File

@@ -1,8 +1,8 @@
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service';
@Component({
selector: 'app-org-settings',

View File

@@ -4,12 +4,12 @@ import {
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { UserService } from 'jslib/abstractions/user.service';
import { TwoFactorProviderType } from 'jslib-common/enums/twoFactorProviderType';
import { TwoFactorProviderType } from 'jslib/enums/twoFactorProviderType';
import { TwoFactorDuoComponent } from '../../settings/two-factor-duo.component';
import { TwoFactorSetupComponent as BaseTwoFactorSetupComponent } from '../../settings/two-factor-setup.component';

View File

@@ -1,15 +1,15 @@
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { EventService } from 'jslib-common/abstractions/event.service';
import { ExportService } from 'jslib-common/abstractions/export.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { EventService } from 'jslib/abstractions/event.service';
import { ExportService } from 'jslib/abstractions/export.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { ExportComponent as BaseExportComponent } from '../../tools/export.component';
import { EventType } from 'jslib-common/enums/eventType';
import { EventType } from 'jslib/enums/eventType';
@Component({
selector: 'app-org-export',

View File

@@ -4,17 +4,17 @@ import {
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AuditService } from 'jslib-common/abstractions/audit.service';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { AuditService } from 'jslib/abstractions/audit.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { UserService } from 'jslib/abstractions/user.service';
import {
ExposedPasswordsReportComponent as BaseExposedPasswordsReportComponent,
} from '../../tools/exposed-passwords-report.component';
import { Cipher } from 'jslib-common/models/domain/cipher';
import { CipherView } from 'jslib-common/models/view/cipherView';
import { Cipher } from 'jslib/models/domain/cipher';
import { CipherView } from 'jslib/models/view/cipherView';
@Component({
selector: 'app-exposed-passwords-report',

View File

@@ -6,10 +6,10 @@ import {
import { ToasterService } from 'angular2-toaster';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { ImportService } from 'jslib-common/abstractions/import.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { ImportService } from 'jslib/abstractions/import.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service';
import { ImportComponent as BaseImportComponent } from '../../tools/import.component';

View File

@@ -4,15 +4,15 @@ import {
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { UserService } from 'jslib/abstractions/user.service';
import {
InactiveTwoFactorReportComponent as BaseInactiveTwoFactorReportComponent,
} from '../../tools/inactive-two-factor-report.component';
import { CipherView } from 'jslib-common/models/view/cipherView';
import { CipherView } from 'jslib/models/view/cipherView';
@Component({
selector: 'app-inactive-two-factor-report',

View File

@@ -4,13 +4,13 @@ import {
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { UserService } from 'jslib/abstractions/user.service';
import { Cipher } from 'jslib-common/models/domain/cipher';
import { Cipher } from 'jslib/models/domain/cipher';
import { CipherView } from 'jslib-common/models/view/cipherView';
import { CipherView } from 'jslib/models/view/cipherView';
import {
ReusedPasswordsReportComponent as BaseReusedPasswordsReportComponent,

View File

@@ -1,10 +1,10 @@
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Organization } from 'jslib-common/models/domain/organization';
import { Organization } from 'jslib/models/domain/organization';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { UserService } from 'jslib/abstractions/user.service';
@Component({
selector: 'app-org-tools',

View File

@@ -4,15 +4,15 @@ import {
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { UserService } from 'jslib/abstractions/user.service';
import {
UnsecuredWebsitesReportComponent as BaseUnsecuredWebsitesReportComponent,
} from '../../tools/unsecured-websites-report.component';
import { CipherView } from 'jslib-common/models/view/cipherView';
import { CipherView } from 'jslib/models/view/cipherView';
@Component({
selector: 'app-unsecured-websites-report',

View File

@@ -4,14 +4,14 @@ import {
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { UserService } from 'jslib/abstractions/user.service';
import { Cipher } from 'jslib-common/models/domain/cipher';
import { Cipher } from 'jslib/models/domain/cipher';
import { CipherView } from 'jslib-common/models/view/cipherView';
import { CipherView } from 'jslib/models/view/cipherView';
import {
WeakPasswordsReportComponent as BaseWeakPasswordsReportComponent,

View File

@@ -1,25 +1,25 @@
import { Component } from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { AuditService } from 'jslib-common/abstractions/audit.service';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { CollectionService } from 'jslib-common/abstractions/collection.service';
import { EventService } from 'jslib-common/abstractions/event.service';
import { FolderService } from 'jslib-common/abstractions/folder.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { StateService } from 'jslib-common/abstractions/state.service';
import { TotpService } from 'jslib-common/abstractions/totp.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { AuditService } from 'jslib/abstractions/audit.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { CollectionService } from 'jslib/abstractions/collection.service';
import { EventService } from 'jslib/abstractions/event.service';
import { FolderService } from 'jslib/abstractions/folder.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.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 { TotpService } from 'jslib/abstractions/totp.service';
import { UserService } from 'jslib/abstractions/user.service';
import { CipherData } from 'jslib-common/models/data/cipherData';
import { Cipher } from 'jslib-common/models/domain/cipher';
import { Organization } from 'jslib-common/models/domain/organization';
import { CipherCreateRequest } from 'jslib-common/models/request/cipherCreateRequest';
import { CipherRequest } from 'jslib-common/models/request/cipherRequest';
import { CipherData } from 'jslib/models/data/cipherData';
import { Cipher } from 'jslib/models/domain/cipher';
import { Organization } from 'jslib/models/domain/organization';
import { CipherCreateRequest } from 'jslib/models/request/cipherCreateRequest';
import { CipherRequest } from 'jslib/models/request/cipherRequest';
import { AddEditComponent as BaseAddEditComponent } from '../../vault/add-edit.component';

View File

@@ -1,17 +1,17 @@
import { Component } from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service';
import { CipherData } from 'jslib-common/models/data/cipherData';
import { Cipher } from 'jslib-common/models/domain/cipher';
import { Organization } from 'jslib-common/models/domain/organization';
import { CipherData } from 'jslib/models/data/cipherData';
import { Cipher } from 'jslib/models/domain/cipher';
import { Organization } from 'jslib/models/domain/organization';
import { AttachmentView } from 'jslib-common/models/view/attachmentView';
import { AttachmentView } from 'jslib/models/view/attachmentView';
import { AttachmentsComponent as BaseAttachmentsComponent } from '../../vault/attachments.component';

View File

@@ -6,18 +6,17 @@ import {
import { ToasterService } from 'angular2-toaster';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { EventService } from 'jslib-common/abstractions/event.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PasswordRepromptService } from 'jslib-common/abstractions/passwordReprompt.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { SearchService } from 'jslib-common/abstractions/search.service';
import { TotpService } from 'jslib-common/abstractions/totp.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { EventService } from 'jslib/abstractions/event.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { SearchService } from 'jslib/abstractions/search.service';
import { TotpService } from 'jslib/abstractions/totp.service';
import { UserService } from 'jslib/abstractions/user.service';
import { Organization } from 'jslib-common/models/domain/organization';
import { CipherView } from 'jslib-common/models/view/cipherView';
import { Organization } from 'jslib/models/domain/organization';
import { CipherView } from 'jslib/models/view/cipherView';
import { CiphersComponent as BaseCiphersComponent } from '../../vault/ciphers.component';
@@ -35,10 +34,9 @@ export class CiphersComponent extends BaseCiphersComponent {
constructor(searchService: SearchService, toasterService: ToasterService, i18nService: I18nService,
platformUtilsService: PlatformUtilsService, cipherService: CipherService,
private apiService: ApiService, eventService: EventService, totpService: TotpService,
userService: UserService, passwordRepromptService: PasswordRepromptService) {
private apiService: ApiService, eventService: EventService, totpService: TotpService, userService: UserService) {
super(searchService, toasterService, i18nService, platformUtilsService, cipherService,
eventService, totpService, userService, passwordRepromptService);
eventService, totpService, userService);
}
async load(filter: (cipher: CipherView) => boolean = null) {

View File

@@ -1,15 +1,15 @@
import { Component } from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CipherService } from 'jslib-common/abstractions/cipher.service';
import { CollectionService } from 'jslib-common/abstractions/collection.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { CollectionService } from 'jslib/abstractions/collection.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { CipherData } from 'jslib-common/models/data/cipherData';
import { Cipher } from 'jslib-common/models/domain/cipher';
import { Organization } from 'jslib-common/models/domain/organization';
import { CipherCollectionsRequest } from 'jslib-common/models/request/cipherCollectionsRequest';
import { CipherData } from 'jslib/models/data/cipherData';
import { Cipher } from 'jslib/models/domain/cipher';
import { Organization } from 'jslib/models/domain/organization';
import { CipherCollectionsRequest } from 'jslib/models/request/cipherCollectionsRequest';
import { CollectionsComponent as BaseCollectionsComponent } from '../../vault/collections.component';

View File

@@ -1,17 +1,17 @@
import { Component } from '@angular/core';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CollectionService } from 'jslib-common/abstractions/collection.service';
import { FolderService } from 'jslib-common/abstractions/folder.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { StorageService } from 'jslib-common/abstractions/storage.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CollectionService } from 'jslib/abstractions/collection.service';
import { FolderService } from 'jslib/abstractions/folder.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { UserService } from 'jslib/abstractions/user.service';
import { CollectionData } from 'jslib-common/models/data/collectionData';
import { Collection } from 'jslib-common/models/domain/collection';
import { Organization } from 'jslib-common/models/domain/organization';
import { CollectionDetailsResponse } from 'jslib-common/models/response/collectionResponse';
import { CollectionView } from 'jslib-common/models/view/collectionView';
import { CollectionData } from 'jslib/models/data/collectionData';
import { Collection } from 'jslib/models/domain/collection';
import { Organization } from 'jslib/models/domain/organization';
import { CollectionDetailsResponse } from 'jslib/models/response/collectionResponse';
import { CollectionView } from 'jslib/models/view/collectionView';
import { GroupingsComponent as BaseGroupingsComponent } from '../../vault/groupings.component';

View File

@@ -13,18 +13,18 @@ import {
Router,
} from '@angular/router';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { SyncService } from 'jslib-common/abstractions/sync.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { SyncService } from 'jslib/abstractions/sync.service';
import { UserService } from 'jslib/abstractions/user.service';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
import { Organization } from 'jslib-common/models/domain/organization';
import { CipherView } from 'jslib-common/models/view/cipherView';
import { Organization } from 'jslib/models/domain/organization';
import { CipherView } from 'jslib/models/view/cipherView';
import { CipherType } from 'jslib-common/enums/cipherType';
import { CipherType } from 'jslib/enums/cipherType';
import { ModalComponent } from '../../modal.component';

View File

@@ -1,5 +1,6 @@
/* tslint:disable */
import 'core-js/stable';
import 'core-js/es6';
import 'core-js/es7/reflect';
require('zone.js/dist/zone');
// IE11 fix, ref: https://github.com/angular/angular/issues/24769

View File

@@ -5,24 +5,24 @@ import {
import { ActivatedRoute } from '@angular/router';
import { ApiService } from 'jslib-common/abstractions/api.service';
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { Utils } from 'jslib-common/misc/utils';
import { Utils } from 'jslib/misc/utils';
import { SendAccess } from 'jslib-common/models/domain/sendAccess';
import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey';
import { SendAccess } from 'jslib/models/domain/sendAccess';
import { SymmetricCryptoKey } from 'jslib/models/domain/symmetricCryptoKey';
import { SendAccessView } from 'jslib-common/models/view/sendAccessView';
import { SendAccessView } from 'jslib/models/view/sendAccessView';
import { SendType } from 'jslib-common/enums/sendType';
import { SendAccessRequest } from 'jslib-common/models/request/sendAccessRequest';
import { ErrorResponse } from 'jslib-common/models/response/errorResponse';
import { SendType } from 'jslib/enums/sendType';
import { SendAccessRequest } from 'jslib/models/request/sendAccessRequest';
import { ErrorResponse } from 'jslib/models/response/errorResponse';
import { SendAccessResponse } from 'jslib-common/models/response/sendAccessResponse';
import { SendAccessResponse } from 'jslib/models/response/sendAccessResponse';
@Component({
selector: 'app-send-access',

View File

@@ -1,5 +1,5 @@
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="sendAddEditTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-dialog modal-lg" role="document">
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate
autocomplete="off">
<div class="modal-header">
@@ -232,8 +232,10 @@
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-submit manual" [ngClass]="{loading:form.loading}"
[disabled]="form.loading || disableSend">
<button class="btn btn-primary disabled" disabled=true *ngIf="disableSend">
<span>{{'save' | i18n}}</span>
</button>
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading" *ngIf="!disableSend">
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
<span>{{'save' | i18n}}</span>
</button>

View File

@@ -2,15 +2,15 @@ import { DatePipe } from '@angular/common';
import { Component } from '@angular/core';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { SendService } from 'jslib-common/abstractions/send.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { SendService } from 'jslib/abstractions/send.service';
import { UserService } from 'jslib/abstractions/user.service';
import { AddEditComponent as BaseAddEditComponent } from 'jslib-angular/components/send/add-edit.component';
import { AddEditComponent as BaseAddEditComponent } from 'jslib/angular/components/send/add-edit.component';
@Component({
selector: 'app-send-add-edit',
@@ -25,11 +25,9 @@ export class AddEditComponent extends BaseAddEditComponent {
messagingService, policyService);
}
async copyLinkToClipboard(link: string): Promise<void | boolean> {
copyLinkToClipboard(link: string) {
// Copy function on web depends on the modal being open or not. Since this event occurs during a transition
// of the modal closing we need to add a small delay to make sure state of the DOM is consistent.
return new Promise(resolve => {
window.setTimeout(() => resolve(super.copyLinkToClipboard(link)), 500);
});
window.setTimeout(() => super.copyLinkToClipboard(link), 500);
}
}

View File

@@ -6,23 +6,23 @@ import {
ViewContainerRef,
} from '@angular/core';
import { SendView } from 'jslib-common/models/view/sendView';
import { SendView } from 'jslib/models/view/sendView';
import { SendComponent as BaseSendComponent } from 'jslib-angular/components/send/send.component';
import { SendComponent as BaseSendComponent } from 'jslib/angular/components/send/send.component';
import { AddEditComponent } from './add-edit.component';
import { ModalComponent } from '../modal.component';
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { SearchService } from 'jslib-common/abstractions/search.service';
import { SendService } from 'jslib-common/abstractions/send.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PolicyService } from 'jslib/abstractions/policy.service';
import { SearchService } from 'jslib/abstractions/search.service';
import { SendService } from 'jslib/abstractions/send.service';
import { UserService } from 'jslib/abstractions/user.service';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
const BroadcasterSubscriptionId = 'SendComponent';

View File

@@ -1,18 +1,15 @@
import { Injectable } from '@angular/core';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PolicyService } from 'jslib-common/abstractions/policy.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { DeviceType } from 'jslib-common/enums/deviceType';
import { EventType } from 'jslib-common/enums/eventType';
import { PolicyType } from 'jslib-common/enums/policyType';
import { EventResponse } from 'jslib-common/models/response/eventResponse';
import { DeviceType } from 'jslib/enums/deviceType';
import { EventType } from 'jslib/enums/eventType';
import { EventResponse } from 'jslib/models/response/eventResponse';
@Injectable()
export class EventService {
constructor(private i18nService: I18nService, private policyService: PolicyService) { }
constructor(private i18nService: I18nService) { }
getDefaultDateFilters() {
const d = new Date();
@@ -31,184 +28,146 @@ export class EventService {
return [start.toISOString(), end.toISOString()];
}
async getEventInfo(ev: EventResponse, options = new EventOptions()): Promise<EventInfo> {
getEventInfo(ev: EventResponse, options = new EventOptions()): EventInfo {
const appInfo = this.getAppInfo(ev.deviceType);
const { message, humanReadableMessage } = await this.getEventMessage(ev, options);
return {
message: message,
humanReadableMessage: humanReadableMessage,
message: this.getEventMessage(ev, options),
appIcon: appInfo[0],
appName: appInfo[1],
};
}
private async getEventMessage(ev: EventResponse, options: EventOptions) {
private getEventMessage(ev: EventResponse, options: EventOptions) {
let msg = '';
let humanReadableMsg = '';
switch (ev.type) {
// User
case EventType.User_LoggedIn:
msg = humanReadableMsg = this.i18nService.t('loggedIn');
msg = this.i18nService.t('loggedIn');
break;
case EventType.User_ChangedPassword:
msg = humanReadableMsg = this.i18nService.t('changedPassword');
msg = this.i18nService.t('changedPassword');
break;
case EventType.User_Updated2fa:
msg = humanReadableMsg = this.i18nService.t('enabledUpdated2fa');
msg = this.i18nService.t('enabledUpdated2fa');
break;
case EventType.User_Disabled2fa:
msg = humanReadableMsg = this.i18nService.t('disabled2fa');
msg = this.i18nService.t('disabled2fa');
break;
case EventType.User_Recovered2fa:
msg = humanReadableMsg = this.i18nService.t('recovered2fa');
msg = this.i18nService.t('recovered2fa');
break;
case EventType.User_FailedLogIn:
msg = humanReadableMsg = this.i18nService.t('failedLogin');
msg = this.i18nService.t('failedLogin');
break;
case EventType.User_FailedLogIn2fa:
msg = humanReadableMsg = this.i18nService.t('failedLogin2fa');
msg = this.i18nService.t('failedLogin2fa');
break;
case EventType.User_ClientExportedVault:
msg = humanReadableMsg = this.i18nService.t('exportedVault');
msg = this.i18nService.t('exportedVault');
break;
// Cipher
case EventType.Cipher_Created:
msg = this.i18nService.t('createdItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('createdItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_Updated:
msg = this.i18nService.t('editedItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('editedItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_Deleted:
msg = this.i18nService.t('permanentlyDeletedItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('permanentlyDeletedItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_SoftDeleted:
msg = this.i18nService.t('deletedItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('deletedItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_Restored:
msg = this.i18nService.t('restoredItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('restoredItemId', this.formatCipherId(ev, options));
break;
case EventType.Cipher_AttachmentCreated:
msg = this.i18nService.t('createdAttachmentForItem', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('createdAttachmentForItem', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_AttachmentDeleted:
msg = this.i18nService.t('deletedAttachmentForItem', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('deletedAttachmentForItem', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_Shared:
msg = this.i18nService.t('sharedItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('sharedItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_ClientViewed:
msg = this.i18nService.t('viewedItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('viewedItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_ClientToggledPasswordVisible:
msg = this.i18nService.t('viewedPasswordItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('viewedPasswordItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_ClientToggledHiddenFieldVisible:
msg = this.i18nService.t('viewedHiddenFieldItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('viewedHiddenFieldItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_ClientToggledCardCodeVisible:
msg = this.i18nService.t('viewedSecurityCodeItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('viewedSecurityCodeItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_ClientCopiedHiddenField:
msg = this.i18nService.t('copiedHiddenFieldItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('copiedHiddenFieldItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_ClientCopiedPassword:
msg = this.i18nService.t('copiedPasswordItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('copiedPasswordItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_ClientCopiedCardCode:
msg = this.i18nService.t('copiedSecurityCodeItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('copiedSecurityCodeItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_ClientAutofilled:
msg = this.i18nService.t('autofilledItemId', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('autofilledItemId', this.getShortId(ev.cipherId));
break;
case EventType.Cipher_UpdatedCollections:
msg = this.i18nService.t('editedCollectionsForItem', this.formatCipherId(ev, options));
humanReadableMsg = this.i18nService.t('editedCollectionsForItem', this.getShortId(ev.cipherId));
break;
// Collection
case EventType.Collection_Created:
msg = this.i18nService.t('createdCollectionId', this.formatCollectionId(ev));
humanReadableMsg = this.i18nService.t('createdCollectionId', this.getShortId(ev.collectionId));
break;
case EventType.Collection_Updated:
msg = this.i18nService.t('editedCollectionId', this.formatCollectionId(ev));
humanReadableMsg = this.i18nService.t('editedCollectionId', this.getShortId(ev.collectionId));
break;
case EventType.Collection_Deleted:
msg = this.i18nService.t('deletedCollectionId', this.formatCollectionId(ev));
humanReadableMsg = this.i18nService.t('deletedCollectionId', this.getShortId(ev.collectionId));
break;
// Group
case EventType.Group_Created:
msg = this.i18nService.t('createdGroupId', this.formatGroupId(ev));
humanReadableMsg = this.i18nService.t('createdGroupId', this.getShortId(ev.groupId));
break;
case EventType.Group_Updated:
msg = this.i18nService.t('editedGroupId', this.formatGroupId(ev));
humanReadableMsg = this.i18nService.t('editedGroupId', this.getShortId(ev.groupId));
break;
case EventType.Group_Deleted:
msg = this.i18nService.t('deletedGroupId', this.formatGroupId(ev));
humanReadableMsg = this.i18nService.t('deletedGroupId', this.getShortId(ev.groupId));
break;
// Org user
case EventType.OrganizationUser_Invited:
msg = this.i18nService.t('invitedUserId', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('invitedUserId', this.getShortId(ev.organizationUserId));
break;
case EventType.OrganizationUser_Confirmed:
msg = this.i18nService.t('confirmedUserId', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('confirmedUserId', this.getShortId(ev.organizationUserId));
break;
case EventType.OrganizationUser_Updated:
msg = this.i18nService.t('editedUserId', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('editedUserId', this.getShortId(ev.organizationUserId));
break;
case EventType.OrganizationUser_Removed:
msg = this.i18nService.t('removedUserId', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('removedUserId', this.getShortId(ev.organizationUserId));
break;
case EventType.OrganizationUser_UpdatedGroups:
msg = this.i18nService.t('editedGroupsForUser', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('editedGroupsForUser', this.getShortId(ev.organizationUserId));
break;
case EventType.OrganizationUser_UnlinkedSso:
msg = this.i18nService.t('unlinkedSsoUser', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('unlinkedSsoUser', this.getShortId(ev.organizationUserId));
break;
case EventType.OrganizationUser_ResetPassword_Enroll:
msg = this.i18nService.t('eventEnrollPasswordReset', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('eventEnrollPasswordReset', this.getShortId(ev.organizationUserId));
break;
case EventType.OrganizationUser_ResetPassword_Withdraw:
msg = this.i18nService.t('eventWithdrawPasswordReset', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('eventWithdrawPasswordReset', this.getShortId(ev.organizationUserId));
break;
case EventType.OrganizationUser_AdminResetPassword:
msg = this.i18nService.t('eventAdminPasswordReset', this.formatOrgUserId(ev));
humanReadableMsg = this.i18nService.t('eventAdminPasswordReset', this.getShortId(ev.organizationUserId));
break;
// Org
case EventType.Organization_Updated:
msg = humanReadableMsg = this.i18nService.t('editedOrgSettings');
msg = this.i18nService.t('editedOrgSettings');
break;
case EventType.Organization_PurgedVault:
msg = humanReadableMsg = this.i18nService.t('purgedOrganizationVault');
msg = this.i18nService.t('purgedOrganizationVault');
break;
/*
case EventType.Organization_ClientExportedVault:
@@ -217,25 +176,13 @@ export class EventService {
*/
// Policies
case EventType.Policy_Updated:
msg = this.i18nService.t('modifiedPolicyId', this.formatPolicyId(ev));
const policies = await this.policyService.getAll();
const policy = policies.filter(p => p.id === ev.policyId)[0];
let p1 = this.getShortId(ev.policyId);
if (policy !== null) {
p1 = PolicyType[policy.type];
}
humanReadableMsg = this.i18nService.t('modifiedPolicyId', p1);
msg = this.i18nService.t('modifiedPolicy', this.formatPolicyId(ev));
break;
default:
break;
}
return {
message: msg === '' ? null : msg,
humanReadableMessage: humanReadableMsg === '' ? null : humanReadableMsg,
};
return msg === '' ? null : msg;
}
private getAppInfo(deviceType: DeviceType): [string, string] {
@@ -352,7 +299,6 @@ export class EventService {
export class EventInfo {
message: string;
humanReadableMessage: string;
appIcon: string;
appName: string;
}

View File

@@ -7,8 +7,8 @@ import {
import { ToasterService } from 'angular2-toaster';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { UserService } from 'jslib-common/abstractions/user.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { UserService } from 'jslib/abstractions/user.service';
@Injectable()
export class OrganizationGuardService implements CanActivate {

View File

@@ -5,9 +5,9 @@ import {
Router,
} from '@angular/router';
import { UserService } from 'jslib-common/abstractions/user.service';
import { UserService } from 'jslib/abstractions/user.service';
import { Permissions } from 'jslib-common/enums/permissions';
import { Permissions } from 'jslib/enums/permissions';
@Injectable()
export class OrganizationTypeGuardService implements CanActivate {
@@ -27,8 +27,7 @@ export class OrganizationTypeGuardService implements CanActivate {
(permissions.indexOf(Permissions.ManageGroups) !== -1 && org.canManageGroups) ||
(permissions.indexOf(Permissions.ManageOrganization) !== -1 && org.isOwner) ||
(permissions.indexOf(Permissions.ManagePolicies) !== -1 && org.canManagePolicies) ||
(permissions.indexOf(Permissions.ManageUsers) !== -1 && org.canManageUsers) ||
(permissions.indexOf(Permissions.ManageUsersPassword) !== -1 && org.canManageUsersPassword)
(permissions.indexOf(Permissions.ManageUsers) !== -1 && org.canManageUsers)
) {
return true;
}

View File

@@ -6,7 +6,7 @@ import {
Router,
} from '@angular/router';
import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
@Injectable()
export class RouterService {

View File

@@ -17,86 +17,86 @@ import { OrganizationGuardService } from './organization-guard.service';
import { OrganizationTypeGuardService } from './organization-type-guard.service';
import { RouterService } from './router.service';
import { AuthGuardService } from 'jslib-angular/services/auth-guard.service';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
import { LockGuardService } from 'jslib-angular/services/lock-guard.service';
import { UnauthGuardService } from 'jslib-angular/services/unauth-guard.service';
import { ValidationService } from 'jslib-angular/services/validation.service';
import { AuthGuardService } from 'jslib/angular/services/auth-guard.service';
import { BroadcasterService } from 'jslib/angular/services/broadcaster.service';
import { LockGuardService } from 'jslib/angular/services/lock-guard.service';
import { UnauthGuardService } from 'jslib/angular/services/unauth-guard.service';
import { ValidationService } from 'jslib/angular/services/validation.service';
import { ApiService } from 'jslib-common/services/api.service';
import { AppIdService } from 'jslib-common/services/appId.service';
import { AuditService } from 'jslib-common/services/audit.service';
import { AuthService } from 'jslib-common/services/auth.service';
import { CipherService } from 'jslib-common/services/cipher.service';
import { CollectionService } from 'jslib-common/services/collection.service';
import { ConsoleLogService } from 'jslib-common/services/consoleLog.service';
import { ConstantsService } from 'jslib-common/services/constants.service';
import { ContainerService } from 'jslib-common/services/container.service';
import { CryptoService } from 'jslib-common/services/crypto.service';
import { EnvironmentService } from 'jslib-common/services/environment.service';
import { EventService as EventLoggingService } from 'jslib-common/services/event.service';
import { ExportService } from 'jslib-common/services/export.service';
import { FileUploadService } from 'jslib-common/services/fileUpload.service';
import { FolderService } from 'jslib-common/services/folder.service';
import { ImportService } from 'jslib-common/services/import.service';
import { NotificationsService } from 'jslib-common/services/notifications.service';
import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service';
import { PasswordRepromptService } from 'jslib-common/services/passwordReprompt.service';
import { PolicyService } from 'jslib-common/services/policy.service';
import { SearchService } from 'jslib-common/services/search.service';
import { SendService } from 'jslib-common/services/send.service';
import { SettingsService } from 'jslib-common/services/settings.service';
import { StateService } from 'jslib-common/services/state.service';
import { SyncService } from 'jslib-common/services/sync.service';
import { TokenService } from 'jslib-common/services/token.service';
import { TotpService } from 'jslib-common/services/totp.service';
import { UserService } from 'jslib-common/services/user.service';
import { VaultTimeoutService } from 'jslib-common/services/vaultTimeout.service';
import { WebCryptoFunctionService } from 'jslib-common/services/webCryptoFunction.service';
import { ApiService } from 'jslib/services/api.service';
import { AppIdService } from 'jslib/services/appId.service';
import { AuditService } from 'jslib/services/audit.service';
import { AuthService } from 'jslib/services/auth.service';
import { CipherService } from 'jslib/services/cipher.service';
import { CollectionService } from 'jslib/services/collection.service';
import { ConsoleLogService } from 'jslib/services/consoleLog.service';
import { ConstantsService } from 'jslib/services/constants.service';
import { ContainerService } from 'jslib/services/container.service';
import { CryptoService } from 'jslib/services/crypto.service';
import { EnvironmentService } from 'jslib/services/environment.service';
import { EventService as EventLoggingService } from 'jslib/services/event.service';
import { ExportService } from 'jslib/services/export.service';
import { FileUploadService } from 'jslib/services/fileUpload.service';
import { FolderService } from 'jslib/services/folder.service';
import { ImportService } from 'jslib/services/import.service';
import { NotificationsService } from 'jslib/services/notifications.service';
import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service';
import { PolicyService } from 'jslib/services/policy.service';
import { SearchService } from 'jslib/services/search.service';
import { SendService } from 'jslib/services/send.service';
import { SettingsService } from 'jslib/services/settings.service';
import { StateService } from 'jslib/services/state.service';
import { SyncService } from 'jslib/services/sync.service';
import { TokenService } from 'jslib/services/token.service';
import { TotpService } from 'jslib/services/totp.service';
import { UserService } from 'jslib/services/user.service';
import { VaultTimeoutService } from 'jslib/services/vaultTimeout.service';
import { WebCryptoFunctionService } from 'jslib/services/webCryptoFunction.service';
import { ApiService as ApiServiceAbstraction } from 'jslib-common/abstractions/api.service';
import { AuditService as AuditServiceAbstraction } from 'jslib-common/abstractions/audit.service';
import { AuthService as AuthServiceAbstraction } from 'jslib-common/abstractions/auth.service';
import { CipherService as CipherServiceAbstraction } from 'jslib-common/abstractions/cipher.service';
import { CollectionService as CollectionServiceAbstraction } from 'jslib-common/abstractions/collection.service';
import { CryptoService as CryptoServiceAbstraction } from 'jslib-common/abstractions/crypto.service';
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from 'jslib-common/abstractions/cryptoFunction.service';
import { EnvironmentService as EnvironmentServiceAbstraction } from 'jslib-common/abstractions/environment.service';
import { EventService as EventLoggingServiceAbstraction } from 'jslib-common/abstractions/event.service';
import { ExportService as ExportServiceAbstraction } from 'jslib-common/abstractions/export.service';
import { FileUploadService as FileUploadServiceAbstraction } from 'jslib-common/abstractions/fileUpload.service';
import { FolderService as FolderServiceAbstraction } from 'jslib-common/abstractions/folder.service';
import { I18nService as I18nServiceAbstraction } from 'jslib-common/abstractions/i18n.service';
import { ImportService as ImportServiceAbstraction } from 'jslib-common/abstractions/import.service';
import { MessagingService as MessagingServiceAbstraction } from 'jslib-common/abstractions/messaging.service';
import { NotificationsService as NotificationsServiceAbstraction } from 'jslib-common/abstractions/notifications.service';
import { ApiService as ApiServiceAbstraction } from 'jslib/abstractions/api.service';
import { AppIdService as AppIdServiceAbstraction } from 'jslib/abstractions/appId.service';
import { AuditService as AuditServiceAbstraction } from 'jslib/abstractions/audit.service';
import { AuthService as AuthServiceAbstraction } from 'jslib/abstractions/auth.service';
import { CipherService as CipherServiceAbstraction } from 'jslib/abstractions/cipher.service';
import { CollectionService as CollectionServiceAbstraction } from 'jslib/abstractions/collection.service';
import { CryptoService as CryptoServiceAbstraction } from 'jslib/abstractions/crypto.service';
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from 'jslib/abstractions/cryptoFunction.service';
import { EnvironmentService as EnvironmentServiceAbstraction } from 'jslib/abstractions/environment.service';
import { EventService as EventLoggingServiceAbstraction } from 'jslib/abstractions/event.service';
import { ExportService as ExportServiceAbstraction } from 'jslib/abstractions/export.service';
import { FileUploadService as FileUploadServiceAbstraction } from 'jslib/abstractions/fileUpload.service';
import { FolderService as FolderServiceAbstraction } from 'jslib/abstractions/folder.service';
import { I18nService as I18nServiceAbstraction } from 'jslib/abstractions/i18n.service';
import { ImportService as ImportServiceAbstraction } from 'jslib/abstractions/import.service';
import { LogService as LogServiceAbstraction } from 'jslib/abstractions/log.service';
import { MessagingService as MessagingServiceAbstraction } from 'jslib/abstractions/messaging.service';
import { NotificationsService as NotificationsServiceAbstraction } from 'jslib/abstractions/notifications.service';
import {
PasswordGenerationService as PasswordGenerationServiceAbstraction,
} from 'jslib-common/abstractions/passwordGeneration.service';
import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from 'jslib-common/abstractions/passwordReprompt.service';
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from 'jslib-common/abstractions/platformUtils.service';
import { PolicyService as PolicyServiceAbstraction } from 'jslib-common/abstractions/policy.service';
import { SearchService as SearchServiceAbstraction } from 'jslib-common/abstractions/search.service';
import { SendService as SendServiceAbstraction } from 'jslib-common/abstractions/send.service';
import { SettingsService as SettingsServiceAbstraction } from 'jslib-common/abstractions/settings.service';
import { StateService as StateServiceAbstraction } from 'jslib-common/abstractions/state.service';
import { StorageService as StorageServiceAbstraction } from 'jslib-common/abstractions/storage.service';
import { SyncService as SyncServiceAbstraction } from 'jslib-common/abstractions/sync.service';
import { TokenService as TokenServiceAbstraction } from 'jslib-common/abstractions/token.service';
import { TotpService as TotpServiceAbstraction } from 'jslib-common/abstractions/totp.service';
import { UserService as UserServiceAbstraction } from 'jslib-common/abstractions/user.service';
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from 'jslib-common/abstractions/vaultTimeout.service';
} from 'jslib/abstractions/passwordGeneration.service';
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from 'jslib/abstractions/platformUtils.service';
import { PolicyService as PolicyServiceAbstraction } from 'jslib/abstractions/policy.service';
import { SearchService as SearchServiceAbstraction } from 'jslib/abstractions/search.service';
import { SendService as SendServiceAbstraction } from 'jslib/abstractions/send.service';
import { SettingsService as SettingsServiceAbstraction } from 'jslib/abstractions/settings.service';
import { StateService as StateServiceAbstraction } from 'jslib/abstractions/state.service';
import { StorageService as StorageServiceAbstraction } from 'jslib/abstractions/storage.service';
import { SyncService as SyncServiceAbstraction } from 'jslib/abstractions/sync.service';
import { TokenService as TokenServiceAbstraction } from 'jslib/abstractions/token.service';
import { TotpService as TotpServiceAbstraction } from 'jslib/abstractions/totp.service';
import { UserService as UserServiceAbstraction } from 'jslib/abstractions/user.service';
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from 'jslib/abstractions/vaultTimeout.service';
const i18nService = new I18nService(window.navigator.language, 'locales');
const stateService = new StateService();
const broadcasterService = new BroadcasterService();
const messagingService = new BroadcasterMessagingService(broadcasterService);
const consoleLogService = new ConsoleLogService(false);
const platformUtilsService = new WebPlatformUtilsService(i18nService, messagingService, consoleLogService);
const platformUtilsService = new WebPlatformUtilsService(i18nService, messagingService);
const storageService: StorageServiceAbstraction = new HtmlStorageService(platformUtilsService);
const secureStorageService: StorageServiceAbstraction = new MemoryStorageService();
const cryptoFunctionService: CryptoFunctionServiceAbstraction = new WebCryptoFunctionService(window,
platformUtilsService);
const consoleLogService = new ConsoleLogService(false);
const cryptoService = new CryptoService(storageService,
platformUtilsService.isDev() ? storageService : secureStorageService, cryptoFunctionService, platformUtilsService,
consoleLogService);
@@ -129,23 +129,23 @@ const containerService = new ContainerService(cryptoService);
const authService = new AuthService(cryptoService, apiService,
userService, tokenService, appIdService, i18nService, platformUtilsService, messagingService, vaultTimeoutService,
consoleLogService);
const exportService = new ExportService(folderService, cipherService, apiService, cryptoService);
const exportService = new ExportService(folderService, cipherService, apiService);
const importService = new ImportService(cipherService, folderService, apiService, i18nService, collectionService,
platformUtilsService, cryptoService);
platformUtilsService);
const notificationsService = new NotificationsService(userService, syncService, appIdService,
apiService, vaultTimeoutService, async () => messagingService.send('logout', { expired: true }), consoleLogService);
const environmentService = new EnvironmentService(apiService, storageService, notificationsService);
const auditService = new AuditService(cryptoFunctionService, apiService);
const eventLoggingService = new EventLoggingService(storageService, apiService, userService, cipherService);
const passwordRepromptService = new PasswordRepromptService(i18nService, cryptoService, platformUtilsService);
containerService.attachToWindow(window);
export function initFactory(): Function {
return async () => {
await (storageService as HtmlStorageService).init();
const isDev = platformUtilsService.isDev();
if (process.env.ENV !== 'production' || platformUtilsService.isSelfHost()) {
if (isDev || platformUtilsService.isSelfHost()) {
environmentService.baseUrl = window.location.origin;
} else {
environmentService.notificationsUrl = 'https://notifications.bitwarden.com';
@@ -222,7 +222,6 @@ export function initFactory(): Function {
{ provide: EventLoggingServiceAbstraction, useValue: eventLoggingService },
{ provide: PolicyServiceAbstraction, useValue: policyService },
{ provide: SendServiceAbstraction, useValue: sendService },
{ provide: PasswordRepromptServiceAbstraction, useValue: passwordRepromptService },
{
provide: APP_INITIALIZER,
useFactory: initFactory,

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