Merge branch 'main' into feature/email-notifications-failed-login
This commit is contained in:
commit
052477b6c9
|
@ -1,6 +1,6 @@
|
|||
# Padloc
|
||||
|
||||
[![](https://github.com/padloc/padloc/workflows/Run%20Tests/badge.svg?branch=v4)](https://github.com/padloc/padloc/actions?workflow=Run+Tests)
|
||||
[![](https://github.com/padloc/padloc/workflows/Run%20Tests/badge.svg?branch=main)](https://github.com/padloc/padloc/actions?workflow=Run+Tests)
|
||||
|
||||
Simple, secure password and data management for individuals and teams.
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<p>The following error occurred at {{ time }}:</p>
|
||||
|
||||
<p>
|
||||
Code: {{ code }} <br />
|
||||
Message: {{ message }} <br />
|
||||
Event ID: {{ eventId }}`
|
||||
</p>
|
|
@ -1,5 +0,0 @@
|
|||
The following error occurred at {{ time }}:
|
||||
|
||||
Code: {{ code }}
|
||||
Message: {{ message }}
|
||||
Event ID: {{ eventId }}`
|
|
@ -0,0 +1,3 @@
|
|||
<pre>
|
||||
{{ message }}
|
||||
</pre>
|
|
@ -0,0 +1 @@
|
|||
{{ message }}
|
|
@ -1,39 +1,54 @@
|
|||
<a href="#">
|
||||
<button class="fill-horizontally">
|
||||
<div class="horizontal spacing layout">
|
||||
<i class="fa-user block"></i>
|
||||
<div class="stretch">FAQs</div>
|
||||
<ul class="plain box">
|
||||
<li class="list-item">
|
||||
<a href="https://padloc.app/" target="_blank" class="plain double-padded horizontal spacing center-aligning layout">
|
||||
<i class="fa-globe block"></i>
|
||||
<div class="stretch">Website</div>
|
||||
<i class="subtle block fa-external-link"></i>
|
||||
</div>
|
||||
</button>
|
||||
</a>
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-item">
|
||||
<a href="https://padloc.app/blog/" target="_blank" class="plain double-padded horizontal spacing center-aligning layout">
|
||||
<i class="fa-megaphone block"></i>
|
||||
<div class="stretch">Blog</div>
|
||||
<i class="subtle block fa-external-link"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-item">
|
||||
<a href="https://padloc.app/tos/" target="_blank" class="plain double-padded horizontal spacing center-aligning layout">
|
||||
<i class="fa-file-lines block"></i>
|
||||
<div class="stretch">Terms of Service</div>
|
||||
<i class="subtle block fa-external-link"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-item">
|
||||
<a href="https://docs.padloc.app/privacy/" target="_blank" class="plain double-padded horizontal spacing center-aligning layout">
|
||||
<i class="fa-blinds block"></i>
|
||||
<div class="stretch">Privacy Policy</div>
|
||||
<i class="subtle block fa-external-link"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<a href="#">
|
||||
<button class="fill-horizontally">
|
||||
<div class="horizontal spacing layout">
|
||||
<i class="fa-lock lock block"></i>
|
||||
<div class="stretch">Support Ticket</div>
|
||||
<ul class="plain box">
|
||||
<li class="list-item">
|
||||
<a href="mailto:support@padloc.app" target="_blank" class="plain double-padded horizontal spacing center-aligning layout">
|
||||
<i class="fa-envelope block"></i>
|
||||
<div class="stretch">Contact Support</div>
|
||||
<i class="subtle block fa-external-link"></i>
|
||||
</div>
|
||||
</button>
|
||||
</a>
|
||||
|
||||
<a href="#">
|
||||
<button class="fill-horizontally">
|
||||
<div class="horizontal spacing layout">
|
||||
<i class="fa-comments-alt block"></i>
|
||||
<div class="stretch">Live Chat</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-item">
|
||||
<a href="https://docs.padloc.app/manual/" target="_blank" class="plain double-padded horizontal spacing center-aligning layout">
|
||||
<i class="fa-book block"></i>
|
||||
<div class="stretch">User Manual</div>
|
||||
<i class="subtle block fa-external-link"></i>
|
||||
</div>
|
||||
</button>
|
||||
</a>
|
||||
|
||||
<a href="#">
|
||||
<button class="fill-horizontally">
|
||||
<div class="horizontal spacing layout">
|
||||
<i class="fa-tools block"></i>
|
||||
<div class="stretch">Support Center</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="list-item">
|
||||
<a href="https://docs.padloc.app/questions/" target="_blank" class="plain double-padded horizontal spacing center-aligning layout">
|
||||
<i class="fa-comments-question block"></i>
|
||||
<div class="stretch">Frequently Asked Questions</div>
|
||||
<i class="subtle block fa-external-link"></i>
|
||||
</div>
|
||||
</button>
|
||||
</a>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -184,6 +184,22 @@
|
|||
# PL_LOGGING_MONGODB_MAX_SIZE=""
|
||||
# PL_LOGGING_MONGODB_MAX_DOCUMENTS=""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# POSTGRES
|
||||
#
|
||||
# Use postgresql as log storage: https://www.npmjs.com/package/pg
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# PL_LOGGING_BACKEND=postgres
|
||||
# PL_LOGGING_POSTGRES_HOST=localhost
|
||||
# PL_LOGGING_POSTGRES_PORT=5432
|
||||
# PL_LOGGING_POSTGRES_DATABASE=padloc
|
||||
# PL_LOGGING_POSTGRES_USER=padloc
|
||||
# PL_LOGGING_POSTGRES_PASSWORD=""
|
||||
# PL_LOGGING_POSTGRES_TLS=false
|
||||
# PL_LOGGING_POSTGRES_TLS_CAFILE=""
|
||||
# PL_LOGGING_POSTGRES_TLS_REJECT_UNAUTHORIZED=true
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# MIXPANEL
|
||||
#
|
||||
|
|
|
@ -3,6 +3,7 @@ import { html, css, TemplateResult } from "lit";
|
|||
import { customElement, property } from "lit/decorators.js";
|
||||
import { Dialog } from "./dialog";
|
||||
import "./button";
|
||||
import "./icon";
|
||||
|
||||
const defaultButtonLabel = $l("OK");
|
||||
|
||||
|
@ -20,6 +21,7 @@ export interface AlertOptions {
|
|||
maxWidth?: string;
|
||||
width?: string;
|
||||
hideOnDocumentVisibilityChange?: boolean;
|
||||
zIndex?: number;
|
||||
}
|
||||
|
||||
@customElement("pl-alert-dialog")
|
||||
|
@ -119,6 +121,7 @@ export class AlertDialog extends Dialog<AlertOptions, number> {
|
|||
maxWidth,
|
||||
width,
|
||||
hideOnDocumentVisibilityChange = false,
|
||||
zIndex = 10,
|
||||
}: AlertOptions = {}): Promise<number> {
|
||||
this.message = message;
|
||||
this.dialogTitle = title;
|
||||
|
@ -137,6 +140,7 @@ export class AlertDialog extends Dialog<AlertOptions, number> {
|
|||
|
||||
await this.updateComplete;
|
||||
|
||||
this.style.zIndex = zIndex.toString();
|
||||
this._inner.style.setProperty("--pl-dialog-max-width", maxWidth || "inherit");
|
||||
this._inner.style.setProperty("--pl-dialog-width", width || "inherit");
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ export class WebPlatform extends StubPlatform implements Platform {
|
|||
browser.name && browser.name !== "Electron"
|
||||
? $l("{0} on {1}", browser.name, platform)
|
||||
: $l("{0} Device", platform),
|
||||
runtime: "web",
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ async function alertMessage(message: string | RichContent, action?: { label: str
|
|||
type: !action ? "choice" : "info",
|
||||
title,
|
||||
hideOnDocumentVisibilityChange: true,
|
||||
zIndex: 20,
|
||||
}
|
||||
);
|
||||
if (action && choice === 0) {
|
||||
|
|
|
@ -65,7 +65,8 @@ export const content = css`
|
|||
list-style: square;
|
||||
}
|
||||
|
||||
ul.plain {
|
||||
ul.plain,
|
||||
ul.unstyled {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -96,10 +97,8 @@ export const content = css`
|
|||
color: var(--button-primary-color, var(--button-color));
|
||||
}
|
||||
|
||||
${click("button")};
|
||||
${hover("button")};
|
||||
|
||||
a.plain {
|
||||
a.plain,
|
||||
a.unstyled {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
|
@ -128,4 +127,7 @@ export const content = css`
|
|||
margin-bottom: 0.5em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
${click("button")};
|
||||
${hover("button")};
|
||||
`;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
"name": "@padloc/cordova",
|
||||
"version": "4.0.0",
|
||||
"dependencies": {
|
||||
"cordova-android": "10.1.0",
|
||||
"cordova-clipboard": "1.3.0",
|
||||
"cordova-ios": "6.2.0",
|
||||
"cordova-plugin-add-swift-support": "2.0.2",
|
||||
|
@ -32,6 +31,7 @@
|
|||
"@types/cordova-plugin-qrscanner": "1.0.31",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"cordova": "11.0.0",
|
||||
"cordova-android": "^10.1.2",
|
||||
"css-loader": "5.2.6",
|
||||
"dotenv": "10.0.0",
|
||||
"file-loader": "6.2.0",
|
||||
|
@ -756,6 +756,7 @@
|
|||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/android-versions/-/android-versions-1.7.0.tgz",
|
||||
"integrity": "sha512-TCy4b8Dk8YS6A23ZPfhSKqK66JHFq0D8avGYiwvYpjno6HrrcI0DRgHx9+jtkvWYmrsE2vQWgbHJhvGGhhOb0g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"semver": "^5.7.1"
|
||||
}
|
||||
|
@ -764,6 +765,7 @@
|
|||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
|
@ -1852,9 +1854,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/cordova-android": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-10.1.0.tgz",
|
||||
"integrity": "sha512-nkVh8VMDWoDmvWaQav/sF3Q7N9ZpRRNBJduDhjCOMwYUF/6q2526i/Jb/wJLdXmetBNh+THkGolcTBi9i+1UzA==",
|
||||
"version": "10.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-10.1.2.tgz",
|
||||
"integrity": "sha512-F28+NvgKO4ZhKFkqctCOh62mhVoNyUuRQh/F/nqp+Sti4ODv2rUa6UeW18khhdYTjlDeihHQsPqxvB7mI6fVYA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"android-versions": "^1.7.0",
|
||||
"cordova-common": "^4.0.2",
|
||||
|
@ -1873,9 +1876,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/cordova-android/node_modules/fs-extra": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
|
@ -2963,6 +2967,7 @@
|
|||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||
"integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.3",
|
||||
"get-stream": "^6.0.0",
|
||||
|
@ -3360,6 +3365,7 @@
|
|||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
|
||||
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
|
@ -3757,6 +3763,7 @@
|
|||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10.17.0"
|
||||
}
|
||||
|
@ -4312,6 +4319,7 @@
|
|||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
@ -4341,6 +4349,7 @@
|
|||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
|
@ -4752,7 +4761,8 @@
|
|||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
|
@ -4820,6 +4830,7 @@
|
|||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
@ -5225,6 +5236,7 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"path-key": "^3.0.0"
|
||||
},
|
||||
|
@ -5321,6 +5333,7 @@
|
|||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
},
|
||||
|
@ -5908,7 +5921,8 @@
|
|||
"node_modules/properties-parser": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/properties-parser/-/properties-parser-0.3.1.tgz",
|
||||
"integrity": "sha1-ExbpU5/7/ZOEXjabIRAiq9R4dxo=",
|
||||
"integrity": "sha512-AkSQxQAviJ89x4FIxOyHGfO3uund0gvYo7lfD0E+Gp7gFQKrTNgtoYQklu8EhrfHVZUzTwKGZx2r/KDSfnljcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"string.prototype.codepointat": "^0.2.0"
|
||||
},
|
||||
|
@ -6713,7 +6727,8 @@
|
|||
"node_modules/signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/simctl": {
|
||||
"version": "2.0.3",
|
||||
|
@ -7041,7 +7056,8 @@
|
|||
"node_modules/string.prototype.codepointat": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
|
||||
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
|
||||
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/stringify-package": {
|
||||
"version": "1.0.1",
|
||||
|
@ -7073,6 +7089,7 @@
|
|||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
|
||||
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
@ -7594,6 +7611,7 @@
|
|||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
|
||||
"integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
@ -8849,6 +8867,7 @@
|
|||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/android-versions/-/android-versions-1.7.0.tgz",
|
||||
"integrity": "sha512-TCy4b8Dk8YS6A23ZPfhSKqK66JHFq0D8avGYiwvYpjno6HrrcI0DRgHx9+jtkvWYmrsE2vQWgbHJhvGGhhOb0g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^5.7.1"
|
||||
},
|
||||
|
@ -8856,7 +8875,8 @@
|
|||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9697,9 +9717,10 @@
|
|||
}
|
||||
},
|
||||
"cordova-android": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-10.1.0.tgz",
|
||||
"integrity": "sha512-nkVh8VMDWoDmvWaQav/sF3Q7N9ZpRRNBJduDhjCOMwYUF/6q2526i/Jb/wJLdXmetBNh+THkGolcTBi9i+1UzA==",
|
||||
"version": "10.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-10.1.2.tgz",
|
||||
"integrity": "sha512-F28+NvgKO4ZhKFkqctCOh62mhVoNyUuRQh/F/nqp+Sti4ODv2rUa6UeW18khhdYTjlDeihHQsPqxvB7mI6fVYA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"android-versions": "^1.7.0",
|
||||
"cordova-common": "^4.0.2",
|
||||
|
@ -9715,9 +9736,10 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"fs-extra": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
|
@ -10525,6 +10547,7 @@
|
|||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||
"integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.3",
|
||||
"get-stream": "^6.0.0",
|
||||
|
@ -10837,7 +10860,8 @@
|
|||
"get-stream": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
|
||||
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
|
||||
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
|
||||
"dev": true
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
|
@ -11132,7 +11156,8 @@
|
|||
"human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
|
||||
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
|
||||
"dev": true
|
||||
},
|
||||
"humanize-ms": {
|
||||
"version": "1.2.1",
|
||||
|
@ -11541,7 +11566,8 @@
|
|||
"is-path-inside": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "2.0.4",
|
||||
|
@ -11563,7 +11589,8 @@
|
|||
"is-stream": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
|
||||
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
|
@ -11892,7 +11919,8 @@
|
|||
"merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true
|
||||
},
|
||||
"merge2": {
|
||||
"version": "1.4.1",
|
||||
|
@ -11938,7 +11966,8 @@
|
|||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"dev": true
|
||||
},
|
||||
"mimic-response": {
|
||||
"version": "1.0.1",
|
||||
|
@ -12254,6 +12283,7 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
|
||||
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.0.0"
|
||||
}
|
||||
|
@ -12329,6 +12359,7 @@
|
|||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
}
|
||||
|
@ -12760,7 +12791,8 @@
|
|||
"properties-parser": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/properties-parser/-/properties-parser-0.3.1.tgz",
|
||||
"integrity": "sha1-ExbpU5/7/ZOEXjabIRAiq9R4dxo=",
|
||||
"integrity": "sha512-AkSQxQAviJ89x4FIxOyHGfO3uund0gvYo7lfD0E+Gp7gFQKrTNgtoYQklu8EhrfHVZUzTwKGZx2r/KDSfnljcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string.prototype.codepointat": "^0.2.0"
|
||||
}
|
||||
|
@ -13374,7 +13406,8 @@
|
|||
"signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
|
||||
"dev": true
|
||||
},
|
||||
"simctl": {
|
||||
"version": "2.0.3",
|
||||
|
@ -13617,7 +13650,8 @@
|
|||
"string.prototype.codepointat": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
|
||||
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
|
||||
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==",
|
||||
"dev": true
|
||||
},
|
||||
"stringify-package": {
|
||||
"version": "1.0.1",
|
||||
|
@ -13642,7 +13676,8 @@
|
|||
"strip-final-newline": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
|
||||
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="
|
||||
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
|
@ -14006,7 +14041,8 @@
|
|||
"untildify": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
|
||||
"integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw=="
|
||||
"integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
|
||||
"dev": true
|
||||
},
|
||||
"update-notifier": {
|
||||
"version": "5.1.0",
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"dependencies": {
|
||||
"@padloc/app": "4.0.0",
|
||||
"@padloc/core": "4.0.0",
|
||||
"cordova-android": "10.1.0",
|
||||
"cordova-clipboard": "1.3.0",
|
||||
"cordova-ios": "6.2.0",
|
||||
"cordova-plugin-add-swift-support": "2.0.2",
|
||||
|
@ -64,6 +63,7 @@
|
|||
"@types/cordova-plugin-qrscanner": "1.0.31",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"cordova": "11.0.0",
|
||||
"cordova-android": "10.1.2",
|
||||
"css-loader": "5.2.6",
|
||||
"dotenv": "10.0.0",
|
||||
"file-loader": "6.2.0",
|
||||
|
|
|
@ -49,6 +49,7 @@ export class CordovaPlatform extends WebPlatform implements Platform {
|
|||
platform,
|
||||
osVersion,
|
||||
description: appleDeviceNames[model] || model,
|
||||
runtime: "cordova",
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -231,6 +231,9 @@ export class Auth extends Serializable implements Storable {
|
|||
@AsSerializable(PBES2Container)
|
||||
legacyData?: PBES2Container;
|
||||
|
||||
/** Completely disables mfa for a given account. Only use for testing! */
|
||||
disableMFA = false;
|
||||
|
||||
constructor(public email: string = "") {
|
||||
super();
|
||||
}
|
||||
|
|
|
@ -99,8 +99,10 @@ export class Err extends Error {
|
|||
}
|
||||
|
||||
toString() {
|
||||
return `Time: ${this.time.toISOString()}\nError Code: ${this.code}:\nError Message: ${
|
||||
this.message
|
||||
}\nStack Trace:\n${this.originalError ? this.originalError.stack : this.stack}`;
|
||||
return `Time: ${this.time.toISOString()}
|
||||
Error Code: ${this.code}
|
||||
Error Message: ${this.message}
|
||||
Stack Trace:\n${this.originalError ? this.originalError.stack : this.stack}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,8 +69,8 @@ export class FailedLoginAttemptMessage extends Message<{ location: string }> {
|
|||
}
|
||||
}
|
||||
|
||||
export class ErrorMessage extends Message<{ code: string; message: string; time: string; eventId: string }> {
|
||||
template = "error";
|
||||
export class PlainMessage extends Message<{ message: string }> {
|
||||
template = "plain";
|
||||
|
||||
get title() {
|
||||
return "Padloc Error Notification";
|
||||
|
|
|
@ -47,6 +47,8 @@ export class DeviceInfo extends Serializable {
|
|||
|
||||
description: string = $l("Unknown Device");
|
||||
|
||||
runtime: string = "";
|
||||
|
||||
constructor(props?: Partial<DeviceInfo>) {
|
||||
super();
|
||||
props && Object.assign(this, props);
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Config, ConfigParam } from "./config";
|
|||
import { AsSerializable, Serializable } from "./encoding";
|
||||
import { Err, ErrorCode } from "./error";
|
||||
import { Org, OrgID, OrgInfo } from "./org";
|
||||
import { Session } from "./session";
|
||||
import { Storable, Storage } from "./storage";
|
||||
import { getIdFromEmail } from "./util";
|
||||
|
||||
|
@ -215,7 +216,7 @@ export class Provisioning extends Serializable {
|
|||
}
|
||||
|
||||
export interface Provisioner {
|
||||
getProvisioning(params: { email: string; accountId?: AccountID }): Promise<Provisioning>;
|
||||
getProvisioning(params: { email: string; accountId?: AccountID }, session?: Session): Promise<Provisioning>;
|
||||
accountDeleted(params: { email: string; accountId?: AccountID }): Promise<void>;
|
||||
orgDeleted(params: OrgInfo): Promise<void>;
|
||||
orgOwnerChanged(
|
||||
|
|
|
@ -44,7 +44,7 @@ import { Org, OrgID, OrgMember, OrgMemberStatus, OrgRole, ScimSettings } from ".
|
|||
import { Invite } from "./invite";
|
||||
import {
|
||||
ConfirmMembershipInviteMessage,
|
||||
ErrorMessage,
|
||||
PlainMessage,
|
||||
JoinOrgInviteAcceptedMessage,
|
||||
JoinOrgInviteCompletedMessage,
|
||||
JoinOrgInviteMessage,
|
||||
|
@ -200,13 +200,11 @@ export class Controller extends API {
|
|||
// Get account associated with this session
|
||||
const account = await this.storage.get(Account, session.account);
|
||||
const auth = await this._getAuth(account.email);
|
||||
const provisioning = await this.provisioner.getProvisioning(auth);
|
||||
|
||||
// Store account and session on context
|
||||
ctx.session = session;
|
||||
ctx.account = account;
|
||||
ctx.auth = auth;
|
||||
ctx.provisioning = provisioning;
|
||||
ctx.location = req.location;
|
||||
|
||||
// Update session info
|
||||
|
@ -222,6 +220,8 @@ export class Controller extends API {
|
|||
auth.sessions.push(session.info);
|
||||
}
|
||||
|
||||
ctx.provisioning = await this.provisioner.getProvisioning(auth, session);
|
||||
|
||||
await Promise.all([this.storage.save(session), this.storage.save(account), this.storage.save(auth)]);
|
||||
}
|
||||
|
||||
|
@ -356,7 +356,8 @@ export class Controller extends API {
|
|||
auth.authRequests.push(request);
|
||||
|
||||
const deviceTrusted =
|
||||
this.context.device && auth.trustedDevices.some(({ id }) => id === this.context.device!.id);
|
||||
auth.disableMFA ||
|
||||
(this.context.device && auth.trustedDevices.some(({ id }) => id === this.context.device!.id));
|
||||
|
||||
const response = new StartAuthRequestResponse({
|
||||
id: request.id,
|
||||
|
@ -2121,8 +2122,6 @@ export class Server {
|
|||
}
|
||||
|
||||
private async _handleError(error: Error, req: Request, res: Response, context: Context) {
|
||||
console.error(error);
|
||||
|
||||
const e =
|
||||
error instanceof Err
|
||||
? error
|
||||
|
@ -2139,6 +2138,8 @@ export class Server {
|
|||
};
|
||||
|
||||
if (e.report) {
|
||||
console.error(error);
|
||||
|
||||
const evt = this.log("error", context, {
|
||||
error: e.toRaw(),
|
||||
request: {
|
||||
|
@ -2151,11 +2152,12 @@ export class Server {
|
|||
try {
|
||||
await this.messenger.send(
|
||||
this.config.reportErrors,
|
||||
new ErrorMessage({
|
||||
time: e.time.toISOString(),
|
||||
code: e.code,
|
||||
message: e.message,
|
||||
eventId: evt.id,
|
||||
new PlainMessage({
|
||||
message: `The following error occured at ${e.time.toISOString()}:\n\nEndpoint: ${
|
||||
req.method
|
||||
}\nDevice Info:\n${
|
||||
req.device && JSON.stringify(req.device?.toRaw(), null, 4)
|
||||
}\n${e.toString()}${evt?.id ? `Event ID: ${evt.id}` : ""}`,
|
||||
})
|
||||
);
|
||||
} catch (e) {}
|
||||
|
|
|
@ -21,6 +21,18 @@ export async function uuid(): Promise<string> {
|
|||
].join("-");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random UUID v4
|
||||
* NOT CRYPTOGRAPHICALLY SAFE!
|
||||
*/
|
||||
export function unsafeUUID(): string {
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
||||
var r = (Math.random() * 16) | 0,
|
||||
v = c == "x" ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
/** Caracters, by category */
|
||||
export const chars = {
|
||||
numbers: "0123456789",
|
||||
|
|
|
@ -62,6 +62,7 @@ async function main() {
|
|||
snap: {
|
||||
confinement: "strict",
|
||||
plugs: ["desktop", "home", "browser-support", "network", "opengl", "x11", "wayland", "unity7"],
|
||||
publish: ["github"],
|
||||
},
|
||||
afterSign: "scripts/notarize.js",
|
||||
};
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { Platform } from "@padloc/core/src/platform";
|
||||
import { WebPlatform } from "@padloc/app/src/lib/platform";
|
||||
|
||||
export class ElectronPlatform extends WebPlatform implements Platform {}
|
||||
export class ElectronPlatform extends WebPlatform implements Platform {
|
||||
async getDeviceInfo() {
|
||||
const device = await super.getDeviceInfo();
|
||||
device.runtime = "electron";
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ export class ExtensionPlatform extends WebPlatform {
|
|||
async getDeviceInfo() {
|
||||
const info = await super.getDeviceInfo();
|
||||
info.description = `${info.browser} extension on ${info.platform}`;
|
||||
info.runtime = "extension";
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ export class LoggingConfig extends Config {
|
|||
}
|
||||
|
||||
@ConfigParam()
|
||||
backend: "void" | "mongodb" | "mixpanel" = "void";
|
||||
backend: "void" | "mongodb" | "postgres" | "mixpanel" = "void";
|
||||
|
||||
@ConfigParam()
|
||||
secondaryBackend?: "mongodb" | "mixpanel";
|
||||
|
@ -90,6 +90,9 @@ export class LoggingConfig extends Config {
|
|||
@ConfigParam(MongoDBStorageConfig)
|
||||
mongodb?: MongoDBStorageConfig;
|
||||
|
||||
@ConfigParam(PostgresConfig)
|
||||
postgres?: PostgresConfig;
|
||||
|
||||
@ConfigParam(MixpanelConfig)
|
||||
mixpanel?: MixpanelConfig;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { AuthServer, AuthType } from "@padloc/core/src/auth";
|
|||
import { WebAuthnConfig, WebAuthnServer } from "./auth/webauthn";
|
||||
import { SMTPSender } from "./email/smtp";
|
||||
import { MongoDBStorage } from "./storage/mongodb";
|
||||
import { ConsoleMessenger, ErrorMessage } from "@padloc/core/src/messenger";
|
||||
import { ConsoleMessenger, PlainMessage } from "@padloc/core/src/messenger";
|
||||
import { FSAttachmentStorage, FSAttachmentStorageConfig } from "./attachments/fs";
|
||||
import {
|
||||
AttachmentStorageConfig,
|
||||
|
@ -33,11 +33,11 @@ import { resolve, join } from "path";
|
|||
import { MongoDBLogger } from "./logging/mongodb";
|
||||
import { MixpanelLogger } from "./logging/mixpanel";
|
||||
import { PostgresStorage } from "./storage/postgres";
|
||||
import { ErrorCode } from "@padloc/core/src/error";
|
||||
import { stripPropertiesRecursive } from "@padloc/core/src/util";
|
||||
import { DirectoryProvisioner } from "./provisioning/directory";
|
||||
import { ScimServer, ScimServerConfig } from "./scim";
|
||||
import { DirectoryProvider, DirectorySync } from "@padloc/core/src/directory";
|
||||
import { PostgresLogger } from "./logging/postgres";
|
||||
|
||||
const rootDir = resolve(__dirname, "../../..");
|
||||
const assetsDir = resolve(rootDir, process.env.PL_ASSETS_DIR || "assets");
|
||||
|
@ -75,7 +75,7 @@ async function initDataStorage(config: DataStorageConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
async function initLogger({ backend, secondaryBackend, mongodb, mixpanel }: LoggingConfig) {
|
||||
async function initLogger({ backend, secondaryBackend, mongodb, postgres, mixpanel }: LoggingConfig) {
|
||||
let primaryLogger: Logger;
|
||||
|
||||
switch (backend) {
|
||||
|
@ -83,9 +83,15 @@ async function initLogger({ backend, secondaryBackend, mongodb, mixpanel }: Logg
|
|||
if (!mongodb) {
|
||||
throw "PL_LOGGING_BACKEND was set to 'mongodb', but no related configuration was found!";
|
||||
}
|
||||
const storage = new MongoDBStorage(mongodb);
|
||||
await storage.init();
|
||||
primaryLogger = new MongoDBLogger(storage);
|
||||
const mongoStorage = new MongoDBStorage(mongodb);
|
||||
await mongoStorage.init();
|
||||
primaryLogger = new MongoDBLogger(mongoStorage);
|
||||
break;
|
||||
case "postgres":
|
||||
if (!postgres) {
|
||||
throw "PL_LOGGING_BACKEND was set to 'postgres', but no related configuration was found!";
|
||||
}
|
||||
primaryLogger = new PostgresLogger(new PostgresStorage(postgres));
|
||||
break;
|
||||
case "void":
|
||||
primaryLogger = new VoidLogger();
|
||||
|
@ -302,11 +308,10 @@ async function init(config: PadlocConfig) {
|
|||
try {
|
||||
await emailSender.send(
|
||||
config.server.reportErrors,
|
||||
new ErrorMessage({
|
||||
code: ErrorCode.UNKNOWN_ERROR,
|
||||
message: `${err.message}\n${err.stack}`,
|
||||
time: new Date().toISOString(),
|
||||
eventId: "",
|
||||
new PlainMessage({
|
||||
message: `An uncaught exception occured at ${new Date().toISOString()}:\n${err.message}\n${
|
||||
err.stack
|
||||
}`,
|
||||
})
|
||||
);
|
||||
} catch (e) {}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { Logger, LogEvent } from "@padloc/core/src/logging";
|
||||
import { PostgresStorage } from "../storage/postgres";
|
||||
|
||||
export class PostgresLogger implements Logger {
|
||||
constructor(private _storage: PostgresStorage) {}
|
||||
|
||||
log(type: string, data?: any) {
|
||||
const event = new LogEvent(type, data);
|
||||
event.id = `${event.time.toISOString()}_${Math.floor(Math.random() * 1e6)}`;
|
||||
(async () => {
|
||||
try {
|
||||
this._storage.save(event);
|
||||
} catch (e) {}
|
||||
})();
|
||||
return event;
|
||||
}
|
||||
}
|
|
@ -3,4 +3,10 @@ import { NodeCryptoProvider } from "../crypto/node";
|
|||
|
||||
export class NodePlatform extends StubPlatform implements Platform {
|
||||
crypto = new NodeCryptoProvider();
|
||||
|
||||
async getDeviceInfo() {
|
||||
const info = await super.getDeviceInfo();
|
||||
info.runtime = "node";
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import { base64ToBytes, bytesToBase64, stringToBytes } from "@padloc/core/src/en
|
|||
import { HMACKeyParams, HMACParams } from "@padloc/core/src/crypto";
|
||||
import { URLSearchParams } from "url";
|
||||
import { Account } from "@padloc/core/src/account";
|
||||
import { Session } from "@padloc/core/src/session";
|
||||
|
||||
export class StripeProvisionerConfig extends BasicProvisionerConfig {
|
||||
@ConfigParam("string", true)
|
||||
|
@ -48,6 +49,9 @@ export class StripeProvisionerConfig extends BasicProvisionerConfig {
|
|||
|
||||
@ConfigParam("number")
|
||||
forceSyncAfter: number = 24 * 60 * 60;
|
||||
|
||||
@ConfigParam("string[]")
|
||||
disableBillingOn = ["ios", "android"];
|
||||
}
|
||||
|
||||
enum Tier {
|
||||
|
@ -97,7 +101,7 @@ export class StripeProvisioner extends BasicProvisioner {
|
|||
[Tier.Premium]: {
|
||||
order: 1,
|
||||
name: "Premium",
|
||||
description: "Power up your password manager!",
|
||||
description: "Advanced multi-factor authentication, encrypted file storage and more!",
|
||||
minSeats: undefined,
|
||||
maxSeats: undefined,
|
||||
features: [
|
||||
|
@ -218,8 +222,8 @@ export class StripeProvisioner extends BasicProvisioner {
|
|||
}
|
||||
}
|
||||
|
||||
async getProvisioning(opts: { email: string; accountId?: string | undefined }) {
|
||||
const provisioning = await super.getProvisioning(opts);
|
||||
async getProvisioning(opts: { email: string; accountId?: string | undefined }, session?: Session) {
|
||||
let provisioning = await super.getProvisioning(opts);
|
||||
if (
|
||||
provisioning.account.accountId &&
|
||||
(!provisioning.account.metaData?.customer ||
|
||||
|
@ -228,7 +232,35 @@ export class StripeProvisioner extends BasicProvisioner {
|
|||
) {
|
||||
await this._syncBilling(provisioning);
|
||||
}
|
||||
return super.getProvisioning(opts);
|
||||
|
||||
provisioning = await super.getProvisioning(opts);
|
||||
|
||||
const platform = session?.device?.platform?.toLowerCase() || "";
|
||||
const runtime = session?.device?.runtime;
|
||||
if (runtime === "cordova" && this.config.disableBillingOn.includes(platform)) {
|
||||
provisioning.account.billingPage = undefined;
|
||||
for (const feature of Object.values(provisioning.account.features)) {
|
||||
if (feature.disabled) {
|
||||
feature.message = {
|
||||
type: "html",
|
||||
content: html`
|
||||
<div style="max-width: 20em">
|
||||
<div class="large text-centering semibold">
|
||||
<i class="fa-ban"></i> Feature Not Available
|
||||
</div>
|
||||
<div class="top-margined">
|
||||
This feature is not available on this platform yet. Please use the
|
||||
<a href="https://web.padloc.app">web app</a> instead!
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
feature.actionUrl = "https://web.padloc.app";
|
||||
feature.actionLabel = "Open Web App";
|
||||
}
|
||||
}
|
||||
}
|
||||
return provisioning;
|
||||
}
|
||||
|
||||
async orgOwnerChanged(
|
||||
|
@ -328,21 +360,14 @@ export class StripeProvisioner extends BasicProvisioner {
|
|||
email,
|
||||
expand: ["data.subscriptions", "data.tax_ids"],
|
||||
});
|
||||
customer = existingCustomers.data.find(
|
||||
(c) => !c.metadata.org && (!c.metadata.account || c.metadata.account === accountId)
|
||||
);
|
||||
customer = existingCustomers.data.find((c) => !c.metadata.account || c.metadata.account === accountId);
|
||||
}
|
||||
|
||||
// Create a new customer
|
||||
if (!customer || customer.deleted) {
|
||||
const account = accountId ? await this.storage.get(Account, accountId).catch(() => null) : null;
|
||||
const testClock = await this._stripe.testHelpers.testClocks.create({
|
||||
name: `Test Clock for ${email}`,
|
||||
frozen_time: Math.floor(Date.now() / 1000),
|
||||
});
|
||||
customer = await this._stripe.customers.create({
|
||||
email,
|
||||
test_clock: testClock.id,
|
||||
name: account?.name,
|
||||
metadata: {
|
||||
account: accountId!,
|
||||
|
@ -1464,7 +1489,7 @@ export class StripeProvisioner extends BasicProvisioner {
|
|||
protected async _handleRequest(httpReq: IncomingMessage, httpRes: ServerResponse) {
|
||||
const path = new URL(httpReq.url!, "http://localhost").pathname;
|
||||
|
||||
if (path === "/stripe_webhooks") {
|
||||
if (path.endsWith("/stripe_webhooks")) {
|
||||
if (httpReq.method !== "POST") {
|
||||
httpRes.statusCode = 405;
|
||||
httpRes.end();
|
||||
|
@ -1474,7 +1499,7 @@ export class StripeProvisioner extends BasicProvisioner {
|
|||
return this._handleStripeEvent(httpReq, httpRes);
|
||||
}
|
||||
|
||||
if (path === "/sync") {
|
||||
if (path.endsWith("/sync")) {
|
||||
if (httpReq.method !== "POST") {
|
||||
httpRes.statusCode = 405;
|
||||
httpRes.end();
|
||||
|
@ -1484,7 +1509,7 @@ export class StripeProvisioner extends BasicProvisioner {
|
|||
return this._handleSyncBilling(httpReq, httpRes);
|
||||
}
|
||||
|
||||
if (path === "/portal") {
|
||||
if (path.endsWith("/portal")) {
|
||||
if (httpReq.method !== "GET") {
|
||||
httpRes.statusCode = 405;
|
||||
httpRes.end();
|
||||
|
@ -1494,7 +1519,7 @@ export class StripeProvisioner extends BasicProvisioner {
|
|||
return this._handlePortalRequest(httpReq, httpRes);
|
||||
}
|
||||
|
||||
if (path == "/callback") {
|
||||
if (path.endsWith("/callback")) {
|
||||
if (httpReq.method !== "GET") {
|
||||
httpRes.statusCode = 405;
|
||||
httpRes.end();
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { Platform } from "@padloc/core/src/platform";
|
||||
import { WebPlatform } from "@padloc/app/src/lib/platform";
|
||||
// import { MemoryStorage } from "@padloc/core/src/storage";
|
||||
|
||||
export class TauriPlatform extends WebPlatform implements Platform {
|
||||
// storage = new MemoryStorage();
|
||||
async getDeviceInfo() {
|
||||
const device = await super.getDeviceInfo();
|
||||
device.runtime = "tauri";
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue