A few improvements, requested from the review:
- File reading is now happening later in the process; - File reading now reuses methods from `core/attachment`; - Errors thrown in the import now include an error message; - Adds prettier command to "prettify" all files; - Adds prettier command to check for files not conforming to prettier's config; - Makes CI run the prettier:check command; - Changes `export const method = () => {};` to `export function method() {}` in the `1pux-parser` file; - Other minor consistency changes/fixes/improvements; - Actually ran prettier on every file, and it had a lot of things to tweak.
This commit is contained in:
parent
db18adf7fd
commit
50ae105b45
|
@ -2,43 +2,43 @@ name: "Build And Publish Desktop Tauri Apps"
|
|||
on: [workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
build_and_publish:
|
||||
name: Build And Publish
|
||||
build_and_publish:
|
||||
name: Build And Publish
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-latest, ubuntu-latest, windows-latest]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-latest, ubuntu-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
- name: install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: install tauri bundler
|
||||
run: cargo install tauri-bundler --force
|
||||
- name: install webkit2gtk (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y webkit2gtk-4.0
|
||||
- name: install app dependencies and bootstrap packages
|
||||
run: npm install
|
||||
- uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
PL_SERVER_URL: https://api.padloc.app
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tagName: tauri-v__VERSION__ # the action automatically replaces \_\_VERSION\_\_ with the app version
|
||||
releaseName: "Padloc (Tauri Edition) v__VERSION__"
|
||||
body: "WARNING: The builds in this release are experimental. Use at your own risk!"
|
||||
draft: true
|
||||
prerelease: true
|
||||
projectPath: packages/tauri
|
||||
npmScript: build
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
- name: install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: install tauri bundler
|
||||
run: cargo install tauri-bundler --force
|
||||
- name: install webkit2gtk (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y webkit2gtk-4.0
|
||||
- name: install app dependencies and bootstrap packages
|
||||
run: npm install
|
||||
- uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
PL_SERVER_URL: https://api.padloc.app
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tagName: tauri-v__VERSION__ # the action automatically replaces \_\_VERSION\_\_ with the app version
|
||||
releaseName: "Padloc (Tauri Edition) v__VERSION__"
|
||||
body: "WARNING: The builds in this release are experimental. Use at your own risk!"
|
||||
draft: true
|
||||
prerelease: true
|
||||
projectPath: packages/tauri
|
||||
npmScript: build
|
||||
|
|
|
@ -3,18 +3,20 @@ name: Run Tests
|
|||
on: [push]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.13.1
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run pwa test build
|
||||
run: npm run pwa:build
|
||||
- name: Test starting zero-config server
|
||||
run: npm run server:start-dry
|
||||
#- name: Run tests
|
||||
# run: npm test
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16.13.1
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run prettier check
|
||||
run: npm run prettier:check
|
||||
- name: Run pwa test build
|
||||
run: npm run pwa:build
|
||||
- name: Test starting zero-config server
|
||||
run: npm run server:start-dry
|
||||
#- name: Run tests
|
||||
# run: npm test
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
app/src/core/*.js
|
||||
package-lock.json
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
{
|
||||
"lit-plugin.globalAttributes": [
|
||||
"disabled"
|
||||
],
|
||||
"lit-plugin.globalAttributes": ["disabled"],
|
||||
"files.associations": {
|
||||
"*.svg": "html"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ For more configuration options, see [Configuration](#configuration)
|
|||
|
||||
To add dependencies, you can use `scope=[scope-without-@padloc/] npm run add [package]` and to remove them, run `scope=[scope-without-@padloc/] npm run remove [package]`.
|
||||
|
||||
Use `npm run prettier` to make "prettify" all files.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Environment Variable | Default | Description |
|
||||
|
|
|
@ -7,4 +7,4 @@
|
|||
"appId": "app.padloc",
|
||||
"scheme": "padloc",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module.exports = function(config) {
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
frameworks: ["mocha", "chai"],
|
||||
files: ["test/tests.js"],
|
||||
|
@ -9,6 +9,6 @@ module.exports = function(config) {
|
|||
browsers: ["ChromeHeadless"],
|
||||
autoWatch: false,
|
||||
// singleRun: false, // Karma captures browsers, runs the tests and exits
|
||||
concurrency: Infinity
|
||||
concurrency: Infinity,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
{
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "4.0.0",
|
||||
"exact": true
|
||||
"packages": ["packages/*"],
|
||||
"version": "4.0.0",
|
||||
"exact": true
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"license": "GPL-3.0",
|
||||
"devDependencies": {
|
||||
"lerna": "4.0.0",
|
||||
"prettier": "2.5.1",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
|
@ -5658,6 +5659,18 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
|
||||
"integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
|
@ -12266,6 +12279,12 @@
|
|||
"find-up": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
|
||||
"integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
|
||||
"dev": true
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
|
|
79
package.json
79
package.json
|
@ -1,40 +1,43 @@
|
|||
{
|
||||
"name": "padloc",
|
||||
"private": true,
|
||||
"version": "4.0.0",
|
||||
"description": "A minimalist password manager",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPL-3.0",
|
||||
"homepage": "https://padlock.io/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/maklesoft/padlock.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"main": "main.js",
|
||||
"devDependencies": {
|
||||
"lerna": "4.0.0",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "lerna bootstrap",
|
||||
"bootstrap": "lerna bootstrap",
|
||||
"pwa:build": "lerna run build --scope @padloc/pwa",
|
||||
"pwa:start": "lerna run start --scope @padloc/pwa",
|
||||
"server:start": "lerna run start --scope @padloc/server --stream",
|
||||
"server:start-dry": "lerna run start-dry --stream --scope @padloc/server",
|
||||
"electron:build": "cd packages/electron && npm run build && cd ../..",
|
||||
"start": "npm run pwa:build && lerna run --scope '@padloc/{server,pwa}' --parallel start",
|
||||
"dev": "lerna run --parallel --scope '@padloc/{server,pwa}' --parallel dev",
|
||||
"tauri:dev": "lerna run --parallel --scope '@padloc/{server,tauri}' --parallel dev",
|
||||
"repl": "cd packages/server && npm run repl && cd ../..",
|
||||
"test": "lerna run test",
|
||||
"locale:extract": "lerna run extract --scope '@padloc/locale'",
|
||||
"add": "lerna add $1 --scope=@padloc/$scope",
|
||||
"remove": "rm packages/$scope/package-lock.json && lerna exec \"npm uninstall $1\" --scope=@padloc/$scope"
|
||||
}
|
||||
"name": "padloc",
|
||||
"private": true,
|
||||
"version": "4.0.0",
|
||||
"description": "A minimalist password manager",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPL-3.0",
|
||||
"homepage": "https://padloc.app/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/padloc/padloc.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"main": "main.js",
|
||||
"devDependencies": {
|
||||
"lerna": "4.0.0",
|
||||
"prettier": "2.5.1",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "lerna bootstrap",
|
||||
"bootstrap": "lerna bootstrap",
|
||||
"pwa:build": "lerna run build --scope @padloc/pwa",
|
||||
"pwa:start": "lerna run start --scope @padloc/pwa",
|
||||
"server:start": "lerna run start --scope @padloc/server --stream",
|
||||
"server:start-dry": "lerna run start-dry --stream --scope @padloc/server",
|
||||
"electron:build": "cd packages/electron && npm run build && cd ../..",
|
||||
"start": "npm run pwa:build && lerna run --scope '@padloc/{server,pwa}' --parallel start",
|
||||
"dev": "lerna run --parallel --scope '@padloc/{server,pwa}' --parallel dev",
|
||||
"tauri:dev": "lerna run --parallel --scope '@padloc/{server,tauri}' --parallel dev",
|
||||
"repl": "cd packages/server && npm run repl && cd ../..",
|
||||
"test": "lerna run test",
|
||||
"locale:extract": "lerna run extract --scope '@padloc/locale'",
|
||||
"add": "lerna add $1 --scope=@padloc/$scope",
|
||||
"remove": "rm packages/$scope/package-lock.json && lerna exec \"npm uninstall $1\" --scope=@padloc/$scope",
|
||||
"prettier": "prettier --write .",
|
||||
"prettier:check": "prettier --check ."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
{
|
||||
"name": "@padloc/app",
|
||||
"version": "4.0.0",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"files": [
|
||||
"src",
|
||||
"assets",
|
||||
"types",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/app"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/core": "4.0.0",
|
||||
"@padloc/locale": "4.0.0",
|
||||
"@simplewebauthn/browser": "4.0.0",
|
||||
"@simplewebauthn/typescript-types": "4.0.0",
|
||||
"@types/dompurify": "2.3.1",
|
||||
"@types/marked": "3.0.1",
|
||||
"@types/papaparse": "5.2.5",
|
||||
"@types/qrcode": "1.4.1",
|
||||
"@types/ua-parser-js": "0.7.36",
|
||||
"@types/workbox-precaching": "4.3.1",
|
||||
"@types/workbox-sw": "4.3.1",
|
||||
"@types/workbox-window": "4.3.3",
|
||||
"@types/zxcvbn": "4.4.1",
|
||||
"@webcomponents/webcomponentsjs": "2.5.0",
|
||||
"autosize": "5.0.0",
|
||||
"date-fns": "2.22.1",
|
||||
"dompurify": "2.3.3",
|
||||
"event-target-shim": "6.0.2",
|
||||
"http-server": "0.12.3",
|
||||
"jsqr": "1.4.0",
|
||||
"jszip": "3.7.1",
|
||||
"lit": "2.0.0-rc.2",
|
||||
"localforage": "1.9.0",
|
||||
"marked": "3.0.4",
|
||||
"papaparse": "5.3.1",
|
||||
"qrcode": "1.4.4",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"typescript": "4.4.3",
|
||||
"ua-parser-js": "0.7.28",
|
||||
"workbox-precaching": "6.2.0",
|
||||
"workbox-sw": "6.1.5",
|
||||
"workbox-window": "6.1.5",
|
||||
"zxcvbn": "4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "4.2.18",
|
||||
"@types/mocha": "8.2.2",
|
||||
"chai": "4.3.4",
|
||||
"mocha": "8.4.0"
|
||||
},
|
||||
"description": "Padloc Web-Based UI package"
|
||||
"name": "@padloc/app",
|
||||
"version": "4.0.0",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"files": [
|
||||
"src",
|
||||
"assets",
|
||||
"types",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/app"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/core": "4.0.0",
|
||||
"@padloc/locale": "4.0.0",
|
||||
"@simplewebauthn/browser": "4.0.0",
|
||||
"@simplewebauthn/typescript-types": "4.0.0",
|
||||
"@types/dompurify": "2.3.1",
|
||||
"@types/marked": "3.0.1",
|
||||
"@types/papaparse": "5.2.5",
|
||||
"@types/qrcode": "1.4.1",
|
||||
"@types/ua-parser-js": "0.7.36",
|
||||
"@types/workbox-precaching": "4.3.1",
|
||||
"@types/workbox-sw": "4.3.1",
|
||||
"@types/workbox-window": "4.3.3",
|
||||
"@types/zxcvbn": "4.4.1",
|
||||
"@webcomponents/webcomponentsjs": "2.5.0",
|
||||
"autosize": "5.0.0",
|
||||
"date-fns": "2.22.1",
|
||||
"dompurify": "2.3.3",
|
||||
"event-target-shim": "6.0.2",
|
||||
"http-server": "0.12.3",
|
||||
"jsqr": "1.4.0",
|
||||
"jszip": "3.7.1",
|
||||
"lit": "2.0.0-rc.2",
|
||||
"localforage": "1.9.0",
|
||||
"marked": "3.0.4",
|
||||
"papaparse": "5.3.1",
|
||||
"qrcode": "1.4.4",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"typescript": "4.4.3",
|
||||
"ua-parser-js": "0.7.28",
|
||||
"workbox-precaching": "6.2.0",
|
||||
"workbox-sw": "6.1.5",
|
||||
"workbox-window": "6.1.5",
|
||||
"zxcvbn": "4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "4.2.18",
|
||||
"@types/mocha": "8.2.2",
|
||||
"chai": "4.3.4",
|
||||
"mocha": "8.4.0"
|
||||
},
|
||||
"description": "Padloc Web-Based UI package"
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ export class Dialog<I, R> extends LitElement {
|
|||
Dialog.openDialogs.delete(this);
|
||||
}
|
||||
|
||||
async show(_input: I = (undefined as any) as I) {
|
||||
async show(_input: I = undefined as any as I) {
|
||||
Dialog.openDialogs.add(this);
|
||||
this.open = true;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import { stringToBytes } from "@padloc/core/src/encoding";
|
|||
@customElement("pl-import-dialog")
|
||||
export class ImportDialog extends Dialog<File, void> {
|
||||
@state()
|
||||
private _rawData: null | string | ArrayBuffer = "";
|
||||
private _file: File;
|
||||
|
||||
@state()
|
||||
private _items: VaultItem[] = [];
|
||||
|
@ -71,19 +71,10 @@ export class ImportDialog extends Dialog<File, void> {
|
|||
await this.updateComplete;
|
||||
const result = super.show();
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
this._rawData = reader.result;
|
||||
this._formatSelect.value = (imp.guessFormat(file, this._rawData) || imp.CSV).value;
|
||||
this._parseData();
|
||||
this._vaultSelect.value = app.mainVault!;
|
||||
};
|
||||
|
||||
if (imp.doesFileRequireReadingAsBinary(file)) {
|
||||
reader.readAsArrayBuffer(file);
|
||||
} else {
|
||||
reader.readAsText(file);
|
||||
}
|
||||
this._file = file;
|
||||
this._formatSelect.value = ((await imp.guessFormat(file)) || imp.CSV).value;
|
||||
await this._parseData();
|
||||
this._vaultSelect.value = app.mainVault!;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -100,7 +91,7 @@ Github,"work,coding",https://github.com,john.doe@gmail.com,129lskdf93`)
|
|||
}
|
||||
|
||||
private async _parseData(): Promise<void> {
|
||||
const rawStr = this._rawData;
|
||||
const file = this._file;
|
||||
|
||||
switch (this._formatSelect.value) {
|
||||
case imp.PADLOCK_LEGACY.value:
|
||||
|
@ -111,7 +102,7 @@ Github,"work,coding",https://github.com,john.doe@gmail.com,129lskdf93`)
|
|||
type: "password",
|
||||
validate: async (pwd: string) => {
|
||||
try {
|
||||
this._items = await imp.asPadlockLegacy(rawStr as string, pwd);
|
||||
this._items = await imp.asPadlockLegacy(file, pwd);
|
||||
} catch (e) {
|
||||
throw $l("Wrong Password");
|
||||
}
|
||||
|
@ -125,13 +116,13 @@ Github,"work,coding",https://github.com,john.doe@gmail.com,129lskdf93`)
|
|||
}
|
||||
break;
|
||||
case imp.LASTPASS.value:
|
||||
this._items = await imp.asLastPass(rawStr as string);
|
||||
this._items = await imp.asLastPass(file);
|
||||
break;
|
||||
case imp.CSV.value:
|
||||
this._items = await imp.asCSV(rawStr as string);
|
||||
this._items = await imp.asCSV(file);
|
||||
break;
|
||||
case imp.ONEPUX.value:
|
||||
this._items = await imp.as1Pux(rawStr);
|
||||
this._items = await imp.as1Pux(file);
|
||||
break;
|
||||
case imp.PBES2.value:
|
||||
this.open = false;
|
||||
|
@ -141,7 +132,7 @@ Github,"work,coding",https://github.com,john.doe@gmail.com,129lskdf93`)
|
|||
type: "password",
|
||||
validate: async (pwd: string) => {
|
||||
try {
|
||||
this._items = await imp.asPBES2Container(rawStr as string, pwd);
|
||||
this._items = await imp.asPBES2Container(file, pwd);
|
||||
} catch (e) {
|
||||
throw $l("Wrong Password");
|
||||
}
|
||||
|
|
|
@ -173,9 +173,8 @@ export class Popover extends LitElement {
|
|||
}
|
||||
|
||||
private _getAutoAlignment(): PopoverAlignment {
|
||||
const preferred = (Array.isArray(this.preferAlignment)
|
||||
? [...this.preferAlignment]
|
||||
: [this.preferAlignment]
|
||||
const preferred = (
|
||||
Array.isArray(this.preferAlignment) ? [...this.preferAlignment] : [this.preferAlignment]
|
||||
).reverse();
|
||||
const alignments = [...ALIGNMENTS].sort((a, b) => preferred.indexOf(b) - preferred.indexOf(a));
|
||||
return alignments.find((alignment) => this._isWithinBounds(this._getPosition(alignment))) || alignments[0];
|
||||
|
|
|
@ -65,7 +65,12 @@ export class SettingsTools extends StateMixin(LitElement) {
|
|||
</pl-scroller>
|
||||
</div>
|
||||
|
||||
<input type="file" accept="text/plain,.csv,.pls,.set,.pbes2,.1pux" hidden @change=${() => this._importFile()} />
|
||||
<input
|
||||
type="file"
|
||||
accept="text/plain,.csv,.pls,.set,.pbes2,.1pux"
|
||||
hidden
|
||||
@change=${() => this._importFile()}
|
||||
/>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,308 +1,283 @@
|
|||
import { loadAsync } from 'jszip';
|
||||
import { loadAsync } from "jszip";
|
||||
|
||||
export type OnePuxItemDetailsLoginField = {
|
||||
value: string;
|
||||
id: string;
|
||||
name: string;
|
||||
fieldType: 'A' | 'B' | 'C' | 'E' | 'I' | 'N' | 'P' | 'R' | 'S' | 'T' | 'U';
|
||||
designation?: 'username' | 'password';
|
||||
value: string;
|
||||
id: string;
|
||||
name: string;
|
||||
fieldType: "A" | "B" | "C" | "E" | "I" | "N" | "P" | "R" | "S" | "T" | "U";
|
||||
designation?: "username" | "password";
|
||||
};
|
||||
|
||||
export type OnePuxItemDetailsSection = {
|
||||
title: string;
|
||||
name: string;
|
||||
fields: [
|
||||
{
|
||||
title: string;
|
||||
id: string;
|
||||
value: {
|
||||
concealed?: string;
|
||||
reference?: string;
|
||||
string?: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
url?: string;
|
||||
totp?: string;
|
||||
gender?: string;
|
||||
creditCardType?: string;
|
||||
creditCardNumber?: string;
|
||||
monthYear?: number;
|
||||
date?: number;
|
||||
};
|
||||
indexAtSource: number;
|
||||
guarded: boolean;
|
||||
multiline: boolean;
|
||||
dontGenerate: boolean;
|
||||
inputTraits: {
|
||||
keyboard: string;
|
||||
correction: string;
|
||||
capitalization: string;
|
||||
};
|
||||
},
|
||||
];
|
||||
title: string;
|
||||
name: string;
|
||||
fields: [
|
||||
{
|
||||
title: string;
|
||||
id: string;
|
||||
value: {
|
||||
concealed?: string;
|
||||
reference?: string;
|
||||
string?: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
url?: string;
|
||||
totp?: string;
|
||||
gender?: string;
|
||||
creditCardType?: string;
|
||||
creditCardNumber?: string;
|
||||
monthYear?: number;
|
||||
date?: number;
|
||||
};
|
||||
indexAtSource: number;
|
||||
guarded: boolean;
|
||||
multiline: boolean;
|
||||
dontGenerate: boolean;
|
||||
inputTraits: {
|
||||
keyboard: string;
|
||||
correction: string;
|
||||
capitalization: string;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
export type OnePuxItemDetailsPasswordHistory = {
|
||||
value: string;
|
||||
time: number;
|
||||
value: string;
|
||||
time: number;
|
||||
};
|
||||
|
||||
export type OnePuxItemOverviewUrl = {
|
||||
label: string;
|
||||
url: string;
|
||||
label: string;
|
||||
url: string;
|
||||
};
|
||||
|
||||
export type OnePuxItem = {
|
||||
item?: {
|
||||
uuid: string;
|
||||
favIndex: number;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
trashed: boolean;
|
||||
categoryUuid: string;
|
||||
details: {
|
||||
loginFields: OnePuxItemDetailsLoginField[];
|
||||
notesPlain?: string;
|
||||
sections: OnePuxItemDetailsSection[];
|
||||
passwordHistory: OnePuxItemDetailsPasswordHistory[];
|
||||
documentAttributes?: {
|
||||
fileName: string;
|
||||
documentId: string;
|
||||
decryptedSize: number;
|
||||
};
|
||||
item?: {
|
||||
uuid: string;
|
||||
favIndex: number;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
trashed: boolean;
|
||||
categoryUuid: string;
|
||||
details: {
|
||||
loginFields: OnePuxItemDetailsLoginField[];
|
||||
notesPlain?: string;
|
||||
sections: OnePuxItemDetailsSection[];
|
||||
passwordHistory: OnePuxItemDetailsPasswordHistory[];
|
||||
documentAttributes?: {
|
||||
fileName: string;
|
||||
documentId: string;
|
||||
decryptedSize: number;
|
||||
};
|
||||
};
|
||||
overview: {
|
||||
subtitle: string;
|
||||
urls?: OnePuxItemOverviewUrl[];
|
||||
title: string;
|
||||
url: string;
|
||||
ps?: number;
|
||||
pbe?: number;
|
||||
pgrng?: boolean;
|
||||
tags?: string[];
|
||||
};
|
||||
};
|
||||
overview: {
|
||||
subtitle: string;
|
||||
urls?: OnePuxItemOverviewUrl[];
|
||||
title: string;
|
||||
url: string;
|
||||
ps?: number;
|
||||
pbe?: number;
|
||||
pgrng?: boolean;
|
||||
tags?: string[];
|
||||
file?: {
|
||||
attrs: {
|
||||
uuid: string;
|
||||
name: string;
|
||||
type: string;
|
||||
};
|
||||
path: string;
|
||||
};
|
||||
};
|
||||
file?: {
|
||||
attrs: {
|
||||
uuid: string;
|
||||
name: string;
|
||||
type: string;
|
||||
};
|
||||
path: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type OnePuxVault = {
|
||||
attrs: {
|
||||
uuid: string;
|
||||
desc: string;
|
||||
avatar: string;
|
||||
name: string;
|
||||
type: 'P' | 'E' | 'U';
|
||||
};
|
||||
items: OnePuxItem[];
|
||||
attrs: {
|
||||
uuid: string;
|
||||
desc: string;
|
||||
avatar: string;
|
||||
name: string;
|
||||
type: "P" | "E" | "U";
|
||||
};
|
||||
items: OnePuxItem[];
|
||||
};
|
||||
|
||||
export type OnePuxAccount = {
|
||||
attrs: {
|
||||
accountName: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
email: string;
|
||||
uuid: string;
|
||||
domain: string;
|
||||
};
|
||||
vaults: OnePuxVault[];
|
||||
attrs: {
|
||||
accountName: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
email: string;
|
||||
uuid: string;
|
||||
domain: string;
|
||||
};
|
||||
vaults: OnePuxVault[];
|
||||
};
|
||||
|
||||
export type OnePuxData = {
|
||||
accounts: OnePuxAccount[];
|
||||
accounts: OnePuxAccount[];
|
||||
};
|
||||
|
||||
export type OnePuxAttributes = {
|
||||
version: number;
|
||||
description: string;
|
||||
createdAt: number;
|
||||
version: number;
|
||||
description: string;
|
||||
createdAt: number;
|
||||
};
|
||||
|
||||
export type OnePuxExport = {
|
||||
attributes: OnePuxAttributes;
|
||||
data: OnePuxData;
|
||||
attributes: OnePuxAttributes;
|
||||
data: OnePuxData;
|
||||
};
|
||||
|
||||
export const parse1PuxFile = async (
|
||||
fileContents: string | ArrayBuffer,
|
||||
) => {
|
||||
try {
|
||||
const zip = await loadAsync(fileContents);
|
||||
export async function parse1PuxFile(fileContents: ArrayBuffer): Promise<OnePuxExport> {
|
||||
try {
|
||||
const zip = await loadAsync(fileContents);
|
||||
|
||||
const attributesContent = await zip
|
||||
.file('export.attributes')!
|
||||
.async('string');
|
||||
const attributes = JSON.parse(attributesContent);
|
||||
const dataContent = await zip.file('export.data')!.async('string');
|
||||
const data = JSON.parse(dataContent);
|
||||
const attributesContent = await zip.file("export.attributes")!.async("string");
|
||||
const attributes = JSON.parse(attributesContent);
|
||||
const dataContent = await zip.file("export.data")!.async("string");
|
||||
const data = JSON.parse(dataContent);
|
||||
|
||||
return {
|
||||
attributes,
|
||||
data,
|
||||
} as OnePuxExport;
|
||||
} catch (error) {
|
||||
console.error('Failed to parse .1pux file');
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
return {
|
||||
attributes,
|
||||
data,
|
||||
} as OnePuxExport;
|
||||
} catch (error) {
|
||||
console.error("Failed to parse .1pux file");
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
type RowData = {
|
||||
name: string;
|
||||
tags: string;
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
notes: string;
|
||||
extraFields: ExtraField[];
|
||||
name: string;
|
||||
tags: string;
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
notes: string;
|
||||
extraFields: ExtraField[];
|
||||
};
|
||||
|
||||
type ExtraFieldType =
|
||||
| 'username'
|
||||
| 'password'
|
||||
| 'url'
|
||||
| 'email'
|
||||
| 'date'
|
||||
| 'month'
|
||||
| 'credit'
|
||||
| 'phone'
|
||||
| 'totp'
|
||||
| 'text';
|
||||
| "username"
|
||||
| "password"
|
||||
| "url"
|
||||
| "email"
|
||||
| "date"
|
||||
| "month"
|
||||
| "credit"
|
||||
| "phone"
|
||||
| "totp"
|
||||
| "text";
|
||||
|
||||
type ExtraField = { name: string; value: string; type: ExtraFieldType };
|
||||
|
||||
type ParseFieldTypeToExtraFieldType = (
|
||||
field: OnePuxItemDetailsLoginField,
|
||||
) => ExtraFieldType;
|
||||
|
||||
const parseFieldTypeToExtraFieldType: ParseFieldTypeToExtraFieldType = (
|
||||
field,
|
||||
) => {
|
||||
if (field.designation === 'username') {
|
||||
return 'username';
|
||||
} else if (field.designation === 'password') {
|
||||
return 'password';
|
||||
} else if (field.fieldType === 'E') {
|
||||
return 'email';
|
||||
} else if (field.fieldType === 'U') {
|
||||
return 'url';
|
||||
}
|
||||
return 'text';
|
||||
};
|
||||
|
||||
export const parseToRowData = (
|
||||
item: OnePuxItem['item'],
|
||||
defaultTags?: string[],
|
||||
) => {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rowData: RowData = {
|
||||
name: item.overview.title,
|
||||
tags: [...(defaultTags || []), ...(item.overview.tags || [])].join(','),
|
||||
url: item.overview.url || '',
|
||||
username: '',
|
||||
password: '',
|
||||
notes: item.details.notesPlain || '',
|
||||
extraFields: [],
|
||||
};
|
||||
|
||||
// Skip documents
|
||||
if (
|
||||
item.details.documentAttributes &&
|
||||
item.details.loginFields.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract username, password, and some extraFields
|
||||
item.details.loginFields.forEach((field) => {
|
||||
if (field.designation === 'username') {
|
||||
rowData.username = field.value;
|
||||
} else if (field.designation === 'password') {
|
||||
rowData.password = field.value;
|
||||
} else if (
|
||||
field.fieldType === 'I' ||
|
||||
field.fieldType === 'C' ||
|
||||
field.id.includes(';opid=__') ||
|
||||
field.value === ''
|
||||
) {
|
||||
// Skip these noisy form-fields
|
||||
return;
|
||||
} else {
|
||||
rowData.extraFields.push({
|
||||
name: field.name || field.id,
|
||||
value: field.value,
|
||||
type: parseFieldTypeToExtraFieldType(field),
|
||||
});
|
||||
function parseFieldTypeToExtraFieldType(field: OnePuxItemDetailsLoginField): ExtraFieldType {
|
||||
if (field.designation === "username") {
|
||||
return "username";
|
||||
} else if (field.designation === "password") {
|
||||
return "password";
|
||||
} else if (field.fieldType === "E") {
|
||||
return "email";
|
||||
} else if (field.fieldType === "U") {
|
||||
return "url";
|
||||
}
|
||||
});
|
||||
return "text";
|
||||
}
|
||||
|
||||
// Extract some more extraFields
|
||||
item.details.sections.forEach((section) => {
|
||||
section.fields.forEach((field) => {
|
||||
let value = '';
|
||||
let type: ExtraFieldType = 'text';
|
||||
export function parseToRowData(item: OnePuxItem["item"], defaultTags?: string[]): RowData | undefined {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(field.value, 'concealed')) {
|
||||
value = field.value.concealed || '';
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(field.value, 'reference')
|
||||
) {
|
||||
value = field.value.reference || '';
|
||||
} else if (Object.prototype.hasOwnProperty.call(field.value, 'string')) {
|
||||
value = field.value.string || '';
|
||||
} else if (Object.prototype.hasOwnProperty.call(field.value, 'email')) {
|
||||
value = field.value.email || '';
|
||||
type = 'email';
|
||||
} else if (Object.prototype.hasOwnProperty.call(field.value, 'phone')) {
|
||||
value = field.value.phone || '';
|
||||
type = 'phone';
|
||||
} else if (Object.prototype.hasOwnProperty.call(field.value, 'url')) {
|
||||
value = field.value.url || '';
|
||||
type = 'url';
|
||||
} else if (Object.prototype.hasOwnProperty.call(field.value, 'totp')) {
|
||||
value = field.value.totp || '';
|
||||
type = 'totp';
|
||||
} else if (Object.prototype.hasOwnProperty.call(field.value, 'gender')) {
|
||||
value = field.value.gender || '';
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(field.value, 'creditCardType')
|
||||
) {
|
||||
value = field.value.creditCardType || '';
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(field.value, 'creditCardNumber')
|
||||
) {
|
||||
value = field.value.creditCardNumber || '';
|
||||
type = 'credit';
|
||||
} else if (
|
||||
Object.prototype.hasOwnProperty.call(field.value, 'monthYear')
|
||||
) {
|
||||
value =
|
||||
(field.value.monthYear && field.value.monthYear.toString()) || '';
|
||||
type = 'month';
|
||||
} else if (Object.prototype.hasOwnProperty.call(field.value, 'date')) {
|
||||
value = (field.value.date && field.value.date.toString()) || '';
|
||||
type = 'date';
|
||||
} else {
|
||||
// Default, so no data is lost when something new comes up
|
||||
value = JSON.stringify(field.value);
|
||||
}
|
||||
const rowData: RowData = {
|
||||
name: item.overview.title,
|
||||
tags: [...(defaultTags || []), ...(item.overview.tags || [])].join(","),
|
||||
url: item.overview.url || "",
|
||||
username: "",
|
||||
password: "",
|
||||
notes: item.details.notesPlain || "",
|
||||
extraFields: [],
|
||||
};
|
||||
|
||||
rowData.extraFields.push({
|
||||
name: field.title || field.id,
|
||||
value,
|
||||
type,
|
||||
});
|
||||
// Skip documents
|
||||
if (item.details.documentAttributes && item.details.loginFields.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract username, password, and some extraFields
|
||||
item.details.loginFields.forEach((field) => {
|
||||
if (field.designation === "username") {
|
||||
rowData.username = field.value;
|
||||
} else if (field.designation === "password") {
|
||||
rowData.password = field.value;
|
||||
} else if (
|
||||
field.fieldType === "I" ||
|
||||
field.fieldType === "C" ||
|
||||
field.id.includes(";opid=__") ||
|
||||
field.value === ""
|
||||
) {
|
||||
// Skip these noisy form-fields
|
||||
return;
|
||||
} else {
|
||||
rowData.extraFields.push({
|
||||
name: field.name || field.id,
|
||||
value: field.value,
|
||||
type: parseFieldTypeToExtraFieldType(field),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return rowData;
|
||||
};
|
||||
// Extract some more extraFields
|
||||
item.details.sections.forEach((section) => {
|
||||
section.fields.forEach((field) => {
|
||||
let value = "";
|
||||
let type: ExtraFieldType = "text";
|
||||
|
||||
if (field.value.concealed) {
|
||||
value = field.value.concealed || "";
|
||||
} else if (field.value.reference) {
|
||||
value = field.value.reference || "";
|
||||
} else if (field.value.string) {
|
||||
value = field.value.string || "";
|
||||
} else if (field.value.email) {
|
||||
value = field.value.email || "";
|
||||
type = "email";
|
||||
} else if (field.value.phone) {
|
||||
value = field.value.phone || "";
|
||||
type = "phone";
|
||||
} else if (field.value.url) {
|
||||
value = field.value.url || "";
|
||||
type = "url";
|
||||
} else if (field.value.totp) {
|
||||
value = field.value.totp || "";
|
||||
type = "totp";
|
||||
} else if (field.value.gender) {
|
||||
value = field.value.gender || "";
|
||||
} else if (field.value.creditCardType) {
|
||||
value = field.value.creditCardType || "";
|
||||
} else if (field.value.creditCardNumber) {
|
||||
value = field.value.creditCardNumber || "";
|
||||
type = "credit";
|
||||
} else if (field.value.monthYear) {
|
||||
value = (field.value.monthYear && field.value.monthYear.toString()) || "";
|
||||
type = "month";
|
||||
} else if (field.value.date) {
|
||||
value = (field.value.date && field.value.date.toString()) || "";
|
||||
type = "date";
|
||||
} else {
|
||||
// Default, so no data is lost when something new comes up
|
||||
value = JSON.stringify(field.value);
|
||||
}
|
||||
|
||||
rowData.extraFields.push({
|
||||
name: field.title || field.id,
|
||||
value,
|
||||
type,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return rowData;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ const defaults = {
|
|||
initialDelay: 0,
|
||||
fullDuration: 1000,
|
||||
clear: false,
|
||||
direction: "normal"
|
||||
direction: "normal",
|
||||
};
|
||||
|
||||
const clearAnimation = new Map<HTMLElement, number>();
|
||||
|
@ -20,10 +20,13 @@ export function animateElement(el: HTMLElement, opts = {}) {
|
|||
el.style.animation = `${animation} ${direction} ${duration}ms ${easing} ${delay}ms ${fill}`;
|
||||
if (clear) {
|
||||
const clearDelay = typeof clear === "number" ? clear : 0;
|
||||
clearAnimation.set(el, window.setTimeout(() => (el.style.animation = ""), delay + duration + clearDelay));
|
||||
clearAnimation.set(
|
||||
el,
|
||||
window.setTimeout(() => (el.style.animation = ""), delay + duration + clearDelay)
|
||||
);
|
||||
}
|
||||
|
||||
return new Promise(resolve => setTimeout(resolve, delay + duration));
|
||||
return new Promise((resolve) => setTimeout(resolve, delay + duration));
|
||||
}
|
||||
|
||||
export function animateCascade(nodes: Iterable<Node | Element>, opts = {}) {
|
||||
|
|
|
@ -5,8 +5,9 @@ import { VaultItem, Field, createVaultItem, FieldType } from "@padloc/core/src/i
|
|||
import { Err, ErrorCode } from "@padloc/core/src/error";
|
||||
import { uuid } from "@padloc/core/src/util";
|
||||
import { translate as $l } from "@padloc/locale/src/translate";
|
||||
import { readFileAsText, readFileAsArrayBuffer } from "@padloc/core/src/attachment";
|
||||
|
||||
import { parse1PuxFile, parseToRowData, OnePuxItem } from "./1pux-parser";
|
||||
import { OnePuxItem } from "./1pux-parser";
|
||||
|
||||
export interface ImportFormat {
|
||||
value: "csv" | "padlock-legacy" | "lastpass" | "padloc" | "1pux";
|
||||
|
@ -101,27 +102,27 @@ export async function isCSV(data: string): Promise<Boolean> {
|
|||
return papa.parse(data).errors.length === 0;
|
||||
}
|
||||
|
||||
export async function asCSV(data: string, nameColIndex?: number, tagsColIndex?: number): Promise<VaultItem[]> {
|
||||
export async function asCSV(file: File, nameColIndex?: number, tagsColIndex?: number): Promise<VaultItem[]> {
|
||||
const data = await readFileAsText(file);
|
||||
const papa = await loadPapa();
|
||||
const parsed = papa.parse(data);
|
||||
if (parsed.errors.length) {
|
||||
throw new Err(ErrorCode.INVALID_CSV);
|
||||
throw new Err(ErrorCode.INVALID_CSV, "Failed to parse .csv file.");
|
||||
}
|
||||
return fromTable(parsed.data, nameColIndex, tagsColIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given string represents a Padlock enrypted backup
|
||||
*/
|
||||
export function isPadlockV1(data: string): boolean {
|
||||
export async function isPadlockV1(file: File): Promise<boolean> {
|
||||
try {
|
||||
const data = await readFileAsText(file);
|
||||
return validateLegacyContainer(unmarshal(data));
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function asPadlockLegacy(data: string, password: string): Promise<VaultItem[]> {
|
||||
export async function asPadlockLegacy(file: File, password: string): Promise<VaultItem[]> {
|
||||
const data = await readFileAsText(file);
|
||||
const container = parseLegacyContainer(unmarshal(data));
|
||||
await container.unlock(password);
|
||||
return importLegacyContainer(container);
|
||||
|
@ -146,16 +147,18 @@ export async function importLegacyContainer(container: PBES2Container) {
|
|||
return Promise.all(items);
|
||||
}
|
||||
|
||||
export function isPBES2Container(data: string) {
|
||||
export async function isPBES2Container(file: File) {
|
||||
try {
|
||||
const data = await readFileAsText(file);
|
||||
new PBES2Container().fromRaw(unmarshal(data));
|
||||
return true;
|
||||
} catch (e) {
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function asPBES2Container(data: string, password: string): Promise<VaultItem[]> {
|
||||
export async function asPBES2Container(file: File, password: string): Promise<VaultItem[]> {
|
||||
const data = await readFileAsText(file);
|
||||
const container = new PBES2Container().fromRaw(unmarshal(data));
|
||||
await container.unlock(password);
|
||||
|
||||
|
@ -234,7 +237,8 @@ async function lpParseRow(row: string[]): Promise<VaultItem> {
|
|||
return createVaultItem(row[nameIndex], fields, dir ? [dir] : []);
|
||||
}
|
||||
|
||||
export async function asLastPass(data: string): Promise<VaultItem[]> {
|
||||
export async function asLastPass(file: File): Promise<VaultItem[]> {
|
||||
const data = await readFileAsText(file);
|
||||
const papa = await loadPapa();
|
||||
let items = papa
|
||||
.parse(data)
|
||||
|
@ -247,22 +251,26 @@ export async function asLastPass(data: string): Promise<VaultItem[]> {
|
|||
return Promise.all(items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given string represents a LastPass CSV file
|
||||
*/
|
||||
export function isLastPass(data: string): boolean {
|
||||
export async function isLastPass(file: File): Promise<boolean> {
|
||||
try {
|
||||
const data = await readFileAsText(file);
|
||||
return data.split("\n")[0] === "url,username,password,extra,name,grouping,fav";
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function parse1PuxItem(accountName: string, vaultName: string, item: OnePuxItem['item']): Promise<VaultItem | undefined> {
|
||||
async function parse1PuxItem(
|
||||
accountName: string,
|
||||
vaultName: string,
|
||||
item: OnePuxItem["item"]
|
||||
): Promise<VaultItem | undefined> {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { parseToRowData } = await import("./1pux-parser");
|
||||
|
||||
const rowData = parseToRowData(item, [accountName, vaultName]);
|
||||
|
||||
if (!rowData) {
|
||||
|
@ -270,10 +278,10 @@ async function parse1PuxItem(accountName: string, vaultName: string, item: OnePu
|
|||
}
|
||||
|
||||
const itemName = rowData.name;
|
||||
const tags = rowData.tags.split(',');
|
||||
const tags = rowData.tags.split(",");
|
||||
|
||||
if (item.trashed) {
|
||||
tags.push('trashed');
|
||||
tags.push("trashed");
|
||||
}
|
||||
|
||||
let fields: Field[] = [
|
||||
|
@ -287,10 +295,10 @@ async function parse1PuxItem(accountName: string, vaultName: string, item: OnePu
|
|||
}
|
||||
|
||||
for (const extraField of rowData.extraFields) {
|
||||
if (extraField.type === 'totp') {
|
||||
if (extraField.type === "totp") {
|
||||
// Extract just the secret
|
||||
try {
|
||||
const secret = new URL(extraField.value).searchParams.get('secret');
|
||||
const secret = new URL(extraField.value).searchParams.get("secret");
|
||||
if (secret) {
|
||||
fields.push(new Field({ name: extraField.name, value: secret, type: FieldType.Totp }));
|
||||
}
|
||||
|
@ -298,24 +306,23 @@ async function parse1PuxItem(accountName: string, vaultName: string, item: OnePu
|
|||
// Do nothing
|
||||
}
|
||||
} else {
|
||||
fields.push(new Field({ name: extraField.name, value: extraField.value, type: extraField.type as FieldType }));
|
||||
fields.push(
|
||||
new Field({ name: extraField.name, value: extraField.value, type: extraField.type as FieldType })
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return createVaultItem(itemName, fields, tags);
|
||||
}
|
||||
|
||||
export async function as1Pux(data: null | string | ArrayBuffer): Promise<VaultItem[]> {
|
||||
if (!data) {
|
||||
throw new Err(ErrorCode.INVALID_1PUX);
|
||||
}
|
||||
|
||||
export async function as1Pux(file: File): Promise<VaultItem[]> {
|
||||
try {
|
||||
const { parse1PuxFile } = await import("./1pux-parser");
|
||||
const data = await readFileAsArrayBuffer(file);
|
||||
const dataExport = await parse1PuxFile(data);
|
||||
|
||||
const items = [];
|
||||
|
||||
|
||||
for (const account of dataExport.data.accounts) {
|
||||
for (const vault of account.vaults) {
|
||||
for (const vaultItem of vault.items) {
|
||||
|
@ -331,7 +338,7 @@ export async function as1Pux(data: null | string | ArrayBuffer): Promise<VaultIt
|
|||
|
||||
return items;
|
||||
} catch (error) {
|
||||
throw new Err(ErrorCode.INVALID_1PUX);
|
||||
throw new Err(ErrorCode.INVALID_1PUX, "Failed to parse .1pux file.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,30 +346,23 @@ export async function as1Pux(data: null | string | ArrayBuffer): Promise<VaultIt
|
|||
* Checks if a given file name ends with .1pux to avoid trying to parse unnecessarily
|
||||
*/
|
||||
export function is1Pux(file: File): boolean {
|
||||
return file.name.endsWith('.1pux');
|
||||
return file.name.endsWith(".1pux");
|
||||
}
|
||||
|
||||
export function guessFormat(file: File, data: string | null | ArrayBuffer): ImportFormat {
|
||||
if (isPBES2Container(data as string)) {
|
||||
return PBES2;
|
||||
}
|
||||
if (isPadlockV1(data as string)) {
|
||||
return PADLOCK_LEGACY;
|
||||
}
|
||||
if (isLastPass(data as string)) {
|
||||
return LASTPASS;
|
||||
}
|
||||
export async function guessFormat(file: File): Promise<ImportFormat> {
|
||||
// Try to guess sync first (won't need parsing)
|
||||
if (is1Pux(file)) {
|
||||
return ONEPUX;
|
||||
}
|
||||
|
||||
return CSV;
|
||||
}
|
||||
|
||||
export function doesFileRequireReadingAsBinary(file: File): boolean {
|
||||
if (is1Pux(file)) {
|
||||
return true;
|
||||
if (await isPBES2Container(file)) {
|
||||
return PBES2;
|
||||
}
|
||||
if (await isPadlockV1(file)) {
|
||||
return PADLOCK_LEGACY;
|
||||
}
|
||||
if (await isLastPass(file)) {
|
||||
return LASTPASS;
|
||||
}
|
||||
|
||||
return false;
|
||||
return CSV;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes" />
|
||||
<title>lit-element tests</title>
|
||||
<link href="../node_modules/mocha/mocha.css" rel="stylesheet" />
|
||||
<script src="../node_modules/mocha/mocha.js"></script>
|
||||
|
@ -9,7 +9,7 @@
|
|||
<script>
|
||||
mocha.setup({
|
||||
ui: "tdd",
|
||||
timeout: 1000000
|
||||
timeout: 1000000,
|
||||
});
|
||||
</script>
|
||||
<script type="module" src="dist/crypto.js"></script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
interface Navigator {
|
||||
Backbutton: any
|
||||
Backbutton: any;
|
||||
}
|
||||
|
||||
interface Window {
|
||||
|
|
|
@ -1,82 +1,82 @@
|
|||
{
|
||||
"name": "app.padloc",
|
||||
"version": "4.0.0",
|
||||
"displayName": "Padloc",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"cordova": {
|
||||
"platforms": [
|
||||
"ios",
|
||||
"android"
|
||||
],
|
||||
"plugins": {
|
||||
"cordova-plugin-app-version": {},
|
||||
"cordova-plugin-backbutton": {},
|
||||
"ionic-plugin-keyboard": {},
|
||||
"cordova-plugin-statusbar": {},
|
||||
"cordova-clipboard": {},
|
||||
"cordova-plugin-qrscanner": {},
|
||||
"cordova-plugin-device": {},
|
||||
"cordova-plugin-x-socialsharing": {
|
||||
"ANDROID_SUPPORT_V4_VERSION": "24.1.1+",
|
||||
"PHOTO_LIBRARY_ADD_USAGE_DESCRIPTION": "This app requires photo library access to function properly.",
|
||||
"PHOTO_LIBRARY_USAGE_DESCRIPTION": "This app requires photo library access to function properly."
|
||||
},
|
||||
"cordova-plugin-splashscreen": {},
|
||||
"cordova-plugin-ionic-webview": {
|
||||
"ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
|
||||
},
|
||||
"cordova-plugin-fingerprint-aio": {
|
||||
"FACEID_USAGE_DESCRIPTION": " "
|
||||
},
|
||||
"cordova-plugin-privacyscreen": {},
|
||||
"cordova-plugin-inappbrowser": {},
|
||||
"cordova-plugin-androidx-adapter": {}
|
||||
"name": "app.padloc",
|
||||
"version": "4.0.0",
|
||||
"displayName": "Padloc",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"cordova": {
|
||||
"platforms": [
|
||||
"ios",
|
||||
"android"
|
||||
],
|
||||
"plugins": {
|
||||
"cordova-plugin-app-version": {},
|
||||
"cordova-plugin-backbutton": {},
|
||||
"ionic-plugin-keyboard": {},
|
||||
"cordova-plugin-statusbar": {},
|
||||
"cordova-clipboard": {},
|
||||
"cordova-plugin-qrscanner": {},
|
||||
"cordova-plugin-device": {},
|
||||
"cordova-plugin-x-socialsharing": {
|
||||
"ANDROID_SUPPORT_V4_VERSION": "24.1.1+",
|
||||
"PHOTO_LIBRARY_ADD_USAGE_DESCRIPTION": "This app requires photo library access to function properly.",
|
||||
"PHOTO_LIBRARY_USAGE_DESCRIPTION": "This app requires photo library access to function properly."
|
||||
},
|
||||
"cordova-plugin-splashscreen": {},
|
||||
"cordova-plugin-ionic-webview": {
|
||||
"ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
|
||||
},
|
||||
"cordova-plugin-fingerprint-aio": {
|
||||
"FACEID_USAGE_DESCRIPTION": " "
|
||||
},
|
||||
"cordova-plugin-privacyscreen": {},
|
||||
"cordova-plugin-inappbrowser": {},
|
||||
"cordova-plugin-androidx-adapter": {}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"cordova-clipboard": "1.3.0",
|
||||
"cordova-ios": "6.2.0",
|
||||
"cordova-plugin-add-swift-support": "2.0.2",
|
||||
"cordova-plugin-app-version": "~0.1.12",
|
||||
"cordova-plugin-backbutton": "~0.3.0",
|
||||
"cordova-plugin-device": "2.0.3",
|
||||
"cordova-plugin-inappbrowser": "5.0.0",
|
||||
"cordova-plugin-ionic-webview": "5.0.0",
|
||||
"cordova-plugin-privacyscreen": "0.4.0",
|
||||
"cordova-plugin-qrscanner": "3.0.1",
|
||||
"cordova-plugin-splashscreen": "6.0.0",
|
||||
"cordova-plugin-statusbar": "2.4.3",
|
||||
"cordova-plugin-x-socialsharing": "6.0.3",
|
||||
"cordova-plugin-androidx-adapter": "1.1.3",
|
||||
"cordova-plugin-fingerprint-aio": "4.0.2",
|
||||
"es6-promise-plugin": "4.2.2",
|
||||
"ionic-plugin-keyboard": "~2.2.1",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cordova-plugin-qrscanner": "1.0.31",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"cordova": "10.0.0",
|
||||
"cordova-android": "10.1.0",
|
||||
"css-loader": "5.2.6",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"webpack": "5.38.1",
|
||||
"webpack-cli": "4.7.0",
|
||||
"sharp": "0.29.1",
|
||||
"raw-loader": "4.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"start": "npm run build && cordova run"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"cordova-clipboard": "1.3.0",
|
||||
"cordova-ios": "6.2.0",
|
||||
"cordova-plugin-add-swift-support": "2.0.2",
|
||||
"cordova-plugin-app-version": "~0.1.12",
|
||||
"cordova-plugin-backbutton": "~0.3.0",
|
||||
"cordova-plugin-device": "2.0.3",
|
||||
"cordova-plugin-inappbrowser": "5.0.0",
|
||||
"cordova-plugin-ionic-webview": "5.0.0",
|
||||
"cordova-plugin-privacyscreen": "0.4.0",
|
||||
"cordova-plugin-qrscanner": "3.0.1",
|
||||
"cordova-plugin-splashscreen": "6.0.0",
|
||||
"cordova-plugin-statusbar": "2.4.3",
|
||||
"cordova-plugin-x-socialsharing": "6.0.3",
|
||||
"cordova-plugin-androidx-adapter": "1.1.3",
|
||||
"cordova-plugin-fingerprint-aio": "4.0.2",
|
||||
"es6-promise-plugin": "4.2.2",
|
||||
"ionic-plugin-keyboard": "~2.2.1",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cordova-plugin-qrscanner": "1.0.31",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"cordova": "10.0.0",
|
||||
"cordova-android": "10.1.0",
|
||||
"css-loader": "5.2.6",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"webpack": "5.38.1",
|
||||
"webpack-cli": "4.7.0",
|
||||
"sharp": "0.29.1",
|
||||
"raw-loader": "4.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"start": "npm run build && cordova run"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,4 +13,3 @@
|
|||
"include": ["src/**/*.ts", "../app/types/*.ts"],
|
||||
"exclude": ["node_modules/**/*.ts"]
|
||||
}
|
||||
|
||||
|
|
|
@ -105,24 +105,7 @@ module.exports = {
|
|||
.toBuffer();
|
||||
|
||||
const iosIconSizes = [
|
||||
20,
|
||||
29,
|
||||
40,
|
||||
50,
|
||||
57,
|
||||
58,
|
||||
60,
|
||||
72,
|
||||
76,
|
||||
80,
|
||||
87,
|
||||
100,
|
||||
114,
|
||||
120,
|
||||
144,
|
||||
152,
|
||||
167,
|
||||
180,
|
||||
20, 29, 40, 50, 57, 58, 60, 72, 76, 80, 87, 100, 114, 120, 144, 152, 167, 180,
|
||||
];
|
||||
|
||||
const androidIconSizes = [36, 48, 72, 96, 144, 192];
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
{
|
||||
"name": "@padloc/core",
|
||||
"version": "4.0.0",
|
||||
"description": "padloc core module",
|
||||
"main": "index.js",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPLv3",
|
||||
"files": [
|
||||
"src",
|
||||
"vendor",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"dependencies": {
|
||||
"@padloc/locale": "4.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "4.2.18",
|
||||
"@types/mocha": "8.2.2",
|
||||
"chai": "4.3.4",
|
||||
"mocha": "8.4.0",
|
||||
"ts-node": "10.0.0",
|
||||
"typedoc": "0.22.4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "cd test && mocha -r ts-node/register *.ts",
|
||||
"docs": "typedoc --mode modules --out docs"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/core"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
}
|
||||
"name": "@padloc/core",
|
||||
"version": "4.0.0",
|
||||
"description": "padloc core module",
|
||||
"main": "index.js",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPLv3",
|
||||
"files": [
|
||||
"src",
|
||||
"vendor",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"dependencies": {
|
||||
"@padloc/locale": "4.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "4.2.18",
|
||||
"@types/mocha": "8.2.2",
|
||||
"chai": "4.3.4",
|
||||
"mocha": "8.4.0",
|
||||
"ts-node": "10.0.0",
|
||||
"typedoc": "0.22.4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "cd test && mocha -r ts-node/register *.ts",
|
||||
"docs": "typedoc --mode modules --out docs"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/core"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import { getCryptoProvider as getProvider } from "./platform";
|
|||
import { Err, ErrorCode } from "./error";
|
||||
import { RequestProgress } from "./transport";
|
||||
|
||||
function readFile(blob: File): Promise<Uint8Array> {
|
||||
export async function readFileAsUint8Array(blob: File): Promise<Uint8Array> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
|
||||
|
@ -15,16 +15,33 @@ function readFile(blob: File): Promise<Uint8Array> {
|
|||
resolve(result);
|
||||
};
|
||||
|
||||
reader.onerror = e => {
|
||||
reader.onerror = (error) => {
|
||||
reader.abort();
|
||||
reject(e);
|
||||
reject(error);
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(blob);
|
||||
});
|
||||
}
|
||||
|
||||
function readAsText(blob: File): Promise<string> {
|
||||
export async function readFileAsArrayBuffer(blob: File): Promise<ArrayBuffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = () => {
|
||||
resolve(reader.result as ArrayBuffer);
|
||||
};
|
||||
|
||||
reader.onerror = (error) => {
|
||||
reader.abort();
|
||||
reject(error);
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(blob);
|
||||
});
|
||||
}
|
||||
|
||||
export async function readFileAsText(blob: File): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
|
||||
|
@ -32,9 +49,9 @@ function readAsText(blob: File): Promise<string> {
|
|||
resolve(reader.result as string);
|
||||
};
|
||||
|
||||
reader.onerror = e => {
|
||||
reader.onerror = (error) => {
|
||||
reader.abort();
|
||||
reject(e);
|
||||
reject(error);
|
||||
};
|
||||
|
||||
reader.readAsText(blob);
|
||||
|
@ -49,7 +66,7 @@ function readFileAsDataURL(blob: File): Promise<string> {
|
|||
resolve(reader.result as string);
|
||||
};
|
||||
|
||||
reader.onerror = e => {
|
||||
reader.onerror = (e) => {
|
||||
reader.abort();
|
||||
reject(e);
|
||||
};
|
||||
|
@ -89,7 +106,7 @@ export class Attachment extends SimpleContainer {
|
|||
super();
|
||||
Object.assign(this, {
|
||||
_key: key,
|
||||
...info
|
||||
...info,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -100,7 +117,7 @@ export class Attachment extends SimpleContainer {
|
|||
name: this.name,
|
||||
type: this.type,
|
||||
size: this.size,
|
||||
key: this._key
|
||||
key: this._key,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -113,11 +130,11 @@ export class Attachment extends SimpleContainer {
|
|||
this.size = file.size;
|
||||
this.name = file.name;
|
||||
|
||||
const data = await readFile(file);
|
||||
const data = await readFileAsUint8Array(file);
|
||||
|
||||
this._key = await getProvider().generateKey({
|
||||
algorithm: "AES",
|
||||
keySize: this.encryptionParams.keySize
|
||||
keySize: this.encryptionParams.keySize,
|
||||
} as AESKeyParams);
|
||||
|
||||
await this.setData(data);
|
||||
|
@ -141,7 +158,7 @@ export class Attachment extends SimpleContainer {
|
|||
|
||||
async toText(): Promise<string> {
|
||||
const file = await this.toFile();
|
||||
return readAsText(file);
|
||||
return readFileAsText(file);
|
||||
}
|
||||
|
||||
validate() {
|
||||
|
|
|
@ -7,7 +7,7 @@ export enum PlanType {
|
|||
Premium,
|
||||
Family,
|
||||
Team,
|
||||
Business
|
||||
Business,
|
||||
}
|
||||
|
||||
export class Plan extends Serializable {
|
||||
|
@ -37,7 +37,7 @@ export enum SubscriptionStatus {
|
|||
Trialing = "trialing",
|
||||
Active = "active",
|
||||
Inactive = "inactive",
|
||||
Canceled = "canceled"
|
||||
Canceled = "canceled",
|
||||
}
|
||||
|
||||
export class Subscription extends Serializable {
|
||||
|
|
|
@ -41,10 +41,10 @@ export class Client extends API {
|
|||
method,
|
||||
typeof input === "undefined" ? [] : [input instanceof Serializable ? input.toRaw() : input],
|
||||
progress
|
||||
).then(res => {
|
||||
).then((res) => {
|
||||
return output
|
||||
? Array.isArray(res.result)
|
||||
? res.result.map(each => new output().fromRaw(each))
|
||||
? res.result.map((each) => new output().fromRaw(each))
|
||||
: new output().fromRaw(res.result)
|
||||
: res.result;
|
||||
}) as PromiseWithProgress<any>;
|
||||
|
@ -85,7 +85,7 @@ export class Client extends API {
|
|||
}
|
||||
|
||||
if (res.error) {
|
||||
const err = new Err((res.error.code as any) as ErrorCode, res.error.message);
|
||||
const err = new Err(res.error.code as any as ErrorCode, res.error.message);
|
||||
if (progress) {
|
||||
progress.error = err;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ export class VaultItemCollection extends Serializable implements Iterable<VaultI
|
|||
|
||||
constructor(items: VaultItem[] = []) {
|
||||
super();
|
||||
this._items = new Map(items.map(item => [item.id, item] as [string, VaultItem]));
|
||||
this._items = new Map(items.map((item) => [item.id, item] as [string, VaultItem]));
|
||||
}
|
||||
|
||||
/** Get an item with a given `id` */
|
||||
|
@ -91,8 +91,8 @@ export class VaultItemCollection extends Serializable implements Iterable<VaultI
|
|||
|
||||
protected _toRaw(version: string) {
|
||||
return {
|
||||
items: Array.from(this).map(item => item.toRaw(version)),
|
||||
changes: [...this._changes]
|
||||
items: Array.from(this).map((item) => item.toRaw(version)),
|
||||
changes: [...this._changes],
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -65,15 +65,15 @@ export function parseLegacyContainer(raw: LegacyContainer): PBES2Container {
|
|||
tagSize: raw.ts,
|
||||
keySize: raw.keySize,
|
||||
iv: raw.iv,
|
||||
additionalData: raw.adata
|
||||
additionalData: raw.adata,
|
||||
},
|
||||
keyParams: {
|
||||
algorithm: "PBKDF2",
|
||||
hash: "SHA-256",
|
||||
keySize: raw.keySize,
|
||||
iterations: raw.iter,
|
||||
salt: raw.salt
|
||||
salt: raw.salt,
|
||||
},
|
||||
encryptedData: raw.ct
|
||||
encryptedData: raw.ct,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -20,22 +20,22 @@ export const MIGRATIONS: Migration[] = [
|
|||
up: ({ mainVault, orgs, ...rest }: any) => ({
|
||||
mainVault: { id: mainVault },
|
||||
orgs: orgs.map((org: any) => ({
|
||||
id: org
|
||||
id: org,
|
||||
})),
|
||||
...rest
|
||||
...rest,
|
||||
}),
|
||||
down: ({ mainVault, orgs, ...rest }: any) => ({
|
||||
mainVault: mainVault.id,
|
||||
orgs: orgs.map((org: any) => org.id),
|
||||
...rest
|
||||
})
|
||||
...rest,
|
||||
}),
|
||||
},
|
||||
all: {
|
||||
up: (raw: any, kind?: string) => ({ kind, ...raw }),
|
||||
down: ({ kind, ...rest }) => rest
|
||||
}
|
||||
}
|
||||
}
|
||||
down: ({ kind, ...rest }) => rest,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const EARLIEST_VERSION = MIGRATIONS[0].from;
|
||||
|
@ -44,7 +44,7 @@ export const LATEST_VERSION = MIGRATIONS[MIGRATIONS.length - 1].to;
|
|||
function norm(version: string = EARLIEST_VERSION): string {
|
||||
return version
|
||||
.split(".")
|
||||
.map(part => part.padStart(3, "0"))
|
||||
.map((part) => part.padStart(3, "0"))
|
||||
.join();
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ export function upgrade(kind: string, raw: any, version: string = LATEST_VERSION
|
|||
}
|
||||
|
||||
const migration = MIGRATIONS.find(
|
||||
m => norm(m.from) >= norm(raw.version || EARLIEST_VERSION) && norm(m.to) <= norm(version)
|
||||
(m) => norm(m.from) >= norm(raw.version || EARLIEST_VERSION) && norm(m.to) <= norm(version)
|
||||
);
|
||||
|
||||
if (migration) {
|
||||
|
@ -76,7 +76,7 @@ export function upgrade(kind: string, raw: any, version: string = LATEST_VERSION
|
|||
|
||||
export function downgrade(kind: string, raw: any, version: string = LATEST_VERSION): any {
|
||||
const migration = MIGRATIONS.reverse().find(
|
||||
m => norm(m.to) <= norm(raw.version || LATEST_VERSION) && norm(m.from) >= norm(version)
|
||||
(m) => norm(m.to) <= norm(raw.version || LATEST_VERSION) && norm(m.from) >= norm(version)
|
||||
);
|
||||
|
||||
if (migration) {
|
||||
|
|
|
@ -115,9 +115,7 @@ export interface Platform {
|
|||
authenticatorIndex?: number;
|
||||
}): Promise<StartAuthRequestResponse>;
|
||||
|
||||
completeAuthRequest(
|
||||
req: StartAuthRequestResponse
|
||||
): Promise<{
|
||||
completeAuthRequest(req: StartAuthRequestResponse): Promise<{
|
||||
token: string;
|
||||
accountStatus: AccountStatus;
|
||||
deviceTrusted: boolean;
|
||||
|
@ -193,9 +191,7 @@ export class StubPlatform implements Platform {
|
|||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
async completeAuthRequest(
|
||||
_req: StartAuthRequestResponse
|
||||
): Promise<{
|
||||
async completeAuthRequest(_req: StartAuthRequestResponse): Promise<{
|
||||
token: string;
|
||||
accountStatus: AccountStatus;
|
||||
deviceTrusted: boolean;
|
||||
|
@ -293,9 +289,7 @@ export function startAuthRequest(opts: {
|
|||
return platform.startAuthRequest(opts);
|
||||
}
|
||||
|
||||
export function completeAuthRequest(
|
||||
req: StartAuthRequestResponse
|
||||
): Promise<{
|
||||
export function completeAuthRequest(req: StartAuthRequestResponse): Promise<{
|
||||
token: string;
|
||||
accountStatus: AccountStatus;
|
||||
deviceTrusted: boolean;
|
||||
|
|
|
@ -30,7 +30,7 @@ type Position = [number, number];
|
|||
export const defaults: Options = {
|
||||
height: 9,
|
||||
width: 17,
|
||||
symbols: [" ", ".", "o", "+", "=", "*", "B", "O", "X", "@", "%", "&", "#", "/", "^", "S", "E"]
|
||||
symbols: [" ", ".", "o", "+", "=", "*", "B", "O", "X", "@", "%", "&", "#", "/", "^", "S", "E"],
|
||||
};
|
||||
|
||||
// Converts a buffer to a binary moves array
|
||||
|
@ -120,6 +120,6 @@ export function randomArt(fingerprint: Uint8Array, opts: Partial<Options> = {}):
|
|||
width: options.width,
|
||||
height: options.height,
|
||||
values: vals,
|
||||
symbols: vals.map(line => line.map(val => symbols[val]))
|
||||
symbols: vals.map((line) => line.map((val) => symbols[val])),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ const SJCLProvider = {
|
|||
} catch (e) {
|
||||
throw new Err(ErrorCode.ENCRYPTION_FAILED);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default SJCLProvider;
|
||||
|
|
|
@ -29,12 +29,12 @@ export function appSpec(): Spec {
|
|||
const user = {
|
||||
email: "lengden@olga.com",
|
||||
name: "Lengden Olga",
|
||||
password: "correct battery horse staple"
|
||||
password: "correct battery horse staple",
|
||||
};
|
||||
const otherUser = {
|
||||
email: "max@mustermann.com",
|
||||
name: "Max Mustermann",
|
||||
password: "password"
|
||||
password: "password",
|
||||
};
|
||||
let sharedVaultID = "";
|
||||
// let otherVaultID = "";
|
||||
|
@ -191,7 +191,7 @@ export function appSpec(): Spec {
|
|||
test("Simulataneous Edit", async () => {
|
||||
const [item1, item2] = await Promise.all([
|
||||
app.createItem("Added Item 1", { id: sharedVaultID }),
|
||||
otherApp.createItem("Added Item 2", { id: sharedVaultID })
|
||||
otherApp.createItem("Added Item 2", { id: sharedVaultID }),
|
||||
]);
|
||||
|
||||
await Promise.all([app.syncVault({ id: sharedVaultID }), otherApp.syncVault({ id: sharedVaultID })]);
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
HMACKeyParams,
|
||||
PBKDF2Params,
|
||||
RSASigningParams,
|
||||
RSAEncryptionParams
|
||||
RSAEncryptionParams,
|
||||
} from "../crypto";
|
||||
import { Spec } from "./spec";
|
||||
|
||||
|
@ -26,7 +26,7 @@ const fixtures = {
|
|||
plain: stringToBytes("Hello World!"),
|
||||
encrypted: base64ToBytes(
|
||||
"eAJDfWUdgL4Wl0UDsA0WsmHE29MNAnTvSjus3N0BP6foD0fFZBlrfmRbF-KjY_2zYhgaqn7E4pEKMB20tPDC-JYcAJO8PMWOR6PdLBsBCUTbdYy062iwFWgWfzSFV2LDy-G2t9HL2CbDoDAdsh1fNGIm81nY9sXbB0kKM4uNXKTdVl49Cwf30jiRRpABV_tSPmQjkHDVWOphVEY5ex0hhveRC6vfO1YZ21-CuoTa1gRq-ab21V-Pl5rfQ0RHsDgtvvSJ8_3ihzCkOTjd2Anj0GiKEsCeV0NaEgT-e5WyDj2zYNIsVOoMmB65UUkXX002Ycc2cGuoYw2uudZQSaAlqg"
|
||||
)
|
||||
),
|
||||
},
|
||||
aes: {
|
||||
key: base64ToBytes("fe8Chv8F4je2wW3u67H6KFVtlRuH4VWBgN1FXPoOKAw"),
|
||||
|
@ -34,8 +34,8 @@ const fixtures = {
|
|||
iv: base64ToBytes("Tg9aODkCqoBQDktZAXLEhw"),
|
||||
additionalData: base64ToBytes("dJvkr9MnycfsAHiqZStEOg"),
|
||||
plain: stringToBytes("Hello World!"),
|
||||
encrypted: base64ToBytes("A4ODqQsZrMQ4hXxV-RyYVDhdjTvk1MQ7MG8j_A")
|
||||
}
|
||||
encrypted: base64ToBytes("A4ODqQsZrMQ4hXxV-RyYVDhdjTvk1MQ7MG8j_A"),
|
||||
},
|
||||
};
|
||||
|
||||
export function cryptoProviderSpec(provider: CryptoProvider): Spec {
|
||||
|
@ -59,7 +59,7 @@ export function cryptoProviderSpec(provider: CryptoProvider): Spec {
|
|||
|
||||
let err;
|
||||
try {
|
||||
await provider.hash(input, ({ algorithm: "BLAH" } as any) as HashParams);
|
||||
await provider.hash(input, { algorithm: "BLAH" } as any as HashParams);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
AESEncryptionParams,
|
||||
RSAEncryptionParams,
|
||||
HashParams,
|
||||
RSASigningParams
|
||||
RSASigningParams,
|
||||
} from "./crypto";
|
||||
import { concatBytes as concat, equalBytes as equal } from "./encoding";
|
||||
import { Err, ErrorCode } from "./error";
|
||||
|
@ -50,7 +50,7 @@ export class StubCryptoProvider implements CryptoProvider {
|
|||
const key = await this.randomBytes(32);
|
||||
return {
|
||||
publicKey: key,
|
||||
privateKey: key
|
||||
privateKey: key,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -172,10 +172,10 @@ export class BigInteger {
|
|||
setBit(n: number): BigInteger;
|
||||
|
||||
// (public) this & ~(1<<n)
|
||||
clearBit(n: number): BigInteger
|
||||
clearBit(n: number): BigInteger;
|
||||
|
||||
// (public) this ^ (1<<n)
|
||||
flipBit(n: number): BigInteger
|
||||
flipBit(n: number): BigInteger;
|
||||
|
||||
// (protected) r = this + a
|
||||
addTo(a: BigInteger, r: BigInteger): void;
|
||||
|
|
|
@ -1369,174 +1369,14 @@ function bnModInverse(m) {
|
|||
}
|
||||
|
||||
var lowprimes = [
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
11,
|
||||
13,
|
||||
17,
|
||||
19,
|
||||
23,
|
||||
29,
|
||||
31,
|
||||
37,
|
||||
41,
|
||||
43,
|
||||
47,
|
||||
53,
|
||||
59,
|
||||
61,
|
||||
67,
|
||||
71,
|
||||
73,
|
||||
79,
|
||||
83,
|
||||
89,
|
||||
97,
|
||||
101,
|
||||
103,
|
||||
107,
|
||||
109,
|
||||
113,
|
||||
127,
|
||||
131,
|
||||
137,
|
||||
139,
|
||||
149,
|
||||
151,
|
||||
157,
|
||||
163,
|
||||
167,
|
||||
173,
|
||||
179,
|
||||
181,
|
||||
191,
|
||||
193,
|
||||
197,
|
||||
199,
|
||||
211,
|
||||
223,
|
||||
227,
|
||||
229,
|
||||
233,
|
||||
239,
|
||||
241,
|
||||
251,
|
||||
257,
|
||||
263,
|
||||
269,
|
||||
271,
|
||||
277,
|
||||
281,
|
||||
283,
|
||||
293,
|
||||
307,
|
||||
311,
|
||||
313,
|
||||
317,
|
||||
331,
|
||||
337,
|
||||
347,
|
||||
349,
|
||||
353,
|
||||
359,
|
||||
367,
|
||||
373,
|
||||
379,
|
||||
383,
|
||||
389,
|
||||
397,
|
||||
401,
|
||||
409,
|
||||
419,
|
||||
421,
|
||||
431,
|
||||
433,
|
||||
439,
|
||||
443,
|
||||
449,
|
||||
457,
|
||||
461,
|
||||
463,
|
||||
467,
|
||||
479,
|
||||
487,
|
||||
491,
|
||||
499,
|
||||
503,
|
||||
509,
|
||||
521,
|
||||
523,
|
||||
541,
|
||||
547,
|
||||
557,
|
||||
563,
|
||||
569,
|
||||
571,
|
||||
577,
|
||||
587,
|
||||
593,
|
||||
599,
|
||||
601,
|
||||
607,
|
||||
613,
|
||||
617,
|
||||
619,
|
||||
631,
|
||||
641,
|
||||
643,
|
||||
647,
|
||||
653,
|
||||
659,
|
||||
661,
|
||||
673,
|
||||
677,
|
||||
683,
|
||||
691,
|
||||
701,
|
||||
709,
|
||||
719,
|
||||
727,
|
||||
733,
|
||||
739,
|
||||
743,
|
||||
751,
|
||||
757,
|
||||
761,
|
||||
769,
|
||||
773,
|
||||
787,
|
||||
797,
|
||||
809,
|
||||
811,
|
||||
821,
|
||||
823,
|
||||
827,
|
||||
829,
|
||||
839,
|
||||
853,
|
||||
857,
|
||||
859,
|
||||
863,
|
||||
877,
|
||||
881,
|
||||
883,
|
||||
887,
|
||||
907,
|
||||
911,
|
||||
919,
|
||||
929,
|
||||
937,
|
||||
941,
|
||||
947,
|
||||
953,
|
||||
967,
|
||||
971,
|
||||
977,
|
||||
983,
|
||||
991,
|
||||
997
|
||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109,
|
||||
113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239,
|
||||
241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
|
||||
383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521,
|
||||
523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
|
||||
673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827,
|
||||
829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991,
|
||||
997,
|
||||
];
|
||||
var lplim = (1 << 26) / lowprimes[lowprimes.length - 1];
|
||||
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
export var sjcl: any
|
||||
|
||||
export var sjcl: any;
|
||||
|
|
|
@ -68,8 +68,8 @@ var sjcl = {
|
|||
* Ciphertext is corrupt.
|
||||
* @constructor
|
||||
*/
|
||||
corrupt: function(message) {
|
||||
this.toString = function() {
|
||||
corrupt: function (message) {
|
||||
this.toString = function () {
|
||||
return "CORRUPT: " + this.message;
|
||||
};
|
||||
this.message = message;
|
||||
|
@ -79,8 +79,8 @@ var sjcl = {
|
|||
* Invalid parameter.
|
||||
* @constructor
|
||||
*/
|
||||
invalid: function(message) {
|
||||
this.toString = function() {
|
||||
invalid: function (message) {
|
||||
this.toString = function () {
|
||||
return "INVALID: " + this.message;
|
||||
};
|
||||
this.message = message;
|
||||
|
@ -90,8 +90,8 @@ var sjcl = {
|
|||
* Bug or missing feature in SJCL.
|
||||
* @constructor
|
||||
*/
|
||||
bug: function(message) {
|
||||
this.toString = function() {
|
||||
bug: function (message) {
|
||||
this.toString = function () {
|
||||
return "BUG: " + this.message;
|
||||
};
|
||||
this.message = message;
|
||||
|
@ -101,13 +101,13 @@ var sjcl = {
|
|||
* Something isn't ready.
|
||||
* @constructor
|
||||
*/
|
||||
notReady: function(message) {
|
||||
this.toString = function() {
|
||||
notReady: function (message) {
|
||||
this.toString = function () {
|
||||
return "NOT READY: " + this.message;
|
||||
};
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
/** @fileOverview Low-level AES implementation.
|
||||
*
|
||||
|
@ -133,7 +133,7 @@ var sjcl = {
|
|||
* @constructor
|
||||
* @param {Array} key The key as an array of 4, 6 or 8 words.
|
||||
*/
|
||||
sjcl.cipher.aes = function(key) {
|
||||
sjcl.cipher.aes = function (key) {
|
||||
if (!this._tables[0][0][0]) {
|
||||
this._precompute();
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ sjcl.cipher.aes.prototype = {
|
|||
* @param {Array} data The plaintext.
|
||||
* @return {Array} The ciphertext.
|
||||
*/
|
||||
encrypt: function(data) {
|
||||
encrypt: function (data) {
|
||||
return this._crypt(data, 0);
|
||||
},
|
||||
|
||||
|
@ -213,7 +213,7 @@ sjcl.cipher.aes.prototype = {
|
|||
* @param {Array} data The ciphertext.
|
||||
* @return {Array} The plaintext.
|
||||
*/
|
||||
decrypt: function(data) {
|
||||
decrypt: function (data) {
|
||||
return this._crypt(data, 1);
|
||||
},
|
||||
|
||||
|
@ -229,14 +229,17 @@ sjcl.cipher.aes.prototype = {
|
|||
*
|
||||
* @private
|
||||
*/
|
||||
_tables: [[[], [], [], [], []], [[], [], [], [], []]],
|
||||
_tables: [
|
||||
[[], [], [], [], []],
|
||||
[[], [], [], [], []],
|
||||
],
|
||||
|
||||
/**
|
||||
* Expand the S-box tables.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_precompute: function() {
|
||||
_precompute: function () {
|
||||
var encTable = this._tables[0],
|
||||
decTable = this._tables[1],
|
||||
sbox = encTable[4],
|
||||
|
@ -290,7 +293,7 @@ sjcl.cipher.aes.prototype = {
|
|||
* @return {Array} The four encrypted or decrypted words.
|
||||
* @private
|
||||
*/
|
||||
_crypt: function(input, dir) {
|
||||
_crypt: function (input, dir) {
|
||||
if (input.length !== 4) {
|
||||
throw new sjcl.exception.invalid("invalid aes block size");
|
||||
}
|
||||
|
@ -344,7 +347,7 @@ sjcl.cipher.aes.prototype = {
|
|||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/** @fileOverview Arrays of bits, encoded as arrays of Numbers.
|
||||
|
@ -387,7 +390,7 @@ sjcl.bitArray = {
|
|||
* slice until the end of the array.
|
||||
* @return {bitArray} The requested slice.
|
||||
*/
|
||||
bitSlice: function(a, bstart, bend) {
|
||||
bitSlice: function (a, bstart, bend) {
|
||||
a = sjcl.bitArray._shiftRight(a.slice(bstart / 32), 32 - (bstart & 31)).slice(1);
|
||||
return bend === undefined ? a : sjcl.bitArray.clamp(a, bend - bstart);
|
||||
},
|
||||
|
@ -399,7 +402,7 @@ sjcl.bitArray = {
|
|||
* @param {Number} blength The length of the number to extract.
|
||||
* @return {Number} The requested slice.
|
||||
*/
|
||||
extract: function(a, bstart, blength) {
|
||||
extract: function (a, bstart, blength) {
|
||||
// FIXME: this Math.floor is not necessary at all, but for some reason
|
||||
// seems to suppress a bug in the Chromium JIT.
|
||||
var x,
|
||||
|
@ -420,7 +423,7 @@ sjcl.bitArray = {
|
|||
* @param {bitArray} a2 The second array.
|
||||
* @return {bitArray} The concatenation of a1 and a2.
|
||||
*/
|
||||
concat: function(a1, a2) {
|
||||
concat: function (a1, a2) {
|
||||
if (a1.length === 0 || a2.length === 0) {
|
||||
return a1.concat(a2);
|
||||
}
|
||||
|
@ -439,7 +442,7 @@ sjcl.bitArray = {
|
|||
* @param {bitArray} a The array.
|
||||
* @return {Number} The length of a, in bits.
|
||||
*/
|
||||
bitLength: function(a) {
|
||||
bitLength: function (a) {
|
||||
var l = a.length,
|
||||
x;
|
||||
if (l === 0) {
|
||||
|
@ -455,7 +458,7 @@ sjcl.bitArray = {
|
|||
* @param {Number} len The length to truncate to, in bits.
|
||||
* @return {bitArray} A new array, truncated to len bits.
|
||||
*/
|
||||
clamp: function(a, len) {
|
||||
clamp: function (a, len) {
|
||||
if (a.length * 32 < len) {
|
||||
return a;
|
||||
}
|
||||
|
@ -475,7 +478,7 @@ sjcl.bitArray = {
|
|||
* @param {Number} [_end=0] Pass 1 if x has already been shifted to the high side.
|
||||
* @return {Number} The partial word.
|
||||
*/
|
||||
partial: function(len, x, _end) {
|
||||
partial: function (len, x, _end) {
|
||||
if (len === 32) {
|
||||
return x;
|
||||
}
|
||||
|
@ -487,7 +490,7 @@ sjcl.bitArray = {
|
|||
* @param {Number} x The partial word.
|
||||
* @return {Number} The number of bits used by the partial word.
|
||||
*/
|
||||
getPartial: function(x) {
|
||||
getPartial: function (x) {
|
||||
return Math.round(x / 0x10000000000) || 32;
|
||||
},
|
||||
|
||||
|
@ -497,7 +500,7 @@ sjcl.bitArray = {
|
|||
* @param {bitArray} b The second array.
|
||||
* @return {boolean} true if a == b; false otherwise.
|
||||
*/
|
||||
equal: function(a, b) {
|
||||
equal: function (a, b) {
|
||||
if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -516,7 +519,7 @@ sjcl.bitArray = {
|
|||
* @param {bitArray} [out=[]] An array to prepend to the output.
|
||||
* @private
|
||||
*/
|
||||
_shiftRight: function(a, shift, carry, out) {
|
||||
_shiftRight: function (a, shift, carry, out) {
|
||||
var i,
|
||||
last2 = 0,
|
||||
shift2;
|
||||
|
@ -545,7 +548,7 @@ sjcl.bitArray = {
|
|||
/** xor a block of 4 words together.
|
||||
* @private
|
||||
*/
|
||||
_xor4: function(x, y) {
|
||||
_xor4: function (x, y) {
|
||||
return [x[0] ^ y[0], x[1] ^ y[1], x[2] ^ y[2], x[3] ^ y[3]];
|
||||
},
|
||||
|
||||
|
@ -554,7 +557,7 @@ sjcl.bitArray = {
|
|||
* @param {sjcl.bitArray} a word array
|
||||
* @return {sjcl.bitArray} byteswapped array
|
||||
*/
|
||||
byteswapM: function(a) {
|
||||
byteswapM: function (a) {
|
||||
var i,
|
||||
v,
|
||||
m = 0xff00;
|
||||
|
@ -563,7 +566,7 @@ sjcl.bitArray = {
|
|||
a[i] = (v >>> 24) | ((v >>> 8) & m) | ((v & m) << 8) | (v << 24);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
},
|
||||
};
|
||||
/** @fileOverview Bit array codec implementations.
|
||||
*
|
||||
|
@ -578,7 +581,7 @@ sjcl.bitArray = {
|
|||
*/
|
||||
sjcl.codec.utf8String = {
|
||||
/** Convert from a bitArray to a UTF-8 string. */
|
||||
fromBits: function(arr) {
|
||||
fromBits: function (arr) {
|
||||
var out = "",
|
||||
bl = sjcl.bitArray.bitLength(arr),
|
||||
i,
|
||||
|
@ -594,7 +597,7 @@ sjcl.codec.utf8String = {
|
|||
},
|
||||
|
||||
/** Convert from a UTF-8 string to a bitArray. */
|
||||
toBits: function(str) {
|
||||
toBits: function (str) {
|
||||
str = unescape(encodeURIComponent(str));
|
||||
var out = [],
|
||||
i,
|
||||
|
@ -610,7 +613,7 @@ sjcl.codec.utf8String = {
|
|||
out.push(sjcl.bitArray.partial(8 * (i & 3), tmp));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
},
|
||||
};
|
||||
/** @fileOverview Bit array codec implementations.
|
||||
*
|
||||
|
@ -625,7 +628,7 @@ sjcl.codec.utf8String = {
|
|||
*/
|
||||
sjcl.codec.bytes = {
|
||||
/** Convert from a bitArray to an array of bytes. */
|
||||
fromBits: function(arr) {
|
||||
fromBits: function (arr) {
|
||||
var out = [],
|
||||
bl = sjcl.bitArray.bitLength(arr),
|
||||
i,
|
||||
|
@ -640,7 +643,7 @@ sjcl.codec.bytes = {
|
|||
return out;
|
||||
},
|
||||
/** Convert from an array of bytes to a bitArray. */
|
||||
toBits: function(bytes) {
|
||||
toBits: function (bytes) {
|
||||
var out = [],
|
||||
i,
|
||||
tmp = 0;
|
||||
|
@ -655,7 +658,7 @@ sjcl.codec.bytes = {
|
|||
out.push(sjcl.bitArray.partial(8 * (i & 3), tmp));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
},
|
||||
};
|
||||
/** @fileOverview CCM mode implementation.
|
||||
*
|
||||
|
@ -679,18 +682,18 @@ sjcl.mode.ccm = {
|
|||
|
||||
_progressListeners: [],
|
||||
|
||||
listenProgress: function(cb) {
|
||||
listenProgress: function (cb) {
|
||||
sjcl.mode.ccm._progressListeners.push(cb);
|
||||
},
|
||||
|
||||
unListenProgress: function(cb) {
|
||||
unListenProgress: function (cb) {
|
||||
var index = sjcl.mode.ccm._progressListeners.indexOf(cb);
|
||||
if (index > -1) {
|
||||
sjcl.mode.ccm._progressListeners.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
_callProgressListener: function(val) {
|
||||
_callProgressListener: function (val) {
|
||||
var p = sjcl.mode.ccm._progressListeners.slice(),
|
||||
i;
|
||||
|
||||
|
@ -708,7 +711,7 @@ sjcl.mode.ccm = {
|
|||
* @param {Number} [tlen=64] the desired tag length, in bits.
|
||||
* @return {bitArray} The encrypted data, an array of bytes.
|
||||
*/
|
||||
encrypt: function(prf, plaintext, iv, adata, tlen) {
|
||||
encrypt: function (prf, plaintext, iv, adata, tlen) {
|
||||
var L,
|
||||
out = plaintext.slice(0),
|
||||
tag,
|
||||
|
@ -747,7 +750,7 @@ sjcl.mode.ccm = {
|
|||
* @param {Number} [tlen=64] tlen the desired tag length, in bits.
|
||||
* @return {bitArray} The decrypted data.
|
||||
*/
|
||||
decrypt: function(prf, ciphertext, iv, adata, tlen) {
|
||||
decrypt: function (prf, ciphertext, iv, adata, tlen) {
|
||||
tlen = tlen || 64;
|
||||
adata = adata || [];
|
||||
var L,
|
||||
|
@ -783,7 +786,7 @@ sjcl.mode.ccm = {
|
|||
return out.data;
|
||||
},
|
||||
|
||||
_macAdditionalData: function(prf, adata, iv, tlen, ol, L) {
|
||||
_macAdditionalData: function (prf, adata, iv, tlen, ol, L) {
|
||||
var mac,
|
||||
tmp,
|
||||
i,
|
||||
|
@ -827,7 +830,7 @@ sjcl.mode.ccm = {
|
|||
* @return {bitArray} The tag, but not yet encrypted.
|
||||
* @private
|
||||
*/
|
||||
_computeTag: function(prf, plaintext, iv, adata, tlen, L) {
|
||||
_computeTag: function (prf, plaintext, iv, adata, tlen, L) {
|
||||
// compute B[0]
|
||||
var mac,
|
||||
i,
|
||||
|
@ -868,7 +871,7 @@ sjcl.mode.ccm = {
|
|||
* @return {Object} An object with data and tag, the en/decryption of data and tag values.
|
||||
* @private
|
||||
*/
|
||||
_ctrMode: function(prf, data, iv, tag, tlen, L) {
|
||||
_ctrMode: function (prf, data, iv, tag, tlen, L) {
|
||||
var enc,
|
||||
i,
|
||||
w = sjcl.bitArray,
|
||||
|
@ -906,7 +909,7 @@ sjcl.mode.ccm = {
|
|||
data[i + 3] ^= enc[3];
|
||||
}
|
||||
return { tag: tag, data: w.clamp(data, bl) };
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export { sjcl };
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
{
|
||||
"name": "@padloc/electron",
|
||||
"version": "4.0.0",
|
||||
"description": "Electron Wrapper for Padloc app",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf app && webpack && node ./prepare-build.js && electron-builder --config build/build.json",
|
||||
"start": "webpack && electron app/main.js"
|
||||
},
|
||||
"author": "MaKleSoft UG",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"electron-store": "8.0.0",
|
||||
"electron-updater": "4.3.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.2.6",
|
||||
"electron": "14.1.1",
|
||||
"electron-builder": "22.13.1",
|
||||
"electron-notarize": "1.1.1",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.2",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.5",
|
||||
"webpack": "5.52.1",
|
||||
"webpack-cli": "4.8.0",
|
||||
"typescript": "4.4.3",
|
||||
"raw-loader": "4.0.2",
|
||||
"sharp": "0.29.1"
|
||||
}
|
||||
"name": "@padloc/electron",
|
||||
"version": "4.0.0",
|
||||
"description": "Electron Wrapper for Padloc app",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf app && webpack && node ./prepare-build.js && electron-builder --config build/build.json",
|
||||
"start": "webpack && electron app/main.js"
|
||||
},
|
||||
"author": "MaKleSoft UG",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"electron-store": "8.0.0",
|
||||
"electron-updater": "4.3.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.2.6",
|
||||
"electron": "14.1.1",
|
||||
"electron-builder": "22.13.1",
|
||||
"electron-notarize": "1.1.1",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.2",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.5",
|
||||
"webpack": "5.52.1",
|
||||
"webpack-cli": "4.8.0",
|
||||
"typescript": "4.4.3",
|
||||
"raw-loader": "4.0.2",
|
||||
"sharp": "0.29.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ const { execSync } = require("child_process");
|
|||
const { tmpdir } = require("os");
|
||||
const { writeFileSync, unlinkSync } = require("fs");
|
||||
|
||||
exports.default = async function(opts) {
|
||||
exports.default = async function (opts) {
|
||||
const jsign = path.resolve(__dirname, "jsign-2.1.jar");
|
||||
const pass = process.env.PL_WIN_SIGN_PASS;
|
||||
const lib = path.resolve(__dirname, "crypto3PKCS.dylib");
|
||||
|
@ -18,9 +18,7 @@ slotListIndex=0`
|
|||
);
|
||||
|
||||
execSync(
|
||||
`java -jar ${jsign} --keystore ${keystore} --storepass ${pass} --storetype PKCS11 -t http://time.certum.pl/ -a "${
|
||||
opts.options.publisherName
|
||||
}" "${opts.path}"`
|
||||
`java -jar ${jsign} --keystore ${keystore} --storepass ${pass} --storetype PKCS11 -t http://time.certum.pl/ -a "${opts.options.publisherName}" "${opts.path}"`
|
||||
);
|
||||
|
||||
unlinkSync(keystore);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"extends": "../app/tsconfig.json"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
{
|
||||
"name": "@padloc/extension",
|
||||
"version": "4.0.0",
|
||||
"description": "Padloc Progressive Web App",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"files": [
|
||||
"src",
|
||||
"assets",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/pwa"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"@webcomponents/webcomponentsjs": "2.5.0",
|
||||
"webextension-polyfill-ts": "0.25.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.2.6",
|
||||
"favicons-webpack-plugin": "5.0.2",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"http-server": "0.12.3",
|
||||
"raw-loader": "4.0.2",
|
||||
"sharp": "0.29.1",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3",
|
||||
"webpack": "5.38.1",
|
||||
"webpack-cli": "4.7.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack"
|
||||
}
|
||||
"name": "@padloc/extension",
|
||||
"version": "4.0.0",
|
||||
"description": "Padloc Progressive Web App",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"files": [
|
||||
"src",
|
||||
"assets",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/pwa"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"@webcomponents/webcomponentsjs": "2.5.0",
|
||||
"webextension-polyfill-ts": "0.25.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.2.6",
|
||||
"favicons-webpack-plugin": "5.0.2",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"http-server": "0.12.3",
|
||||
"raw-loader": "4.0.2",
|
||||
"sharp": "0.29.1",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3",
|
||||
"webpack": "5.38.1",
|
||||
"webpack-cli": "4.7.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,19 +183,19 @@ class ExtensionContent {
|
|||
input.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
bubbles: true,
|
||||
key: ""
|
||||
key: "",
|
||||
})
|
||||
);
|
||||
input.dispatchEvent(
|
||||
new KeyboardEvent("keyup", {
|
||||
bubbles: true,
|
||||
key: ""
|
||||
key: "",
|
||||
})
|
||||
);
|
||||
input.dispatchEvent(
|
||||
new KeyboardEvent("keypress", {
|
||||
bubbles: true,
|
||||
key: ""
|
||||
key: "",
|
||||
})
|
||||
);
|
||||
input.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
|
|
|
@ -4,22 +4,14 @@
|
|||
"128": "icon.png"
|
||||
},
|
||||
"background": {
|
||||
"scripts": [
|
||||
"background.js"
|
||||
],
|
||||
"scripts": ["background.js"],
|
||||
"persistent": true
|
||||
},
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html",
|
||||
"default_icon": "icon.png"
|
||||
},
|
||||
"permissions": [
|
||||
"storage",
|
||||
"unlimitedStorage",
|
||||
"tabs",
|
||||
"activeTab",
|
||||
"contextMenus"
|
||||
],
|
||||
"permissions": ["storage", "unlimitedStorage", "tabs", "activeTab", "contextMenus"],
|
||||
"commands": {
|
||||
"_execute_browser_action": {
|
||||
"suggested_key": {
|
||||
|
@ -42,4 +34,4 @@
|
|||
"description": "Open Previous Vault Item"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
{
|
||||
"name": "@padloc/locale",
|
||||
"version": "4.0.0",
|
||||
"description": "Package containing translations and wordlists for Padloc as well as various other localization tools",
|
||||
"main": "src/index.js",
|
||||
"files": [
|
||||
"src",
|
||||
"res"
|
||||
],
|
||||
"scripts": {
|
||||
"extract": "ts-node src/extract.ts ../*/src/{**,.}/*.ts"
|
||||
},
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/locale"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
}
|
||||
"name": "@padloc/locale",
|
||||
"version": "4.0.0",
|
||||
"description": "Package containing translations and wordlists for Padloc as well as various other localization tools",
|
||||
"main": "src/index.js",
|
||||
"files": [
|
||||
"src",
|
||||
"res"
|
||||
],
|
||||
"scripts": {
|
||||
"extract": "ts-node src/extract.ts ../*/src/{**,.}/*.ts"
|
||||
},
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/locale"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -235,5 +235,5 @@ export const countries = [
|
|||
{ code: "EH", name: "Western Sahara" },
|
||||
{ code: "YE", name: "Yemen" },
|
||||
{ code: "ZM", name: "Zambia" },
|
||||
{ code: "ZW", name: "Zimbabwe" }
|
||||
{ code: "ZW", name: "Zimbabwe" },
|
||||
];
|
||||
|
|
|
@ -54,7 +54,7 @@ function extract(files: ts.SourceFile[]) {
|
|||
items.set(original, {
|
||||
original,
|
||||
translation: "",
|
||||
sources: []
|
||||
sources: [],
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ function extract(files: ts.SourceFile[]) {
|
|||
const source: ItemSource = {
|
||||
file: file.fileName,
|
||||
line,
|
||||
character
|
||||
character,
|
||||
};
|
||||
|
||||
const comments =
|
||||
|
@ -106,7 +106,7 @@ export function toYAML({ language, date, commit, items }: Translation) {
|
|||
commit: ${commit}
|
||||
`;
|
||||
|
||||
doc.contents = YAML.createNode(items.flatMap(item => [item.original, item.translation])) as any;
|
||||
doc.contents = YAML.createNode(items.flatMap((item) => [item.original, item.translation])) as any;
|
||||
|
||||
for (const [i, item] of items.entries()) {
|
||||
const node = (doc.contents as any).items[i * 2];
|
||||
|
@ -131,7 +131,7 @@ export function fromYAML(str: string, language: string): Translation {
|
|||
language,
|
||||
date: new Date(),
|
||||
commit: "",
|
||||
items
|
||||
items,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -156,37 +156,35 @@ export function fromJSON(str: string, language: string) {
|
|||
const items = JSON.parse(str).map(([original, translation]: [string, string]) => ({
|
||||
original,
|
||||
translation,
|
||||
sources: []
|
||||
sources: [],
|
||||
}));
|
||||
return {
|
||||
language,
|
||||
date: new Date(),
|
||||
commit: "",
|
||||
items
|
||||
items,
|
||||
};
|
||||
}
|
||||
|
||||
export function fromSource(fileNames: string[], language: string): Translation {
|
||||
const files = fileNames.map(path =>
|
||||
const files = fileNames.map((path) =>
|
||||
ts.createSourceFile(path, readFileSync(resolve(path), "utf8"), ts.ScriptTarget.ES2017, false)
|
||||
);
|
||||
|
||||
const commit = execSync("git rev-parse HEAD")
|
||||
.toString()
|
||||
.trim();
|
||||
const commit = execSync("git rev-parse HEAD").toString().trim();
|
||||
const items = extract(files);
|
||||
|
||||
return {
|
||||
language,
|
||||
commit,
|
||||
date: new Date(),
|
||||
items
|
||||
items,
|
||||
};
|
||||
}
|
||||
|
||||
export function merge(curr: Translation, prev: Translation) {
|
||||
for (const item of curr.items) {
|
||||
const prevItemIndex = prev.items.findIndex(i => i.original === item.original);
|
||||
const prevItemIndex = prev.items.findIndex((i) => i.original === item.original);
|
||||
if (prevItemIndex !== -1) {
|
||||
item.translation = prev.items[prevItemIndex].translation;
|
||||
prev.items.splice(prevItemIndex, 1);
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"lib": [
|
||||
"esnext"
|
||||
],
|
||||
"lib": ["esnext"],
|
||||
"module": "commonjs",
|
||||
"declaration": false,
|
||||
"baseUrl": "."
|
||||
|
|
|
@ -1,51 +1,51 @@
|
|||
{
|
||||
"name": "@padloc/pwa",
|
||||
"version": "4.0.0",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"files": [
|
||||
"src",
|
||||
"assets",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/pwa"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.2.6",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"http-server": "0.12.3",
|
||||
"raw-loader": "4.0.2",
|
||||
"sharp": "0.29.3",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3",
|
||||
"webpack": "5.52.0",
|
||||
"webpack-cli": "4.8.0",
|
||||
"webpack-dev-server": "4.2.1",
|
||||
"webpack-pwa-manifest": "4.3.0",
|
||||
"workbox-cli": "6.2.4",
|
||||
"workbox-webpack-plugin": "6.4.2"
|
||||
},
|
||||
"description": "Padloc Progressive Web App",
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"dev": "webpack serve",
|
||||
"start": "http-server ${PL_PWA_DIR:-dist} -s -p ${PL_PWA_PORT:-8080} --proxy ${PL_PWA_URL:-http://0.0.0.0:${PL_PWA_PORT:-8080}}?",
|
||||
"build_and_start": "npm run build && npm start"
|
||||
}
|
||||
"name": "@padloc/pwa",
|
||||
"version": "4.0.0",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"files": [
|
||||
"src",
|
||||
"assets",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/pwa"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.2.6",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"http-server": "0.12.3",
|
||||
"raw-loader": "4.0.2",
|
||||
"sharp": "0.29.3",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3",
|
||||
"webpack": "5.52.0",
|
||||
"webpack-cli": "4.8.0",
|
||||
"webpack-dev-server": "4.2.1",
|
||||
"webpack-pwa-manifest": "4.3.0",
|
||||
"workbox-cli": "6.2.4",
|
||||
"workbox-webpack-plugin": "6.4.2"
|
||||
},
|
||||
"description": "Padloc Progressive Web App",
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"dev": "webpack serve",
|
||||
"start": "http-server ${PL_PWA_DIR:-dist} -s -p ${PL_PWA_PORT:-8080} --proxy ${PL_PWA_URL:-http://0.0.0.0:${PL_PWA_PORT:-8080}}?",
|
||||
"build_and_start": "npm run build && npm start"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
{
|
||||
"name": "@padloc/server",
|
||||
"version": "3.1.3",
|
||||
"description": "Padloc server component",
|
||||
"private": true,
|
||||
"files": [
|
||||
"src",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"main": "index.js",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"@types/chai": "4.2.18",
|
||||
"@types/mocha": "8.2.2",
|
||||
"chai": "4.3.4",
|
||||
"mocha": "8.4.0",
|
||||
"ts-node-dev": "1.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/core": "4.0.0",
|
||||
"@padloc/locale": "4.0.0",
|
||||
"@aws-sdk/client-s3": "3.25.0",
|
||||
"@aws-sdk/types": "3.25.0",
|
||||
"@simplewebauthn/server": "4.0.0",
|
||||
"@types/fs-extra": "9.0.11",
|
||||
"@types/mixpanel": "2.14.3",
|
||||
"@types/node": "15.6.1",
|
||||
"@types/nodemailer": "6.4.2",
|
||||
"@types/pg": "8.6.1",
|
||||
"@types/stripe": "8.0.416",
|
||||
"ansi-colors": "4.1.1",
|
||||
"date-fns": "2.22.1",
|
||||
"fs-extra": "10.0.0",
|
||||
"geolite2-redist": "2.0.4",
|
||||
"level": "7.0.0",
|
||||
"maxmind": "4.3.2",
|
||||
"mixpanel": "0.13.0",
|
||||
"mongodb": "4.1.0",
|
||||
"nodemailer": "6.6.1",
|
||||
"pg": "8.7.1",
|
||||
"stripe": "8.194.0",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "ts-node src/init.ts",
|
||||
"start-dry": "ts-node src/init.ts --dryrun",
|
||||
"repl": "ts-node src/init-repl-client.ts",
|
||||
"dev": "ts-node-dev src/init.ts",
|
||||
"dev-inspect": "node -r ts-node/register --inspect-brk --stack-trace-limit=1000 src/init.ts",
|
||||
"test": "cd test && mocha -r ts-node/register *.ts --timeout 5000"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/server"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
}
|
||||
"name": "@padloc/server",
|
||||
"version": "3.1.3",
|
||||
"description": "Padloc server component",
|
||||
"private": true,
|
||||
"files": [
|
||||
"src",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"main": "index.js",
|
||||
"author": "Martin Kleinschrodt <martin@maklesoft.com>",
|
||||
"license": "GPLv3",
|
||||
"devDependencies": {
|
||||
"@types/chai": "4.2.18",
|
||||
"@types/mocha": "8.2.2",
|
||||
"chai": "4.3.4",
|
||||
"mocha": "8.4.0",
|
||||
"ts-node-dev": "1.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/core": "4.0.0",
|
||||
"@padloc/locale": "4.0.0",
|
||||
"@aws-sdk/client-s3": "3.25.0",
|
||||
"@aws-sdk/types": "3.25.0",
|
||||
"@simplewebauthn/server": "4.0.0",
|
||||
"@types/fs-extra": "9.0.11",
|
||||
"@types/mixpanel": "2.14.3",
|
||||
"@types/node": "15.6.1",
|
||||
"@types/nodemailer": "6.4.2",
|
||||
"@types/pg": "8.6.1",
|
||||
"@types/stripe": "8.0.416",
|
||||
"ansi-colors": "4.1.1",
|
||||
"date-fns": "2.22.1",
|
||||
"fs-extra": "10.0.0",
|
||||
"geolite2-redist": "2.0.4",
|
||||
"level": "7.0.0",
|
||||
"maxmind": "4.3.2",
|
||||
"mixpanel": "0.13.0",
|
||||
"mongodb": "4.1.0",
|
||||
"nodemailer": "6.6.1",
|
||||
"pg": "8.7.1",
|
||||
"stripe": "8.194.0",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "ts-node src/init.ts",
|
||||
"start-dry": "ts-node src/init.ts --dryrun",
|
||||
"repl": "ts-node src/init-repl-client.ts",
|
||||
"dev": "ts-node-dev src/init.ts",
|
||||
"dev-inspect": "node -r ts-node/register --inspect-brk --stack-trace-limit=1000 src/init.ts",
|
||||
"test": "cd test && mocha -r ts-node/register *.ts --timeout 5000"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/padloc/padloc.git",
|
||||
"directory": "packages/server"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
createCipheriv,
|
||||
createDecipheriv,
|
||||
publicEncrypt,
|
||||
privateDecrypt
|
||||
privateDecrypt,
|
||||
} from "crypto";
|
||||
import {
|
||||
CryptoProvider,
|
||||
|
@ -29,7 +29,7 @@ import {
|
|||
RSAEncryptionParams,
|
||||
HashParams,
|
||||
RSASigningParams,
|
||||
PBKDF2Params
|
||||
PBKDF2Params,
|
||||
} from "@padloc/core/src/crypto";
|
||||
import { Err, ErrorCode } from "@padloc/core/src/error";
|
||||
import { equalCT } from "@padloc/core/src/encoding";
|
||||
|
@ -80,12 +80,12 @@ export class NodeCryptoProvider implements CryptoProvider {
|
|||
),
|
||||
publicKeyEncoding: {
|
||||
type: "spki",
|
||||
format: "der"
|
||||
format: "der",
|
||||
},
|
||||
privateKeyEncoding: {
|
||||
type: "pkcs8",
|
||||
format: "der"
|
||||
}
|
||||
format: "der",
|
||||
},
|
||||
} as any,
|
||||
(err, publicKey: Buffer, privateKey: Buffer) => {
|
||||
if (err) {
|
||||
|
@ -93,7 +93,7 @@ export class NodeCryptoProvider implements CryptoProvider {
|
|||
} else {
|
||||
resolve({
|
||||
privateKey: new Uint8Array(privateKey),
|
||||
publicKey: new Uint8Array(publicKey)
|
||||
publicKey: new Uint8Array(publicKey),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ export class NodeCryptoProvider implements CryptoProvider {
|
|||
const [alg, mode] = params.algorithm.toLowerCase().split("-");
|
||||
const authTagLength = params.tagSize / 8;
|
||||
const cipher = createCipheriv(`${alg}-${params.keySize}-${mode}` as "aes-256-gcm", key, params.iv, {
|
||||
authTagLength
|
||||
authTagLength,
|
||||
} as any);
|
||||
cipher.setAAD(params.additionalData as Buffer);
|
||||
try {
|
||||
|
@ -223,7 +223,7 @@ export class NodeCryptoProvider implements CryptoProvider {
|
|||
const tag = data.slice(tagPos);
|
||||
|
||||
const cipher = createDecipheriv(`${alg}-${params.keySize}-${mode}` as "aes-256-gcm", key, params.iv, {
|
||||
authTagLength
|
||||
authTagLength,
|
||||
} as any);
|
||||
cipher.setAAD(params.additionalData as Buffer);
|
||||
cipher.setAuthTag(tag);
|
||||
|
@ -242,7 +242,7 @@ export class NodeCryptoProvider implements CryptoProvider {
|
|||
key: Buffer.from(publicKey),
|
||||
format: "der",
|
||||
type: "spki",
|
||||
oaepHash: hashToNode(params.hash)
|
||||
oaepHash: hashToNode(params.hash),
|
||||
} as any,
|
||||
key
|
||||
);
|
||||
|
@ -259,7 +259,7 @@ export class NodeCryptoProvider implements CryptoProvider {
|
|||
key: Buffer.from(privateKey),
|
||||
format: "der",
|
||||
type: "pkcs8",
|
||||
oaepHash: hashToNode(params.hash)
|
||||
oaepHash: hashToNode(params.hash),
|
||||
} as any,
|
||||
key
|
||||
);
|
||||
|
@ -293,7 +293,7 @@ export class NodeCryptoProvider implements CryptoProvider {
|
|||
format: "der",
|
||||
dsaEncoding: "der",
|
||||
saltLength: params.saltLength,
|
||||
padding: constants.RSA_PKCS1_PSS_PADDING
|
||||
padding: constants.RSA_PKCS1_PSS_PADDING,
|
||||
});
|
||||
|
||||
return new Uint8Array(sig);
|
||||
|
@ -309,7 +309,7 @@ export class NodeCryptoProvider implements CryptoProvider {
|
|||
format: "der",
|
||||
dsaEncoding: "der",
|
||||
saltLength: params.saltLength,
|
||||
padding: constants.RSA_PKCS1_PSS_PADDING
|
||||
padding: constants.RSA_PKCS1_PSS_PADDING,
|
||||
},
|
||||
signature
|
||||
);
|
||||
|
|
|
@ -21,10 +21,10 @@ export class NodeLegacyServer implements LegacyServer {
|
|||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `SkeletonKey ${email}:${this.config.key}`,
|
||||
Accept: "application/vnd.padlock;version=1"
|
||||
}
|
||||
Accept: "application/vnd.padlock;version=1",
|
||||
},
|
||||
},
|
||||
res => {
|
||||
(res) => {
|
||||
if (res.statusCode !== 200) {
|
||||
resolve(null);
|
||||
return;
|
||||
|
@ -33,7 +33,7 @@ export class NodeLegacyServer implements LegacyServer {
|
|||
let data = "";
|
||||
|
||||
res.setEncoding("utf8");
|
||||
res.on("data", chunk => (data += chunk));
|
||||
res.on("data", (chunk) => (data += chunk));
|
||||
res.on("end", () => {
|
||||
if (!data) {
|
||||
resolve(null);
|
||||
|
@ -65,10 +65,10 @@ export class NodeLegacyServer implements LegacyServer {
|
|||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `SkeletonKey ${email}:${this.config.key}`,
|
||||
Accept: "application/vnd.padlock;version=1"
|
||||
}
|
||||
Accept: "application/vnd.padlock;version=1",
|
||||
},
|
||||
},
|
||||
res => {
|
||||
(res) => {
|
||||
if (res.statusCode !== 200) {
|
||||
reject("Received status code " + res.statusCode);
|
||||
return;
|
||||
|
|
|
@ -34,7 +34,8 @@ export class DefaultAccountProvisioning
|
|||
Pick<
|
||||
AccountProvisioning,
|
||||
"status" | "statusLabel" | "statusMessage" | "actionUrl" | "actionLabel" | "quota" | "disableFeatures"
|
||||
> {
|
||||
>
|
||||
{
|
||||
@ConfigParam()
|
||||
status: ProvisioningStatus = ProvisioningStatus.Active;
|
||||
|
||||
|
@ -400,16 +401,8 @@ export class SimpleProvisioner implements Provisioner {
|
|||
}
|
||||
}
|
||||
|
||||
const {
|
||||
accountId,
|
||||
status,
|
||||
statusLabel,
|
||||
statusMessage,
|
||||
actionUrl,
|
||||
actionLabel,
|
||||
scheduledUpdates,
|
||||
metaData,
|
||||
} = entry.toRaw();
|
||||
const { accountId, status, statusLabel, statusMessage, actionUrl, actionLabel, scheduledUpdates, metaData } =
|
||||
entry.toRaw();
|
||||
|
||||
httpRes.statusCode = 200;
|
||||
httpRes.end(
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
{
|
||||
"name": "@padloc/tauri",
|
||||
"version": "4.0.0",
|
||||
"description": "Tauri Wrapper for packaging native apps",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"tauri": "tauri",
|
||||
"build": "tauri build",
|
||||
"dev": "tauri dev"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.2.6",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.3.2",
|
||||
"webpack": "5.38.1",
|
||||
"webpack-cli": "4.7.0",
|
||||
"webpack-dev-server": "3.11.2",
|
||||
"@tauri-apps/cli": "1.0.0-beta.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"@tauri-apps/api": "1.0.0-beta.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
}
|
||||
"name": "@padloc/tauri",
|
||||
"version": "4.0.0",
|
||||
"description": "Tauri Wrapper for packaging native apps",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"tauri": "tauri",
|
||||
"build": "tauri build",
|
||||
"dev": "tauri dev"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.2.6",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"style-loader": "2.0.0",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.3.2",
|
||||
"webpack": "5.38.1",
|
||||
"webpack-cli": "4.7.0",
|
||||
"webpack-dev-server": "3.11.2",
|
||||
"@tauri-apps/cli": "1.0.0-beta.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"@tauri-apps/api": "1.0.0-beta.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.13.1",
|
||||
"npm": "8.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,65 +1,61 @@
|
|||
{
|
||||
"package": {
|
||||
"productName": "Padloc",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
"devPath": "http://localhost:8080",
|
||||
"beforeDevCommand": "webpack serve",
|
||||
"beforeBuildCommand": "webpack"
|
||||
},
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"identifier": "app.padloc",
|
||||
"icon": [
|
||||
"icons/icon.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"resources": [],
|
||||
"externalBin": [],
|
||||
"copyright": "",
|
||||
"category": "DeveloperTool",
|
||||
"shortDescription": "",
|
||||
"longDescription": "",
|
||||
"deb": {
|
||||
"depends": [],
|
||||
"useBootstrapper": false
|
||||
},
|
||||
"macOS": {
|
||||
"frameworks": [],
|
||||
"minimumSystemVersion": "",
|
||||
"useBootstrapper": false,
|
||||
"exceptionDomain": "",
|
||||
"signingIdentity": null,
|
||||
"entitlements": null
|
||||
},
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
}
|
||||
"package": {
|
||||
"productName": "Padloc",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"updater": {
|
||||
"active": false
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
"devPath": "http://localhost:8080",
|
||||
"beforeDevCommand": "webpack serve",
|
||||
"beforeBuildCommand": "webpack"
|
||||
},
|
||||
"allowlist": {
|
||||
"all": true
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"title": "Padloc",
|
||||
"width": 1024,
|
||||
"height": 768,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": "default-src blob: data: filesystem: ws: http: https: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'"
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"identifier": "app.padloc",
|
||||
"icon": ["icons/icon.png", "icons/icon.icns", "icons/icon.ico"],
|
||||
"resources": [],
|
||||
"externalBin": [],
|
||||
"copyright": "",
|
||||
"category": "DeveloperTool",
|
||||
"shortDescription": "",
|
||||
"longDescription": "",
|
||||
"deb": {
|
||||
"depends": [],
|
||||
"useBootstrapper": false
|
||||
},
|
||||
"macOS": {
|
||||
"frameworks": [],
|
||||
"minimumSystemVersion": "",
|
||||
"useBootstrapper": false,
|
||||
"exceptionDomain": "",
|
||||
"signingIdentity": null,
|
||||
"entitlements": null
|
||||
},
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
}
|
||||
},
|
||||
"updater": {
|
||||
"active": false
|
||||
},
|
||||
"allowlist": {
|
||||
"all": true
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"title": "Padloc",
|
||||
"width": 1024,
|
||||
"height": 768,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": "default-src blob: data: filesystem: ws: http: https: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
rotate linear 1.2s infinite;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<svg viewBox="0 0 100 100" class="spinner">
|
||||
|
|
|
@ -14,7 +14,6 @@ function createApp() {
|
|||
|
||||
await import("@padloc/app/src/elements/app");
|
||||
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", createApp);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue