feat: install extension on insecure connections
Some checks failed
Docker build on tag / build (push) Has been cancelled
Some checks failed
Docker build on tag / build (push) Has been cancelled
This commit is contained in:
parent
424c7c79d7
commit
ff0f6efa29
@ -6,6 +6,10 @@
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.login p,
|
||||
.login a {
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
@ -21,7 +25,7 @@
|
||||
|
||||
.login .logo {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 67px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.login > div:nth-child(1) {
|
||||
@ -73,14 +77,16 @@
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.login {
|
||||
width: unset;
|
||||
height: unset;
|
||||
}
|
||||
|
||||
.login > div:nth-child(2) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.login .login-note {
|
||||
}
|
||||
|
||||
.login .login-actions {
|
||||
margin-top: 32px;
|
||||
}
|
||||
@ -99,20 +105,14 @@
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
margin-top: 56px;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.login .login-or {
|
||||
margin-top: 32px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
margin-top: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.light .login-or {
|
||||
color: #a1a1aa;
|
||||
}
|
||||
|
||||
.login-container input[type="text"] {
|
||||
border: none;
|
||||
background-color: var(--gray-secondary);
|
||||
|
@ -5,14 +5,14 @@ import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import * as secp from "@noble/secp256k1";
|
||||
import { useIntl, FormattedMessage } from "react-intl";
|
||||
import { HexKey } from "@snort/nostr";
|
||||
|
||||
import { RootState } from "State/Store";
|
||||
import { setPrivateKey, setPublicKey, setRelays, setGeneratedPrivateKey } from "State/Login";
|
||||
import { DefaultRelays, EmailRegex, MnemonicRegex } from "Const";
|
||||
import { bech32ToHex, generateBip39Entropy, entropyToDerivedKey, unwrap } from "Util";
|
||||
import { HexKey } from "@snort/nostr";
|
||||
import ZapButton from "Element/ZapButton";
|
||||
// import useImgProxy from "Feed/ImgProxy";
|
||||
import useImgProxy from "Hooks/useImgProxy";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
@ -67,7 +67,9 @@ export default function LoginPage() {
|
||||
const [error, setError] = useState("");
|
||||
const [art, setArt] = useState<ArtworkEntry>();
|
||||
const { formatMessage } = useIntl();
|
||||
//const { proxy } = useImgProxy();
|
||||
const { proxy } = useImgProxy();
|
||||
const hasNip7 = "nostr" in window;
|
||||
const isSecure = window.location.protocol === "https:";
|
||||
|
||||
useEffect(() => {
|
||||
if (publicKey) {
|
||||
@ -77,14 +79,19 @@ export default function LoginPage() {
|
||||
|
||||
useEffect(() => {
|
||||
const ret = unwrap(Artwork.at(Artwork.length * Math.random()));
|
||||
// disable for now because imgproxy is ded
|
||||
// proxy(ret.link).then(a => setArt({ ...ret, link: a }));
|
||||
setArt(ret);
|
||||
proxy(ret.link).then(a => setArt({ ...ret, link: a }));
|
||||
}, []);
|
||||
|
||||
async function doLogin() {
|
||||
const insecureMsg = formatMessage({
|
||||
defaultMessage:
|
||||
"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead",
|
||||
});
|
||||
try {
|
||||
if (key.startsWith("nsec")) {
|
||||
if (!isSecure) {
|
||||
throw new Error(insecureMsg);
|
||||
}
|
||||
const hexKey = bech32ToHex(key);
|
||||
if (secp.utils.isValidPrivateKey(hexKey)) {
|
||||
dispatch(setPrivateKey(hexKey));
|
||||
@ -98,16 +105,30 @@ export default function LoginPage() {
|
||||
const hexKey = await getNip05PubKey(key);
|
||||
dispatch(setPublicKey(hexKey));
|
||||
} else if (key.match(MnemonicRegex)) {
|
||||
if (!isSecure) {
|
||||
throw new Error(insecureMsg);
|
||||
}
|
||||
const ent = generateBip39Entropy(key);
|
||||
const keyHex = entropyToDerivedKey(ent);
|
||||
dispatch(setPrivateKey(keyHex));
|
||||
} else if (secp.utils.isValidPrivateKey(key)) {
|
||||
if (!isSecure) {
|
||||
throw new Error(insecureMsg);
|
||||
}
|
||||
dispatch(setPrivateKey(key));
|
||||
} else {
|
||||
throw new Error("INVALID PRIVATE KEY");
|
||||
}
|
||||
} catch (e) {
|
||||
setError(`Failed to load NIP-05 pub key (${e})`);
|
||||
if (e instanceof Error) {
|
||||
setError(e.message);
|
||||
} else {
|
||||
setError(
|
||||
formatMessage({
|
||||
defaultMessage: "Unknown login error",
|
||||
})
|
||||
);
|
||||
}
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
@ -139,9 +160,8 @@ export default function LoginPage() {
|
||||
}
|
||||
|
||||
function altLogins() {
|
||||
const nip07 = "nostr" in window;
|
||||
if (!nip07) {
|
||||
return null;
|
||||
if (!hasNip7) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -154,6 +174,92 @@ export default function LoginPage() {
|
||||
);
|
||||
}
|
||||
|
||||
function generateKey() {
|
||||
if (!isSecure) return;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex login-or">
|
||||
<FormattedMessage defaultMessage="OR" description="Seperator text for Login / Generate Key" />
|
||||
<div className="divider w-max"></div>
|
||||
</div>
|
||||
<h1 dir="auto">
|
||||
<FormattedMessage defaultMessage="Create an Account" description="Heading for generate key flow" />
|
||||
</h1>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Generate a public / private key pair. Do not share your private key with anyone, this acts as your password. Once lost, it cannot be “reset” or recovered. Keep safe!"
|
||||
description="Note about key security before generating a new key"
|
||||
/>
|
||||
</p>
|
||||
<div className="login-actions">
|
||||
<button type="button" onClick={() => makeRandomKey()}>
|
||||
<FormattedMessage defaultMessage="Generate Key" description="Button: Generate a new key" />
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function installExtension() {
|
||||
if (isSecure) return;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex login-or">
|
||||
<FormattedMessage defaultMessage="OR" description="Seperator text for Login / Generate Key" />
|
||||
<div className="divider w-max"></div>
|
||||
</div>
|
||||
<h1 dir="auto">
|
||||
<FormattedMessage
|
||||
defaultMessage="Install Extension"
|
||||
description="Heading for install key manager extension"
|
||||
/>
|
||||
</h1>
|
||||
<p>
|
||||
<FormattedMessage defaultMessage="Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:" />
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://getalby.com/" target="_blank" rel="noreferrer">
|
||||
Alby
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://chrome.google.com/webstore/detail/nos2x/kpgefcfmnafjgpblomihpgmejjdanjjp"
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
nos2x
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="If you want to try out some others, check out {link} for more!"
|
||||
values={{
|
||||
link: <a href="https://github.com/aljazceru/awesome-nostr#browser-extensions">awesome-nostr</a>,
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage defaultMessage="Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow." />
|
||||
</p>
|
||||
{hasNip7 ? (
|
||||
<div className="login-actions">
|
||||
<button type="button" onClick={() => doNip07Login().then(() => navigate("/new/username"))}>
|
||||
<FormattedMessage defaultMessage="Setup Profile" />
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<b className="error">
|
||||
<FormattedMessage defaultMessage="Hmm, can't find a key manager extension.. try reloading the page." />
|
||||
</b>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="login">
|
||||
<div>
|
||||
@ -183,36 +289,14 @@ export default function LoginPage() {
|
||||
description="Explanation for public key only login is read-only"
|
||||
/>
|
||||
</p>
|
||||
{/* <a href="">
|
||||
<FormattedMessage
|
||||
defaultMessage="Why is there no password field?"
|
||||
description="Link to why your private key is your password"
|
||||
/>
|
||||
</a>*/}
|
||||
<div dir="auto" className="login-actions">
|
||||
<button type="button" onClick={doLogin}>
|
||||
<FormattedMessage defaultMessage="Login" description="Login button" />
|
||||
</button>
|
||||
{altLogins()}
|
||||
</div>
|
||||
<div className="flex login-or">
|
||||
<FormattedMessage defaultMessage="OR" description="Seperator text for Login / Generate Key" />
|
||||
<div className="divider w-max"></div>
|
||||
</div>
|
||||
<h1 dir="auto">
|
||||
<FormattedMessage defaultMessage="Create an Account" description="Heading for generate key flow" />
|
||||
</h1>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Generate a public / private key pair. Do not share your private key with anyone, this acts as your password. Once lost, it cannot be “reset” or recovered. Keep safe!"
|
||||
description="Note about key security before generating a new key"
|
||||
/>
|
||||
</p>
|
||||
<div className="login-actions">
|
||||
<button type="button" onClick={() => makeRandomKey()}>
|
||||
<FormattedMessage defaultMessage="Generate Key" description="Button: Generate a new key" />
|
||||
</button>
|
||||
</div>
|
||||
{generateKey()}
|
||||
{installExtension()}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -118,6 +118,9 @@
|
||||
"4rYCjn": {
|
||||
"defaultMessage": "Note to Self"
|
||||
},
|
||||
"5rOdPG": {
|
||||
"defaultMessage": "Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow."
|
||||
},
|
||||
"5ykRmX": {
|
||||
"defaultMessage": "Send zap"
|
||||
},
|
||||
@ -410,6 +413,9 @@
|
||||
"OKhRC6": {
|
||||
"defaultMessage": "Share"
|
||||
},
|
||||
"OLEm6z": {
|
||||
"defaultMessage": "Unknown login error"
|
||||
},
|
||||
"P61BTu": {
|
||||
"defaultMessage": "Copy Event JSON"
|
||||
},
|
||||
@ -479,6 +485,9 @@
|
||||
"Up5U7K": {
|
||||
"defaultMessage": "Block"
|
||||
},
|
||||
"VBadwB": {
|
||||
"defaultMessage": "Hmm, can't find a key manager extension.. try reloading the page."
|
||||
},
|
||||
"VN0+Fz": {
|
||||
"defaultMessage": "Balance: {amount} sats"
|
||||
},
|
||||
@ -516,6 +525,9 @@
|
||||
"XgWvGA": {
|
||||
"defaultMessage": "Reactions"
|
||||
},
|
||||
"XzF0aC": {
|
||||
"defaultMessage": "Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:"
|
||||
},
|
||||
"Y31HTH": {
|
||||
"defaultMessage": "Help fund the development of Snort"
|
||||
},
|
||||
@ -549,6 +561,10 @@
|
||||
"bxv59V": {
|
||||
"defaultMessage": "Just now"
|
||||
},
|
||||
"c+oiJe": {
|
||||
"defaultMessage": "Install Extension",
|
||||
"description": "Heading for install key manager extension"
|
||||
},
|
||||
"c35bj2": {
|
||||
"defaultMessage": "If you have an enquiry about your NIP-05 order please DM {link}"
|
||||
},
|
||||
@ -687,6 +703,9 @@
|
||||
"kaaf1E": {
|
||||
"defaultMessage": "now"
|
||||
},
|
||||
"lBboHo": {
|
||||
"defaultMessage": "If you want to try out some others, check out {link} for more!"
|
||||
},
|
||||
"lCILNz": {
|
||||
"defaultMessage": "Buy Now"
|
||||
},
|
||||
@ -735,6 +754,9 @@
|
||||
"nN9XTz": {
|
||||
"defaultMessage": "Share your thoughts with {link}"
|
||||
},
|
||||
"nOaArs": {
|
||||
"defaultMessage": "Setup Profile"
|
||||
},
|
||||
"nn1qb3": {
|
||||
"defaultMessage": "Your donations are greatly appreciated"
|
||||
},
|
||||
@ -833,6 +855,9 @@
|
||||
"uSV4Ti": {
|
||||
"defaultMessage": "Reposts need to be manually confirmed"
|
||||
},
|
||||
"ubtr9S": {
|
||||
"defaultMessage": "Can't login with private key on 'http://' connection, please use a Nostr key manager extension instead"
|
||||
},
|
||||
"usAvMr": {
|
||||
"defaultMessage": "Edit Profile"
|
||||
},
|
||||
|
@ -38,6 +38,7 @@
|
||||
"4Vmpt4": "Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices",
|
||||
"4Z3t5i": "Use imgproxy to compress images",
|
||||
"4rYCjn": "Note to Self",
|
||||
"5rOdPG": "Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.",
|
||||
"5ykRmX": "Send zap",
|
||||
"6ewQqw": "Likes ({n})",
|
||||
"6tUqAb": "Generate a public / private key pair. Do not share your private key with anyone, this acts as your password. Once lost, it cannot be “reset” or recovered. Keep safe!",
|
||||
@ -133,6 +134,7 @@
|
||||
"NndBJE": "New users page",
|
||||
"OEW7yJ": "Zaps",
|
||||
"OKhRC6": "Share",
|
||||
"OLEm6z": "Unknown login error",
|
||||
"P61BTu": "Copy Event JSON",
|
||||
"P7FD0F": "System (Default)",
|
||||
"P7nJT9": "Total today (UTC): {amount} sats",
|
||||
@ -155,6 +157,7 @@
|
||||
"TpgeGw": "Hex Salt..",
|
||||
"UQ3pOC": "On Nostr, many people have the same username. User names and identity are separate things. You can get a unique identifier in the next step.",
|
||||
"Up5U7K": "Block",
|
||||
"VBadwB": "Hmm, can't find a key manager extension.. try reloading the page.",
|
||||
"VN0+Fz": "Balance: {amount} sats",
|
||||
"VOjC1i": "Pick which upload service you want to upload attachments to",
|
||||
"VlJkSk": "{n} muted",
|
||||
@ -167,6 +170,7 @@
|
||||
"WxthCV": "e.g. Jack",
|
||||
"X7xU8J": "nsec, npub, nip-05, hex, mnemonic",
|
||||
"XgWvGA": "Reactions",
|
||||
"XzF0aC": "Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:",
|
||||
"Y31HTH": "Help fund the development of Snort",
|
||||
"YDURw6": "Service URL",
|
||||
"YXA3AH": "Enable reactions",
|
||||
@ -178,6 +182,7 @@
|
||||
"aWpBzj": "Show more",
|
||||
"brAXSu": "Pick a username",
|
||||
"bxv59V": "Just now",
|
||||
"c+oiJe": "Install Extension",
|
||||
"c35bj2": "If you have an enquiry about your NIP-05 order please DM {link}",
|
||||
"cPIKU2": "Following",
|
||||
"cQfLWb": "URL..",
|
||||
@ -223,6 +228,7 @@
|
||||
"k2veDA": "Write",
|
||||
"k7sKNy": "Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!",
|
||||
"kaaf1E": "now",
|
||||
"lBboHo": "If you want to try out some others, check out {link} for more!",
|
||||
"lCILNz": "Buy Now",
|
||||
"lD3+8a": "Pay",
|
||||
"lTbT3s": "Wallet password",
|
||||
@ -239,6 +245,7 @@
|
||||
"nDejmx": "Unblock",
|
||||
"nGBrvw": "Bookmarks",
|
||||
"nN9XTz": "Share your thoughts with {link}",
|
||||
"nOaArs": "Setup Profile",
|
||||
"nn1qb3": "Your donations are greatly appreciated",
|
||||
"nwZXeh": "{n} blocked",
|
||||
"o6Uy3d": "Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.",
|
||||
@ -271,6 +278,7 @@
|
||||
"u4bHcR": "Check out the code here: {link}",
|
||||
"uD/N6c": "Zap {target} {n} sats",
|
||||
"uSV4Ti": "Reposts need to be manually confirmed",
|
||||
"ubtr9S": "Can't login with private key on 'http://' connection, please use a Nostr key manager extension instead",
|
||||
"usAvMr": "Edit Profile",
|
||||
"ut+2Cd": "Get a partner identifier",
|
||||
"vOKedj": "{n,plural,=1{& {n} other} other{& {n} others}}",
|
||||
@ -301,4 +309,4 @@
|
||||
"zjJZBd": "You're ready!",
|
||||
"zonsdq": "Failed to load LNURL service",
|
||||
"zvCDao": "Automatically show latest notes"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user