Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow insecure http for advanced users #74

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ async def get_or_create_lnurlp_settings() -> LnurlpSettings:
if row:
return LnurlpSettings(**row)
else:
settings = LnurlpSettings(nostr_private_key=PrivateKey().hex())
settings = LnurlpSettings(nostr_private_key=PrivateKey().hex(),allow_insecure_http=False)
await db.execute(
insert_query("lnurlp.settings", settings), (*settings.dict().values(),)
)
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"repos": [
{
"id": "lnurlp",
"organisation": "lnbits",
"organisation": "oren-z0",
"repository": "lnurlp"
}
]
Expand Down
10 changes: 10 additions & 0 deletions migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,13 @@ async def m009_add_settings(db):
);
"""
)

async def m010_add_allow_insecure_http_to_settings(db):
"""
Add extension settings table
"""
await db.execute(
"""
ALTER TABLE lnurlp.settings ADD COLUMN allow_insecure_http BOOLEAN;
"""
)
6 changes: 4 additions & 2 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from fastapi import Request
from fastapi.param_functions import Query
from lnurl import encode as lnurl_encode
from lnurl.helpers import url_encode
from lnurl.types import LnurlPayMetadata
from pydantic import BaseModel

Expand All @@ -14,6 +15,7 @@

class LnurlpSettings(BaseModel):
nostr_private_key: str
allow_insecure_http: bool | None

@property
def private_key(self) -> PrivateKey:
Expand Down Expand Up @@ -69,14 +71,14 @@ def from_row(cls, row: Row) -> "PayLink":
data["max"] /= data["fiat_base_multiplier"]
return cls(**data)

def lnurl(self, req: Request) -> str:
def lnurl(self, req: Request, allow_insecure_http = False) -> str:
url = req.url_for("lnurlp.api_lnurl_response", link_id=self.id)
url_str = str(url)
if url.netloc.endswith(".onion"):
# change url string scheme to http
url_str = url_str.replace("https://", "http://")

return lnurl_encode(url_str)
return url_encode(url_str) if allow_insecure_http else lnurl_encode(url_str)

@property
def lnurlpay_metadata(self) -> LnurlPayMetadata:
Expand Down
5 changes: 5 additions & 0 deletions static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ new Vue({
type: 'str',
description: 'Nostr private key used to zap',
name: 'nostr_private_key'
},
{
type: 'bool',
description: 'Allow insecure http: advance usage only, local domain names encoded in lightning-addresses and lnurls may be broken, and communication may be insecure.',
name: 'allow_insecure_http'
}
],
domain: window.location.host,
Expand Down
8 changes: 5 additions & 3 deletions views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from starlette.exceptions import HTTPException
from starlette.responses import HTMLResponse

from .crud import get_pay_link
from .crud import get_pay_link, get_or_create_lnurlp_settings

lnurlp_generic_router = APIRouter()

Expand All @@ -34,7 +34,8 @@ async def display(request: Request, link_id):
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Pay link does not exist."
)
ctx = {"request": request, "lnurl": link.lnurl(req=request)}
settings = await get_or_create_lnurlp_settings()
ctx = {"request": request, "lnurl": link.lnurl(req=request, allow_insecure_http=settings.allow_insecure_http)}
return lnurlp_renderer().TemplateResponse("lnurlp/display.html", ctx)


Expand All @@ -45,5 +46,6 @@ async def print_qr(request: Request, link_id):
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Pay link does not exist."
)
ctx = {"request": request, "lnurl": link.lnurl(req=request)}
settings = await get_or_create_lnurlp_settings()
ctx = {"request": request, "lnurl": link.lnurl(req=request, allow_insecure_http=settings.allow_insecure_http)}
return lnurlp_renderer().TemplateResponse("lnurlp/print_qr.html", ctx)
9 changes: 6 additions & 3 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ async def api_links(
wallet_ids = user.wallet_ids if user else []

try:
settings = await get_or_create_lnurlp_settings()
return [
{**link.dict(), "lnurl": link.lnurl(req)}
{**link.dict(), "lnurl": link.lnurl(req, settings.allow_insecure_http)}
for link in await get_pay_links(wallet_ids)
]

Expand Down Expand Up @@ -87,7 +88,8 @@ async def api_link_retrieve(
detail="Not your pay link.", status_code=HTTPStatus.FORBIDDEN
)

return {**link.dict(), **{"lnurl": link.lnurl(r)}}
settings = await get_or_create_lnurlp_settings()
return {**link.dict(), **{"lnurl": link.lnurl(r, settings.allow_insecure_http)}}


async def check_username_exists(username: str):
Expand Down Expand Up @@ -197,7 +199,8 @@ async def api_link_create_or_update(
link = await create_pay_link(data)

assert link
return {**link.dict(), "lnurl": link.lnurl(request)}
settings = await get_or_create_lnurlp_settings()
return {**link.dict(), "lnurl": link.lnurl(request, settings.allow_insecure_http)}


@lnurlp_api_router.delete("/api/v1/links/{link_id}", status_code=HTTPStatus.OK)
Expand Down
12 changes: 9 additions & 3 deletions views_lnurl.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from lnurl import LnurlErrorResponse, LnurlPayActionResponse, LnurlPayResponse
from lnurl.models import MessageAction, UrlAction
from lnurl.types import (
Url,
ClearnetUrl,
DebugUrl,
LightningInvoice,
Expand All @@ -22,6 +23,10 @@
increment_pay_link,
)

class InsecureClearnetUrl(Url):
tld_required = False
allowed_schemes = {"http", "https"}

lnurlp_lnurl_router = APIRouter()


Expand Down Expand Up @@ -110,8 +115,9 @@ async def api_lnurl_callback(

action: Optional[Union[MessageAction, UrlAction]] = None
if link.success_url:
settings = await get_or_create_lnurlp_settings()
url = parse_obj_as(
Union[DebugUrl, OnionUrl, ClearnetUrl], # type: ignore
Union[DebugUrl, OnionUrl, ClearnetUrl, InsecureClearnetUrl] if settings.allow_insecure_http else Union[DebugUrl, OnionUrl, ClearnetUrl], # type: ignore
str(link.success_url),
)
desc = parse_obj_as(Max144Str, link.success_text)
Expand Down Expand Up @@ -150,8 +156,9 @@ async def api_lnurl_response(
url = url.include_query_params(webhook_data=webhook_data)

link.domain = request.url.netloc
settings = await get_or_create_lnurlp_settings()
callback_url = parse_obj_as(
Union[DebugUrl, OnionUrl, ClearnetUrl], # type: ignore
Union[DebugUrl, OnionUrl, ClearnetUrl, InsecureClearnetUrl] if settings.allow_insecure_http else Union[DebugUrl, OnionUrl, ClearnetUrl], # type: ignore
str(url),
)

Expand All @@ -167,7 +174,6 @@ async def api_lnurl_response(
params["commentAllowed"] = link.comment_chars

if link.zaps:
settings = await get_or_create_lnurlp_settings()
params["allowsNostr"] = True
params["nostrPubkey"] = settings.public_key
return params
Expand Down