Add DELETE for names and PUT for name transfer
This commit is contained in:
parent
43151f36b6
commit
b42621cb23
107
src/index.js
107
src/index.js
|
@ -781,15 +781,6 @@ app.post(NAME_PATH, async (req, res) => {
|
|||
return;
|
||||
}
|
||||
|
||||
const { type } = nip19.decode(npub);
|
||||
if (type !== "npub") {
|
||||
console.log("bad npub", npub);
|
||||
res.status(400).send({
|
||||
error: "Bad npub",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const minPow = getMinPow(name, req);
|
||||
|
||||
if (!(await verifyAuthNostr(req, npub, NAME_PATH, minPow))) {
|
||||
|
@ -876,6 +867,104 @@ app.get(NAME_PATH, async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
app.delete(NAME_PATH, async (req, res) => {
|
||||
try {
|
||||
const { npub, name } = req.body;
|
||||
|
||||
if (!(await verifyAuthNostr(req, npub, NAME_PATH))) {
|
||||
console.log("auth failed", npub);
|
||||
res.status(403).send({
|
||||
error: `Bad auth`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const deletedName = await prisma.names.delete({
|
||||
where: {
|
||||
npub,
|
||||
name,
|
||||
},
|
||||
});
|
||||
console.log({ deletedName });
|
||||
} catch (e) {
|
||||
console.log("Failed to delete name", name, npub);
|
||||
res.status(404).send({
|
||||
error: "Name not found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// reply ok
|
||||
res.status(200).send({
|
||||
ok: true,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(new Date(), "error req from ", req.ip, e.toString());
|
||||
res.status(500).send({
|
||||
error: "Internal error",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.put(NAME_PATH, async (req, res) => {
|
||||
try {
|
||||
const { npub, name, newNpub } = req.body;
|
||||
|
||||
if (!(await verifyAuthNostr(req, npub, NAME_PATH))) {
|
||||
console.log("auth failed", npub);
|
||||
res.status(403).send({
|
||||
error: `Bad auth`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const deletedName = await prisma.names.delete({
|
||||
where: {
|
||||
npub,
|
||||
name,
|
||||
},
|
||||
});
|
||||
console.log({ deletedName });
|
||||
} catch (e) {
|
||||
console.log("Failed to delete name", name, npub);
|
||||
res.status(404).send({
|
||||
error: "Name not found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const dbr = await prisma.names.create({
|
||||
data: {
|
||||
npub: newNpub,
|
||||
name,
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
});
|
||||
console.log({ dbr });
|
||||
} catch (e) {
|
||||
res.status(400).send({
|
||||
error: "Name taken",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// reply ok
|
||||
res.status(201).send({
|
||||
ok: true,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
console.log(new Date(), "error req from ", req.ip, e.toString());
|
||||
res.status(500).send({
|
||||
error: "Internal error",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const JSON_PATH = "/.well-known/nostr.json";
|
||||
app.get(JSON_PATH, async (req, res) => {
|
||||
try {
|
||||
|
|
157
src/test.js
157
src/test.js
|
@ -15,10 +15,10 @@ const ndk = new NDK({
|
|||
explicitRelayUrls: ["wss://relay.nsec.app"],
|
||||
});
|
||||
|
||||
const LOCAL = false;
|
||||
const LOCAL = true;
|
||||
const BUNKER_PUBKEY = LOCAL
|
||||
? "44f9def756f8575aed604408a5c8f5a09d01633015fc65894fdd12af77457f3a"
|
||||
: "e24a86943d37a91ab485d6f9a7c66097c25ddd67e8bd1b75ed252a3c266cf9bb"
|
||||
: "e24a86943d37a91ab485d6f9a7c66097c25ddd67e8bd1b75ed252a3c266cf9bb";
|
||||
|
||||
const sk = generatePrivateKey();
|
||||
console.log("test pubkey", getPublicKey(sk));
|
||||
|
@ -33,32 +33,69 @@ async function sendPost({ url, method, headers, body }) {
|
|||
const r = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
"Content-Type": "application/json",
|
||||
...headers,
|
||||
},
|
||||
body,
|
||||
})
|
||||
});
|
||||
if (r.status !== 200 && r.status !== 201) {
|
||||
console.log('Fetch error', url, method, r.status)
|
||||
const body = await r.json()
|
||||
throw new Error('Failed to fetch ' + url, { cause: body })
|
||||
console.log("Fetch error", url, method, r.status);
|
||||
const body = await r.json();
|
||||
throw new Error("Failed to fetch " + url, { cause: body });
|
||||
}
|
||||
|
||||
return await r.json()
|
||||
return await r.json();
|
||||
}
|
||||
|
||||
async function sha256(data) {
|
||||
return createHash('sha256').update(data, 'utf8').digest().toString('hex')
|
||||
function sha256(data) {
|
||||
return createHash("sha256").update(data, "utf8").digest().toString("hex");
|
||||
}
|
||||
|
||||
function countLeadingZeros(hex) {
|
||||
let count = 0
|
||||
|
||||
for (let i = 0; i < hex.length; i++) {
|
||||
const nibble = parseInt(hex[i], 16)
|
||||
if (nibble === 0) {
|
||||
count += 4
|
||||
} else {
|
||||
count += Math.clz32(nibble) - 28
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
function minePow(e, target) {
|
||||
let ctr = 0
|
||||
|
||||
let nonceTagIdx = e.tags.findIndex((a) => a[0] === 'nonce')
|
||||
if (nonceTagIdx === -1) {
|
||||
nonceTagIdx = e.tags.length
|
||||
e.tags.push(['nonce', ctr.toString(), target.toString()])
|
||||
}
|
||||
do {
|
||||
e.tags[nonceTagIdx][1] = (++ctr).toString()
|
||||
e.id = createId(e)
|
||||
} while (countLeadingZeros(e.id) < target)
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
function createId(e) {
|
||||
const payload = [0, e.pubkey, e.created_at, e.kind, e.tags, e.content]
|
||||
return sha256(JSON.stringify(payload))
|
||||
}
|
||||
|
||||
async function sendPostAuthd({
|
||||
sk,
|
||||
url,
|
||||
method = 'GET',
|
||||
body = ''
|
||||
body = '',
|
||||
pow = 0,
|
||||
}) {
|
||||
|
||||
const pubkey = getPublicKey(sk)
|
||||
const pubkey = getPublicKey(sk);
|
||||
const signer = new NDKPrivateKeySigner(sk);
|
||||
|
||||
const authEvent = new NDKEvent(ndk, {
|
||||
|
@ -73,9 +110,20 @@ async function sendPostAuthd({
|
|||
})
|
||||
if (body) authEvent.tags.push(['payload', await sha256(body)])
|
||||
|
||||
authEvent.sig = await authEvent.sign(signer)
|
||||
// generate pow on auth evevnt
|
||||
if (pow) {
|
||||
const start = Date.now()
|
||||
const powEvent = authEvent.rawEvent()
|
||||
const minedEvent = minePow(powEvent, pow)
|
||||
console.log('mined pow of', pow, 'in', Date.now() - start, 'ms', minedEvent)
|
||||
authEvent.tags = minedEvent.tags
|
||||
}
|
||||
|
||||
const auth = Buffer.from(JSON.stringify(authEvent.rawEvent())).toString('base64')
|
||||
authEvent.sig = await authEvent.sign(signer);
|
||||
|
||||
const auth = Buffer.from(JSON.stringify(authEvent.rawEvent())).toString(
|
||||
"base64"
|
||||
);
|
||||
|
||||
return await sendPost({
|
||||
url,
|
||||
|
@ -87,39 +135,96 @@ async function sendPostAuthd({
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
// OAuth flow
|
||||
signer.on("authUrl", async (url) => {
|
||||
console.log("nostr login auth url", url);
|
||||
const u = new URL(url);
|
||||
const token = u.searchParams.get('token');
|
||||
const token = u.searchParams.get("token");
|
||||
console.log({ token });
|
||||
const sk = generatePrivateKey();
|
||||
console.log("created account", getPublicKey(sk));
|
||||
await sendPostAuthd({
|
||||
sk,
|
||||
method: 'POST',
|
||||
url: LOCAL ? 'http://localhost:8000/created' : 'https://noauthd.nsec.app/created',
|
||||
method: "POST",
|
||||
url: LOCAL
|
||||
? "http://localhost:8000/created"
|
||||
: "https://noauthd.nsec.app/created",
|
||||
body: JSON.stringify({
|
||||
npub: nip19.npubEncode(getPublicKey(sk)),
|
||||
token,
|
||||
})
|
||||
})
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
const params = [
|
||||
if (process.argv.length >= 3) {
|
||||
if (process.argv[2] === "check_names") {
|
||||
const sk = generatePrivateKey();
|
||||
const npub = nip19.npubEncode(getPublicKey(sk))
|
||||
const sk1 = generatePrivateKey();
|
||||
const npub1 = nip19.npubEncode(getPublicKey(sk1))
|
||||
const name = npub.substring(0, 10);
|
||||
console.log("create name", npub, name);
|
||||
const test = async () => {
|
||||
await sendPostAuthd({
|
||||
sk,
|
||||
method: "POST",
|
||||
url: LOCAL
|
||||
? "http://localhost:8000/name"
|
||||
: "https://noauthd.nsec.app/name",
|
||||
body: JSON.stringify({
|
||||
npub,
|
||||
name,
|
||||
}),
|
||||
pow: 15
|
||||
});
|
||||
console.log("created");
|
||||
await sendPostAuthd({
|
||||
sk,
|
||||
method: "PUT",
|
||||
url: LOCAL
|
||||
? "http://localhost:8000/name"
|
||||
: "https://noauthd.nsec.app/name",
|
||||
body: JSON.stringify({
|
||||
npub,
|
||||
name: name,
|
||||
newNpub: npub1
|
||||
}),
|
||||
});
|
||||
console.log("transferred")
|
||||
await sendPostAuthd({
|
||||
sk: sk1,
|
||||
method: "DELETE",
|
||||
url: LOCAL
|
||||
? "http://localhost:8000/name"
|
||||
: "https://noauthd.nsec.app/name",
|
||||
body: JSON.stringify({
|
||||
npub: npub1,
|
||||
name: name,
|
||||
}),
|
||||
});
|
||||
console.log("deleted");
|
||||
}
|
||||
test()
|
||||
}
|
||||
} else {
|
||||
const params = [
|
||||
"test",
|
||||
"nsec.app",
|
||||
// email?
|
||||
];
|
||||
ndk
|
||||
];
|
||||
ndk
|
||||
.connect()
|
||||
.then(async () => {
|
||||
console.log("sending", params);
|
||||
signer.rpc.sendRequest(
|
||||
BUNKER_PUBKEY, "create_account", params, undefined,
|
||||
BUNKER_PUBKEY,
|
||||
"create_account",
|
||||
params,
|
||||
undefined,
|
||||
(res) => {
|
||||
console.log({ res });
|
||||
});
|
||||
}
|
||||
);
|
||||
})
|
||||
.then(console.log);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user