diff --git a/README.md b/README.md
index d86b158..d621875 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,6 @@
[![hacs_badge][hacs_shield]][hacs]
[![GitHub Latest Release][releases_shield]][latest_release]
-[hacs_shield]: https://img.shields.io/badge/HACS-Custom-41BDF5.svg?style=for-the-badge
-[hacs]: https://github.com/hacs/integration
-
-[releases_shield]: https://img.shields.io/github/release/igor-panteleev/lovelace-qr-code-card.svg?style=for-the-badge
-[latest_release]: https://github.com/igor-panteleev/lovelace-qr-code-card/releases/latest
-
# Lovelace QRCode Generator card
This card provides a possibility to generate QRCode in Home Assistant interface.
@@ -19,88 +13,46 @@ This card provides a possibility to generate QRCode in Home Assistant interface.
## Configuration
-
-
- Key |
- Type |
- Required |
- Default |
- Description |
-
-
-
- General options
- |
-
-
- title |
- string |
- no |
- empty |
- Title for the card |
-
-
- source |
- string |
- yes |
- text |
- Card source type. Options: text , entity , wifi |
-
-
-
- Text mode options
- |
-
-
- text |
- string |
- yes |
- QRCode example text |
- Text that will be used for QRCode generation |
-
-
-
- Entity mode options
- |
-
-
- entity |
- string |
- yes |
- empty |
- Entity that will be used for QRCode generation |
-
-
-
- Wi-Fi mode options
- |
-
-
- auth_type |
- string |
- yes |
- empty |
- Wi-Fi network authentication type. Options: WEP , WPA , nopass |
-
-
- ssid |
- string |
- yes |
- empty |
- Wi-Fi network ssid |
-
-
- password |
- string |
- yes (except nopass authentication) |
- empty |
- Wi-Fi network password |
-
-
- is_hidden |
- boolean |
- no |
- empty |
- Is Wi-Fi network is hidden |
-
-
+### Main config
+
+| Key | Type | Required | Default | Description |
+|-----------------------|------------------------------------------|-----------------|---------------------|-------------------------------------------------------------------------|
+| *Generic options* |
+| `title` | string | no | empty | Title for the card |
+| `source` | string | yes | `text` | Card source type.
Options: `text,` `entity`, `wifi` |
+| *Text mode options* |
+| `text` | string | yes | QRCode example text | Text that will be used for QRCode generation |
+| *Entity mode options* |
+| `entity` | string | yes | empty | Entity that will be used for QRCode generation |
+| *Wi-Fi mode options* |
+| `auth_type` | string | yes | empty | Wi-Fi network authentication type.
Options: `WEP`, `WPA`, `nopass` |
+| `ssid` | string \| [EntityConfig](#entity-config) | yes | empty | Wi-Fi network ssid |
+| `password` | string \| [EntityConfig](#entity-config) | yes1 | empty | Wi-Fi network password |
+| `is_hidden` | boolean | no | empty | Is Wi-Fi network is hidden |
+
+1Required for `WEP` and `WPA` authentication
+
+### Entity Config
+
+| Key | Type | Required | Description |
+|-------------|--------|----------|--------------------------------------------------------------------------|
+| `entity` | string | yes | Entity to get state from |
+| `attribute` | string | no | Enables usage of a configured attribute instead of state of given entity |
+
+
+### Example WiFi config
+```yaml
+type: custom:qr-code-card
+source: wifi
+title: My Awesom WiFi
+auth_type: WPA
+ssid: my_awesom_wifi
+password:
+ entity: input_text.my_super_secure_password
+```
+
+[hacs_shield]: https://img.shields.io/badge/HACS-Custom-41BDF5.svg?style=for-the-badge
+[hacs]: https://github.com/hacs/integration
+
+[releases_shield]: https://img.shields.io/github/release/igor-panteleev/lovelace-qr-code-card.svg?style=for-the-badge
+[latest_release]: https://github.com/igor-panteleev/lovelace-qr-code-card/releases/latest
diff --git a/package.json b/package.json
index 42159f5..6881984 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "qr-code-card",
- "version": "v1.1.0",
+ "version": "v1.2.0",
"description": "QR code card",
"keywords": [
"home-assistant",
diff --git a/src/editor.ts b/src/editor.ts
index 317a7a8..2579b55 100644
--- a/src/editor.ts
+++ b/src/editor.ts
@@ -12,7 +12,7 @@ import {
} from "./types/types";
import { localizeWithHass } from "./localize/localize";
import { SourceType } from "./models/source-type";
-import { AuthenticationType, is_password_protected } from "./models/authentication-type";
+import { AuthenticationType, isPasswordProtected } from "./models/authentication-type";
import { EDITOR_CUSTOM_ELEMENT_NAME } from "./const";
@@ -54,24 +54,39 @@ export class QRCodeCardEditor extends LitElement implements LovelaceCardEditor {
get _ssid(): string {
const config = this._config as WiFiSourceConfig | undefined;
- return config?.ssid || "";
+ if (typeof config?.ssid === "string") {
+ return config?.ssid || "";
+ }
+ return ""
}
get _password(): string {
const config = this._config as WiFiSourceConfig | undefined;
- return config?.password || "";
+ if (typeof config?.password === "string") {
+ return config?.password || "";
+ }
+ return "";
}
get _is_hidden(): boolean {
const config = this._config as WiFiSourceConfig | undefined;
return config?.is_hidden || false;
}
+
+ get _is_debug(): boolean {
+ const config = this._config as QRCodeCardConfig | undefined;
+ return config?.debug || false;
+ }
get _entity(): string {
const config = this._config as EntitySourceConfig | undefined;
return config?.entity || ""
}
+ private _isDisabled(): boolean {
+ return this._config?.source === SourceType.WIFI && (typeof this._config?.ssid !== "string" || typeof this._config?.password !== "string");
+ }
+
private _localize(ts: TranslatableString): string {
return localizeWithHass(ts, this.hass, this._config);
}
@@ -81,6 +96,13 @@ export class QRCodeCardEditor extends LitElement implements LovelaceCardEditor {
return html``;
}
+ if (this._isDisabled()) {
+ return html`
+
+
${this._localize("editor.yaml_mode")}
+
`;
+ }
+
const entities = Object.keys(this.hass.states);
return html`
@@ -139,7 +161,7 @@ export class QRCodeCardEditor extends LitElement implements LovelaceCardEditor {
.configValue=${"ssid"}
@input=${this._valueChanged}>
- ${is_password_protected(this._auth_type) ? html`
+ ${isPasswordProtected(this._auth_type) ? html`
` : ""}
+
+
+
+
+
+
`;
}
@@ -250,6 +281,10 @@ export class QRCodeCardEditor extends LitElement implements LovelaceCardEditor {
color: var(--secondary-text-color);
direction: var(--direction);
}
+
+ .error {
+ color: var(--error-color);
+ }
`;
}
}
diff --git a/src/generator.ts b/src/generator.ts
new file mode 100644
index 0000000..f292e1d
--- /dev/null
+++ b/src/generator.ts
@@ -0,0 +1,18 @@
+import QRCode from "qrcode";
+
+import { DataUrl } from "./types/types";
+import { TranslatableError } from "./models/error";
+
+const quality = {
+ margin: 1,
+ width: 500
+}
+
+export async function generateQR(inputString: string): Promise {
+ try {
+ return QRCode.toDataURL(inputString, quality);
+ }
+ catch (e: unknown) {
+ throw new TranslatableError("generation.unknown_error")
+ }
+}
diff --git a/src/localize/languages/en.json b/src/localize/languages/en.json
index d8399fb..fada52d 100644
--- a/src/localize/languages/en.json
+++ b/src/localize/languages/en.json
@@ -13,7 +13,8 @@
"auth_type": "Authentication type (required)",
"ssid": "SSID (required)",
"password": "Password (required)",
- "is_hidden": "Hidden SSID"
+ "is_hidden": "Hidden SSID",
+ "is_debug": "Debug mode (Show value for QR code)"
},
"title": {
"show_password": "Show password",
@@ -30,9 +31,13 @@
"WPA": "WPA",
"nopass": "None"
}
- }
+ },
+ "yaml_mode": "Configuring SSID and password from entity is not supported in visual editor mode. Please switch to code editor mode."
},
"validation": {
+ "debug": {
+ "invalid": "Debug mode must be true or false"
+ },
"source": {
"missing": "Missing property: source",
"invalid": "Invalid source type"
@@ -45,16 +50,29 @@
"invalid": "Invalid authentication type"
},
"ssid": {
- "missing": "Missing property: ssid"
+ "missing": "Missing property: ssid",
+ "unknown_type": "Unsupported data type for SSID: {type}",
+ "unknown_entity": "Entity specified for SSID is unknown: {entity}",
+ "unknown_attribute": "Attribute specified for SSID is unknown: {attribute}",
+ "unavailable": "Entity specified for SSID is unavailable: {entity}"
},
"password": {
- "missing": "Missing property: password"
+ "missing": "Missing property: password",
+ "unknown_type": "Unsupported data type for password: {type}",
+ "unknown_entity": "Entity specified for password is unknown: {entity}",
+ "unknown_attribute": "Attribute specified for password is unknown: {attribute}",
+ "unavailable": "Entity specified for password is unavailable: {entity}"
},
"entity": {
- "missing": "Missing property: entity"
+ "missing": "Missing property: entity",
+ "unknown_type": "Unsupported data type for entity: {type}",
+ "unknown_entity": "Unknown entity: {entity}",
+ "unknown_attribute": "Attribute specified for entity is unknown: {attribute}",
+ "unavailable": "Entity is unavailable: {entity}"
}
},
"generation": {
- "error": "An error occurred while generating QR-Code"
+ "error": "An error occurred while generating QR-Code: {message}",
+ "unknown_error": "An error occurred while generating QR-Code"
}
}
diff --git a/src/models/authentication-type.ts b/src/models/authentication-type.ts
index c3369d4..e3da799 100644
--- a/src/models/authentication-type.ts
+++ b/src/models/authentication-type.ts
@@ -6,6 +6,6 @@ export enum AuthenticationType {
const PasswordAuthenticationTypes = [AuthenticationType.WEP, AuthenticationType.WPA];
-export function is_password_protected(auth_type: AuthenticationType | undefined): boolean {
+export function isPasswordProtected(auth_type: AuthenticationType | undefined): boolean {
return auth_type !== undefined && PasswordAuthenticationTypes.includes(auth_type);
}
diff --git a/src/models/data-builder.ts b/src/models/data-builder.ts
new file mode 100644
index 0000000..3b9f30e
--- /dev/null
+++ b/src/models/data-builder.ts
@@ -0,0 +1,131 @@
+import {
+ EntitySourceConfig,
+ QRCodeCardConfig,
+ QRCodeGeneratorClass,
+ TextSourceConfig,
+ WiFiSourceConfig,
+} from "../types/types";
+import { isPasswordProtected } from "./authentication-type";
+import { SourceType } from "./source-type";
+import { HomeAssistant } from "custom-card-helpers";
+import { TranslatableError } from "./error";
+
+
+abstract class QRCodeDataBuilder {
+
+ protected readonly config: T;
+ protected readonly hass: HomeAssistant;
+
+ public constructor(hass: HomeAssistant, config: T) {
+ this.hass = hass;
+ this.config = config;
+ }
+
+ public getInputString(): string {
+ try {
+ return this._getInputString();
+ }
+ catch (e: unknown) {
+ if (e instanceof TranslatableError) {
+ throw e
+ } else if (e instanceof Error) {
+ throw new TranslatableError(["generation.error", "{message}", e.message])
+ }
+ throw new TranslatableError("generation.unknown_error")
+ }
+ }
+
+ protected abstract _getInputString(): string
+
+ protected _getValueFromConfig(property: string): string {
+ let result: string;
+
+ const configProperty = this.config[property];
+ if (configProperty === undefined) {
+ throw new TranslatableError(`validation.${property}.missing`)
+ } else if (typeof configProperty === "string") {
+ result = configProperty;
+ } else if (configProperty.hasOwnProperty("entity")) {
+ const entity = this.hass?.states[configProperty.entity]
+ if (entity === undefined) {
+ throw new TranslatableError([`validation.${property}.unknown_entity`, "{entity}", configProperty.entity])
+ }
+ if (configProperty.attribute !== undefined) {
+ const attribute_value = entity.attributes[configProperty.attribute];
+ if (attribute_value === undefined) {
+ throw new TranslatableError([`validation.${property}.unknown_attribute`, "{attribute}", configProperty.attribute])
+ }
+ result = attribute_value.toString();
+ } else {
+ const state = entity.state;
+ if (state === "unavailable") {
+ throw new TranslatableError([`validation.${property}.unavailable`, "{entity}", configProperty.entity])
+ }
+ result = state;
+ }
+ } else {
+ throw new TranslatableError([`validation.${property}.unknown_type`, "{type}", typeof configProperty])
+ }
+
+ return result;
+ }
+}
+
+
+class TextQRCodeDataBuilder extends QRCodeDataBuilder {
+
+ protected _getInputString(): string {
+ return this.config.text || "";
+ }
+}
+
+
+class WiFiQRCodeDataBuilder extends QRCodeDataBuilder {
+ protected readonly special_chars = ['\\', ';', ',', '"', ':']
+
+ protected _escape(plain: string): string {
+ return this.special_chars.reduce(
+ (previousValue, currentValue) => {
+ return previousValue.replace(currentValue, '\\'+currentValue)
+ },
+ plain
+ );
+ }
+
+ protected _getInputString(): string {
+ const ssid = this._getValueFromConfig("ssid");
+ let text = `WIFI:T:${this.config.auth_type || ""};S:${this._escape(ssid)};`;
+
+ if (isPasswordProtected(this.config.auth_type)) {
+ const password = this._getValueFromConfig("password");
+ text += `P:${this._escape(password)};`
+ }
+
+ if (this.config.is_hidden) {
+ text += "H:true"
+ }
+
+ return text;
+ }
+}
+
+class EntityQRCodeDataBuilder extends QRCodeDataBuilder {
+ protected _getInputString(): string {
+ return this._getValueFromConfig("entity")
+ }
+}
+
+const configBuilderMapping = new Map>>([
+ [SourceType.TEXT, TextQRCodeDataBuilder],
+ [SourceType.WIFI, WiFiQRCodeDataBuilder],
+ [SourceType.ENTITY, EntityQRCodeDataBuilder]
+]);
+
+
+export function getInputString(hass: HomeAssistant, config: QRCodeCardConfig): string {
+ const dataBuilderCls = configBuilderMapping.get(config.source);
+
+ if (!dataBuilderCls) throw new TranslatableError("validation.source.invalid");
+
+ return new dataBuilderCls(hass, config).getInputString();
+}
diff --git a/src/models/error.ts b/src/models/error.ts
new file mode 100644
index 0000000..b9ecf3b
--- /dev/null
+++ b/src/models/error.ts
@@ -0,0 +1,8 @@
+import { TranslatableString } from "../types/types";
+import { localize } from "../localize/localize";
+
+export class TranslatableError extends Error {
+ public constructor(ts: TranslatableString) {
+ super(localize(ts));
+ }
+}
diff --git a/src/models/generator.ts b/src/models/generator.ts
deleted file mode 100644
index 8b02376..0000000
--- a/src/models/generator.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import QRCode from "qrcode";
-
-import {
- DataUrl, EntitySourceConfig,
- QRCodeCardConfig,
- QRCodeGeneratorClass,
- TextSourceConfig,
- WiFiSourceConfig,
-} from "../types/types";
-import { is_password_protected } from "./authentication-type";
-import { SourceType } from "./source-type";
-import { localize } from "../localize/localize";
-import { HomeAssistant } from "custom-card-helpers";
-
-
-abstract class QRCodeGenerator {
-
- protected readonly config: T;
- protected readonly hass: HomeAssistant;
-
- // TODO: make it configurable
- protected readonly quality = {
- margin: 1,
- width: 500
- }
-
- public constructor(hass: HomeAssistant, config: T) {
- this.hass = hass;
- this.config = config;
- }
-
- public async generate(): Promise {
- try {
- return QRCode.toDataURL(this.input, this.quality);
- }
- catch (e: any) {
- throw new Error(localize("generation.error"))
- }
- }
-
- protected abstract get input(): string
-
-}
-
-
-class TextQRCodeGenerator extends QRCodeGenerator {
-
- protected get input(): string {
- return this.config.text || "";
- }
-}
-
-
-class WiFiQRCodeGenerator extends QRCodeGenerator {
- protected readonly special_chars = ['\\', ';', ',', '"', ':']
-
- protected _escape(plain: string): string {
- return this.special_chars.reduce(
- (previousValue, currentValue) => {
- return previousValue.replace(currentValue, '\\'+currentValue)
- },
- plain
- );
- }
-
- protected get input(): string {
- let text = `WIFI:T:${this.config.auth_type || ""};S:${this._escape(this.config.ssid || "")};`;
-
- if (is_password_protected(this.config.auth_type)) {
- text += `P:${this._escape(this.config.password || "")};`
- }
-
- if (!this.config.is_hidden) {
- text += "H:true"
- }
-
- return text;
- }
-}
-
-class EntityQRCodeGenerator extends QRCodeGenerator {
- protected get input(): string {
- return this.hass?.states[this.config.entity].state
- }
-}
-
-const generatorMap = new Map>>([
- [SourceType.TEXT, TextQRCodeGenerator],
- [SourceType.WIFI, WiFiQRCodeGenerator],
- [SourceType.ENTITY, EntityQRCodeGenerator]
-]);
-
-
-export async function generateQR(hass: HomeAssistant, config: QRCodeCardConfig): Promise {
- const generatorCls = generatorMap.get(config.source);
-
- if (!generatorCls) throw new Error(localize("validation.source.invalid"));
-
- return await (new generatorCls(hass, config)).generate();
-}
diff --git a/src/qr-code-card.ts b/src/qr-code-card.ts
index 33ce68c..d31af85 100644
--- a/src/qr-code-card.ts
+++ b/src/qr-code-card.ts
@@ -9,10 +9,12 @@ import type {QRCodeCardConfig, TranslatableString } from "./types/types";
import { localize, localizeWithHass } from "./localize/localize";
import { getWatchedEntities, hasConfigOrAnyEntityChanged } from "./utils"
import { version } from '../package.json';
-import { generateQR } from "./models/generator";
+import { getInputString } from "./models/data-builder";
+import { generateQR } from "./generator";
import { validateConfig } from "./validators";
import { SourceType } from "./models/source-type";
import { CARD_CUSTOM_ELEMENT_NAME, EDITOR_CUSTOM_ELEMENT_NAME } from "./const";
+import { TranslatableError } from "./models/error";
console.info(
`%c QR-CODE-GENERATOR %c ${version} `,
@@ -46,6 +48,7 @@ export class QRCodeCard extends LitElement {
private config!: QRCodeCardConfig;
private watchedEntities: string[] = [];
+ private inputString!: string;
@property({ attribute: false }) public _hass!: HomeAssistant;
@state() private errors: string[] = [];
@state() private dataUrl = "";
@@ -75,12 +78,13 @@ export class QRCodeCard extends LitElement {
private async _updateQR(): Promise {
try {
- this.dataUrl = await generateQR(this.hass, this.config);
+ this.inputString = getInputString(this.hass, this.config)
+ this.dataUrl = await generateQR(this.inputString);
} catch (e: unknown) {
- if (e instanceof Error) {
+ if (e instanceof TranslatableError) {
this.errors = [e.message]
} else {
- this.errors = ['An unknown error occurred'];
+ this.errors = [this._localize("generation.unknown_error")];
}
}
}
@@ -97,13 +101,15 @@ export class QRCodeCard extends LitElement {
}
protected async update(changedProperties: PropertyValues): Promise {
- await this._updateQR();
+ if (this.errors.length == 0) {
+ await this._updateQR();
+ }
super.update(changedProperties);
}
protected render(): TemplateResult {
if (this.errors.length > 0) {
- return this._showErrors(this.errors);
+ return this._showErrors();
}
if (!this.dataUrl) {
@@ -117,6 +123,7 @@ export class QRCodeCard extends LitElement {
return html`
${(this.config?.title ?? "").length > 0 ? html``: ""}
+ ${(this.config?.debug ?? false) ? html`Input string: ${this.inputString}
`: ""}
@@ -124,15 +131,16 @@ export class QRCodeCard extends LitElement {
`
}
- private _showErrors(errors: string[]): TemplateResult {
- errors.forEach(e => console.error(e));
+ private _showErrors(): TemplateResult {
+ this.errors.forEach(e => console.error(e));
const errorCard = document.createElement("hui-error-card") as LovelaceCard;
- errorCard.setConfig({
- type: "error",
- error: errors[0],
- origConfig: this.config,
+ customElements.whenDefined("hui-error-card").then(() => {
+ errorCard.setConfig({
+ type: "error",
+ error: this.errors[0],
+ origConfig: this.config,
+ });
});
-
return html` ${errorCard} `;
}
@@ -147,8 +155,8 @@ export class QRCodeCard extends LitElement {
flex-direction: column;
flex: 1;
position: relative;
- padding: 0px;
- border-radius: 4px;
+ padding: 0;
+ border-radius: 6px;
overflow: hidden;
}
.qrcode {
diff --git a/src/types/types.ts b/src/types/types.ts
index 274fce7..6bf762a 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -19,8 +19,14 @@ export type DataUrl = string;
export type QRCodeGeneratorClass = new (...args: any[]) => T;
export type QRCodeValidatorClass = new (...args: any[]) => T;
+export interface EntityConfig {
+ readonly entity: string;
+ readonly attribute?: string;
+}
+
export interface BaseQRCodeCardConfig extends LovelaceCardConfig {
readonly language?: Language;
+ readonly debug?: boolean;
readonly title?: string;
readonly source: SourceType;
}
@@ -31,8 +37,8 @@ export interface TextSourceConfig extends BaseQRCodeCardConfig {
export interface WiFiSourceConfig extends BaseQRCodeCardConfig {
readonly auth_type: AuthenticationType;
- readonly ssid: string;
- readonly password?: string;
+ readonly ssid: string | EntityConfig;
+ readonly password?: string | EntityConfig;
readonly is_hidden?: boolean;
}
diff --git a/src/utils.ts b/src/utils.ts
index e5c173f..a598446 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -2,6 +2,7 @@ import { PropertyValues } from "@lit/reactive-element";
import { HomeAssistant } from "custom-card-helpers";
import { QRCodeCardConfig } from "./types/types"
import { SourceType } from "./models/source-type";
+import { TranslatableError } from "./models/error";
export function hasConfigOrAnyEntityChanged(
watchedEntities: string[],
@@ -24,11 +25,11 @@ export function getWatchedEntities(config: QRCodeCardConfig): string[] {
watchedEntities.add(config.entity);
break;
- // TODO: add support to use entities for WIFI QR code
- // case SourceType.WIFI:
- // if (config.ssid.hasOwnProperty("entity")) watchedEntities.add(config.ssid["entity"]);
- // if (config.password.hasOwnProperty("entity")) watchedEntities.add(config.password["entity"]);
+ case SourceType.WIFI:
+ if (config.ssid.hasOwnProperty("entity")) watchedEntities.add(config.ssid["entity"]);
+ if (config.password.hasOwnProperty("entity")) watchedEntities.add(config.password["entity"]);
}
return [...watchedEntities];
}
+
diff --git a/src/validators.ts b/src/validators.ts
index 480d1ac..42c7a72 100644
--- a/src/validators.ts
+++ b/src/validators.ts
@@ -8,7 +8,7 @@ import {
} from "./types/types";
import { localize } from "./localize/localize";
import { SourceType } from "./models/source-type";
-import { AuthenticationType, is_password_protected } from "./models/authentication-type";
+import { AuthenticationType, isPasswordProtected } from "./models/authentication-type";
abstract class Validator {
@@ -27,6 +27,18 @@ abstract class Validator {
}
+class DebugModeValidator extends Validator {
+ protected _validate(): string[] {
+ const errors: string[] = [];
+
+ if (this.config.debug !== undefined && typeof this.config.debug !== "boolean") {
+ errors.push("validation.debug.invalid");
+ }
+
+ return errors;
+ }
+}
+
class SourceValidator extends Validator {
protected _validate(): string[] {
const errors: string[] = [];
@@ -71,11 +83,17 @@ class WiFiValidator extends Validator {
// Validate ssid
if (!this.config.ssid) {
errors.push("validation.ssid.missing");
+ } else if (typeof this.config.ssid !== "string" && !this.config.ssid.hasOwnProperty("entity")) {
+ errors.push("validation.ssid.entity.missing")
}
// Validate password
- if (is_password_protected(this.config.auth_type) && !this.config.password) {
- errors.push("validation.password.missing");
+ if (isPasswordProtected(this.config.auth_type)) {
+ if (!this.config.password) {
+ errors.push("validation.password.missing");
+ } else if (typeof this.config.password !== "string" && !this.config.password.hasOwnProperty("entity")) {
+ errors.push("validation.password.entity.missing")
+ }
}
return errors;
@@ -102,6 +120,7 @@ export function validateConfig(config: QRCodeCardConfig): string[] {
const errors: TranslatableString[] = [];
new SourceValidator(config).validate().forEach(e => errors.push(e));
+ new DebugModeValidator(config).validate().forEach(e => errors.push(e));
if (errors.length == 0) {
const validatorCls = validatorMap.get(config.source);