[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-wallet-core] branch master updated: show qr to import TOTP into o
From: |
gnunet |
Subject: |
[taler-wallet-core] branch master updated: show qr to import TOTP into other app |
Date: |
Fri, 23 Jun 2023 15:36:30 +0200 |
This is an automated email from the git hooks/post-receive script.
sebasjm pushed a commit to branch master
in repository wallet-core.
The following commit(s) were added to refs/heads/master by this push:
new 4f30506dc show qr to import TOTP into other app
4f30506dc is described below
commit 4f30506dcacc587586381b1a8fa20c5442784e41
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Jun 23 10:36:24 2023 -0300
show qr to import TOTP into other app
---
.../paths/instance/templates/create/CreatePage.tsx | 117 ++++++++++++--------
.../paths/instance/templates/update/UpdatePage.tsx | 119 +++++++++++++--------
2 files changed, 143 insertions(+), 93 deletions(-)
diff --git
a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
index 137d50b3e..4dde202c4 100644
---
a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
+++
b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
@@ -24,7 +24,7 @@ import {
MerchantTemplateContractDetails,
} from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { h, VNode } from "preact";
+import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
import {
@@ -44,6 +44,8 @@ import {
randomBase32Key,
} from "../../../../utils/crypto.js";
import { undefinedIfEmpty } from "../../../../utils/table.js";
+import { QR } from "../../../../components/exception/QR.js";
+import { useInstanceContext } from "../../../../context/instance.js";
type Entity = MerchantBackend.Template.TemplateAddDetails;
@@ -58,6 +60,8 @@ const algorithmsNames = ["off", "30s 8d TOTP-SHA1", "30s 8d
eTOTP-SHA1"];
export function CreatePage({ onCreate, onBack }: Props): VNode {
const { i18n } = useTranslationContext();
const backend = useBackendContext();
+ const { id: instanceId } = useInstanceContext();
+ const issuer = new URL(backend.url).hostname;
const [showKey, setShowKey] = useState(false);
const [state, setState] = useState<Partial<Entity>>({
@@ -120,6 +124,8 @@ export function CreatePage({ onCreate, onBack }: Props):
VNode {
return onCreate(state as any);
};
+ const qrText =
`otpauth://totp/${instanceId}/${state.template_id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${state.pos_key}`;
+
return (
<div>
<section class="section is-main-section">
@@ -175,54 +181,73 @@ export function CreatePage({ onCreate, onBack }: Props):
VNode {
fromStr={(v) => Number(v)}
/>
{state.pos_algorithm && state.pos_algorithm > 0 ? (
- <InputWithAddon<Entity>
- name="pos_key"
- label={i18n.str`Point-of-sale key`}
- inputType={showKey ? "text" : "password"}
- help="Be sure to be very hard to guess or use the random
generator"
- tooltip={i18n.str`Useful to validate the purchase`}
- fromStr={(v) => v.toUpperCase()}
- addonAfter={
- <span class="icon">
- {showKey ? (
- <i class="mdi mdi-eye" />
- ) : (
- <i class="mdi mdi-eye-off" />
- )}
- </span>
- }
- side={
- <span style={{ display: "flex" }}>
- <button
- data-tooltip={i18n.str`generate random secret key`}
- class="button is-info mr-3"
- onClick={(e) => {
- const pos_key = randomBase32Key();
- setState((s) => ({ ...s, pos_key }));
- }}
- >
- <i18n.Translate>random</i18n.Translate>
- </button>
- <button
- data-tooltip={
- showKey
- ? i18n.str`show secret key`
- : i18n.str`hide secret key`
- }
- class="button is-info mr-3"
- onClick={(e) => {
- setShowKey(!showKey);
- }}
- >
+ <Fragment>
+ <InputWithAddon<Entity>
+ name="pos_key"
+ label={i18n.str`Point-of-sale key`}
+ inputType={showKey ? "text" : "password"}
+ help="Be sure to be very hard to guess or use the random
generator"
+ tooltip={i18n.str`Useful to validate the purchase`}
+ fromStr={(v) => v.toUpperCase()}
+ addonAfter={
+ <span class="icon">
{showKey ? (
- <i18n.Translate>hide</i18n.Translate>
+ <i class="mdi mdi-eye" />
) : (
- <i18n.Translate>show</i18n.Translate>
+ <i class="mdi mdi-eye-off" />
)}
- </button>
- </span>
- }
- />
+ </span>
+ }
+ side={
+ <span style={{ display: "flex" }}>
+ <button
+ data-tooltip={i18n.str`generate random secret key`}
+ class="button is-info mr-3"
+ onClick={(e) => {
+ const pos_key = randomBase32Key();
+ setState((s) => ({ ...s, pos_key }));
+ }}
+ >
+ <i18n.Translate>random</i18n.Translate>
+ </button>
+ <button
+ data-tooltip={
+ showKey
+ ? i18n.str`show secret key`
+ : i18n.str`hide secret key`
+ }
+ class="button is-info mr-3"
+ onClick={(e) => {
+ setShowKey(!showKey);
+ }}
+ >
+ {showKey ? (
+ <i18n.Translate>hide</i18n.Translate>
+ ) : (
+ <i18n.Translate>show</i18n.Translate>
+ )}
+ </button>
+ </span>
+ }
+ />
+ {showKey && (
+ <Fragment>
+ <QR text={qrText} />
+ <div
+ style={{
+ color: "grey",
+ fontSize: "small",
+ width: 200,
+ textAlign: "center",
+ margin: "auto",
+ wordBreak: "break-all",
+ }}
+ >
+ {qrText}
+ </div>
+ </Fragment>
+ )}
+ </Fragment>
) : undefined}
</FormProvider>
diff --git
a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
index 20e40cf9b..30e5502bb 100644
---
a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
+++
b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
@@ -24,7 +24,7 @@ import {
MerchantTemplateContractDetails,
} from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { h, VNode } from "preact";
+import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
import {
@@ -44,6 +44,8 @@ import {
randomBase32Key,
} from "../../../../utils/crypto.js";
import { undefinedIfEmpty } from "../../../../utils/table.js";
+import { QR } from "../../../../components/exception/QR.js";
+import { useInstanceContext } from "../../../../context/instance.js";
type Entity = MerchantBackend.Template.TemplatePatchDetails & WithId;
@@ -59,6 +61,8 @@ const algorithmsNames = ["off", "30s 8d TOTP-SHA1", "30s 8d
eTOTP-SHA1"];
export function UpdatePage({ template, onUpdate, onBack }: Props): VNode {
const { i18n } = useTranslationContext();
const backend = useBackendContext();
+ const { id: instanceId } = useInstanceContext();
+ const issuer = new URL(backend.url).hostname;
const [showKey, setShowKey] = useState(false);
const [state, setState] = useState<Partial<Entity>>(template);
@@ -113,6 +117,8 @@ export function UpdatePage({ template, onUpdate, onBack }:
Props): VNode {
return onUpdate(state as any);
};
+ const qrText =
`otpauth://totp/${instanceId}/${state.id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${state.pos_key}`;
+
return (
<div>
<section class="section">
@@ -185,55 +191,74 @@ export function UpdatePage({ template, onUpdate, onBack
}: Props): VNode {
fromStr={(v) => Number(v)}
/>
{state.pos_algorithm && state.pos_algorithm > 0 ? (
- <InputWithAddon<Entity>
- name="pos_key"
- label={i18n.str`Point-of-sale key`}
- inputType={showKey ? "text" : "password"}
- help="Be sure to be very hard to guess or use the random
generator"
- expand
- tooltip={i18n.str`Useful to validate the purchase`}
- fromStr={(v) => v.toUpperCase()}
- addonAfter={
- <span class="icon">
- {showKey ? (
- <i class="mdi mdi-eye" />
- ) : (
- <i class="mdi mdi-eye-off" />
- )}
- </span>
- }
- side={
- <span style={{ display: "flex" }}>
- <button
- data-tooltip={i18n.str`generate random secret key`}
- class="button is-info mr-3"
- onClick={(e) => {
- const pos_key = randomBase32Key();
- setState((s) => ({ ...s, pos_key }));
- }}
- >
- <i18n.Translate>random</i18n.Translate>
- </button>
- <button
- data-tooltip={
- showKey
- ? i18n.str`show secret key`
- : i18n.str`hide secret key`
- }
- class="button is-info mr-3"
- onClick={(e) => {
- setShowKey(!showKey);
- }}
- >
+ <Fragment>
+ <InputWithAddon<Entity>
+ name="pos_key"
+ label={i18n.str`Point-of-sale key`}
+ inputType={showKey ? "text" : "password"}
+ help="Be sure to be very hard to guess or use the random
generator"
+ expand
+ tooltip={i18n.str`Useful to validate the purchase`}
+ fromStr={(v) => v.toUpperCase()}
+ addonAfter={
+ <span class="icon">
{showKey ? (
- <i18n.Translate>hide</i18n.Translate>
+ <i class="mdi mdi-eye" />
) : (
- <i18n.Translate>show</i18n.Translate>
+ <i class="mdi mdi-eye-off" />
)}
- </button>
- </span>
- }
- />
+ </span>
+ }
+ side={
+ <span style={{ display: "flex" }}>
+ <button
+ data-tooltip={i18n.str`generate random secret key`}
+ class="button is-info mr-3"
+ onClick={(e) => {
+ const pos_key = randomBase32Key();
+ setState((s) => ({ ...s, pos_key }));
+ }}
+ >
+ <i18n.Translate>random</i18n.Translate>
+ </button>
+ <button
+ data-tooltip={
+ showKey
+ ? i18n.str`show secret key`
+ : i18n.str`hide secret key`
+ }
+ class="button is-info mr-3"
+ onClick={(e) => {
+ setShowKey(!showKey);
+ }}
+ >
+ {showKey ? (
+ <i18n.Translate>hide</i18n.Translate>
+ ) : (
+ <i18n.Translate>show</i18n.Translate>
+ )}
+ </button>
+ </span>
+ }
+ />
+ {showKey && (
+ <Fragment>
+ <QR text={qrText} />
+ <div
+ style={{
+ color: "grey",
+ fontSize: "small",
+ width: 200,
+ textAlign: "center",
+ margin: "auto",
+ wordBreak: "break-all",
+ }}
+ >
+ {qrText}
+ </div>
+ </Fragment>
+ )}
+ </Fragment>
) : undefined}
</FormProvider>
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-wallet-core] branch master updated: show qr to import TOTP into other app,
gnunet <=