chore: update github workflows

This commit is contained in:
Eneko Illarramendi 2020-09-03 23:02:15 +02:00
parent a651f747ac
commit 23cfe0d417
23 changed files with 199 additions and 91 deletions

1
.gitattributes vendored
View File

@ -1 +0,0 @@
**/static/vendor/** linguist-vendored

View File

@ -1,54 +1,28 @@
name: "CodeQL" name: codeql
on: on:
push: push:
branches: [master, ] branches: [master, ]
pull_request: pull_request:
# The branches below must be a subset of the branches above
branches: [master] branches: [master]
schedule: schedule:
- cron: '0 12 * * 5' - cron: '0 12 * * 5'
jobs: jobs:
CodeQL-Build: analyze:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
# We must fetch at least the immediate parents so that if this is fetch-depth: 2
# a pull request then we can checkout the head. - run: git checkout HEAD^2
fetch-depth: 2 if: ${{ github.event_name == 'pull_request' }}
- name: Initialize CodeQL
# If this run was triggered by a pull request event, then checkout uses: github/codeql-action/init@v1
# the head of the pull request instead of the merge commit. with:
- run: git checkout HEAD^2 languages: javascript, python
if: ${{ github.event_name == 'pull_request' }} - name: Autobuild
uses: github/codeql-action/autobuild@v1
# Initializes the CodeQL tools for scanning. - name: Perform CodeQL Analysis
- name: Initialize CodeQL uses: github/codeql-action/analyze@v1
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -1,4 +1,4 @@
name: Linters name: formatting
on: on:
push: push:
@ -21,13 +21,3 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: npm install - run: npm install
- run: make checkprettier - run: make checkprettier
mypy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: sudo apt-get install python3-venv
- run: sudo apt-get install libev-dev
- run: python3 -m venv venv
- run: ./venv/bin/pip install -r requirements.txt
- run: ./venv/bin/pip install mypy
- run: make mypy

12
.github/workflows/mypy.yml vendored Normal file
View File

@ -0,0 +1,12 @@
name: mypy
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: jpetrucciani/mypy-check@master
with:
path: lnbits

View File

@ -1,15 +1,13 @@
name: test suite name: tests
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: [3.8] python-version: [3.8]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}

View File

@ -1,7 +1,8 @@
LNbits LNbits
====== ======
[![github-actions-badge]][github-actions] [![github-tests-badge]][github-tests]
[![github-mypy-badge]][github-mypy]
[![codecov-badge]][codecov] [![codecov-badge]][codecov]
[![license-badge]](LICENSE) [![license-badge]](LICENSE)
[![docs-badge]][docs] [![docs-badge]][docs]
@ -70,8 +71,10 @@ If you like this project and might even use or extend it, why not [send some tip
[docs]: https://lnbits.org/ [docs]: https://lnbits.org/
[docs-badge]: https://img.shields.io/badge/docs-lnbits.org-673ab7.svg [docs-badge]: https://img.shields.io/badge/docs-lnbits.org-673ab7.svg
[github-actions]: https://github.com/lnbits/lnbits/actions [github-mypy]: https://github.com/lnbits/lnbits/actions?query=workflow%3Amypy
[github-actions-badge]: https://github.com/lnbits/lnbits/workflows/test%20suite/badge.svg [github-mypy-badge]: https://github.com/lnbits/lnbits/workflows/mypy/badge.svg
[github-tests]: https://github.com/lnbits/lnbits/actions?query=workflow%3Atests
[github-tests-badge]: https://github.com/lnbits/lnbits/workflows/tests/badge.svg
[codecov]: https://codecov.io/gh/lnbits/lnbits [codecov]: https://codecov.io/gh/lnbits/lnbits
[codecov-badge]: https://codecov.io/gh/lnbits/lnbits/branch/master/graph/badge.svg [codecov-badge]: https://codecov.io/gh/lnbits/lnbits/branch/master/graph/badge.svg
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg [license-badge]: https://img.shields.io/badge/license-MIT-blue.svg

View File

@ -29,7 +29,13 @@ Talisman(
app, app,
force_https=FORCE_HTTPS, force_https=FORCE_HTTPS,
content_security_policy={ content_security_policy={
"default-src": ["'self'", "'unsafe-eval'", "'unsafe-inline'", "blob:", "api.opennode.co",] "default-src": [
"'self'",
"'unsafe-eval'",
"'unsafe-inline'",
"blob:",
"api.opennode.co",
]
}, },
) )

View File

@ -2,7 +2,7 @@ import bitstring # type: ignore
import re import re
import hashlib import hashlib
from typing import List, NamedTuple, Optional from typing import List, NamedTuple, Optional
from bech32 import bech32_decode, CHARSET from bech32 import bech32_decode, CHARSET # type: ignore
from ecdsa import SECP256k1, VerifyingKey # type: ignore from ecdsa import SECP256k1, VerifyingKey # type: ignore
from ecdsa.util import sigdecode_string # type: ignore from ecdsa.util import sigdecode_string # type: ignore
from binascii import unhexlify from binascii import unhexlify
@ -115,8 +115,7 @@ def decode(pr: str) -> Invoice:
def _unshorten_amount(amount: str) -> int: def _unshorten_amount(amount: str) -> int:
""" Given a shortened amount, return millisatoshis """Given a shortened amount, return millisatoshis"""
"""
# BOLT #11: # BOLT #11:
# The following `multiplier` letters are defined: # The following `multiplier` letters are defined:
# #

View File

@ -268,7 +268,13 @@ def create_payment(
def update_payment_status(checking_id: str, pending: bool) -> None: def update_payment_status(checking_id: str, pending: bool) -> None:
with open_db() as db: with open_db() as db:
db.execute("UPDATE apipayments SET pending = ? WHERE checking_id = ?", (int(pending), checking_id,)) db.execute(
"UPDATE apipayments SET pending = ? WHERE checking_id = ?",
(
int(pending),
checking_id,
),
)
def delete_payment(checking_id: str) -> None: def delete_payment(checking_id: str) -> None:

View File

@ -9,7 +9,12 @@ from .crud import get_wallet, create_payment, delete_payment, check_internal, up
def create_invoice( def create_invoice(
*, wallet_id: str, amount: int, memo: str, description_hash: Optional[bytes] = None, extra: Optional[Dict] = None, *,
wallet_id: str,
amount: int,
memo: str,
description_hash: Optional[bytes] = None,
extra: Optional[Dict] = None,
) -> Tuple[str, str]: ) -> Tuple[str, str]:
invoice_memo = None if description_hash else memo invoice_memo = None if description_hash else memo
storeable_memo = memo storeable_memo = memo

View File

@ -16,7 +16,10 @@ def api_check_wallet_key(key_type: str = "invoice"):
try: try:
g.wallet = get_wallet_for_key(request.headers["X-Api-Key"], key_type) g.wallet = get_wallet_for_key(request.headers["X-Api-Key"], key_type)
except KeyError: except KeyError:
return jsonify({"message": "`X-Api-Key` header missing."}), HTTPStatus.BAD_REQUEST return (
jsonify({"message": "`X-Api-Key` header missing."}),
HTTPStatus.BAD_REQUEST,
)
if not g.wallet: if not g.wallet:
return jsonify({"message": "Wrong keys."}), HTTPStatus.UNAUTHORIZED return jsonify({"message": "Wrong keys."}), HTTPStatus.UNAUTHORIZED
@ -33,13 +36,19 @@ def api_validate_post_request(*, schema: dict):
@wraps(view) @wraps(view)
def wrapped_view(**kwargs): def wrapped_view(**kwargs):
if "application/json" not in request.headers["Content-Type"]: if "application/json" not in request.headers["Content-Type"]:
return jsonify({"message": "Content-Type must be `application/json`."}), HTTPStatus.BAD_REQUEST return (
jsonify({"message": "Content-Type must be `application/json`."}),
HTTPStatus.BAD_REQUEST,
)
v = Validator(schema) v = Validator(schema)
g.data = {key: request.json[key] for key in schema.keys() if key in request.json} g.data = {key: request.json[key] for key in schema.keys() if key in request.json}
if not v.validate(g.data): if not v.validate(g.data):
return jsonify({"message": f"Errors in request data: {v.errors}"}), HTTPStatus.BAD_REQUEST return (
jsonify({"message": f"Errors in request data: {v.errors}"}),
HTTPStatus.BAD_REQUEST,
)
return view(**kwargs) return view(**kwargs)

View File

@ -125,10 +125,22 @@ def get_diagonalleys_indexer(indexer_id: str) -> Optional[Indexers]:
print(x) print(x)
print("poo") print("poo")
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
db.execute("UPDATE indexers SET online = ? WHERE id = ?", (True, indexer_id,)) db.execute(
"UPDATE indexers SET online = ? WHERE id = ?",
(
True,
indexer_id,
),
)
else: else:
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
db.execute("UPDATE indexers SET online = ? WHERE id = ?", (False, indexer_id,)) db.execute(
"UPDATE indexers SET online = ? WHERE id = ?",
(
False,
indexer_id,
),
)
except: except:
print("An exception occurred") print("An exception occurred")
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
@ -149,10 +161,22 @@ def get_diagonalleys_indexers(wallet_ids: Union[str, List[str]]) -> List[Indexer
x = requests.get(r["indexeraddress"] + "/" + r["ratingkey"]) x = requests.get(r["indexeraddress"] + "/" + r["ratingkey"])
if x.status_code == 200: if x.status_code == 200:
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
db.execute("UPDATE indexers SET online = ? WHERE id = ?", (True, r["id"],)) db.execute(
"UPDATE indexers SET online = ? WHERE id = ?",
(
True,
r["id"],
),
)
else: else:
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
db.execute("UPDATE indexers SET online = ? WHERE id = ?", (False, r["id"],)) db.execute(
"UPDATE indexers SET online = ? WHERE id = ?",
(
False,
r["id"],
),
)
except: except:
print("An exception occurred") print("An exception occurred")
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
@ -213,7 +237,13 @@ def get_diagonalleys_orders(wallet_ids: Union[str, List[str]]) -> List[Orders]:
PAID = WALLET.get_invoice_status(r["invoiceid"]).paid PAID = WALLET.get_invoice_status(r["invoiceid"]).paid
if PAID: if PAID:
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
db.execute("UPDATE orders SET paid = ? WHERE id = ?", (True, r["id"],)) db.execute(
"UPDATE orders SET paid = ? WHERE id = ?",
(
True,
r["id"],
),
)
rows = db.fetchall(f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,)) rows = db.fetchall(f"SELECT * FROM orders WHERE wallet IN ({q})", (*wallet_ids,))
return [Orders(**row) for row in rows] return [Orders(**row) for row in rows]

View File

@ -198,7 +198,13 @@ def api_diagonalley_order_delete(order_id):
@api_check_wallet_key(key_type="invoice") @api_check_wallet_key(key_type="invoice")
def api_diagonalleys_order_paid(order_id): def api_diagonalleys_order_paid(order_id):
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
db.execute("UPDATE orders SET paid = ? WHERE id = ?", (True, order_id,)) db.execute(
"UPDATE orders SET paid = ? WHERE id = ?",
(
True,
order_id,
),
)
return "", HTTPStatus.OK return "", HTTPStatus.OK
@ -206,7 +212,13 @@ def api_diagonalleys_order_paid(order_id):
@api_check_wallet_key(key_type="invoice") @api_check_wallet_key(key_type="invoice")
def api_diagonalleys_order_shipped(order_id): def api_diagonalleys_order_shipped(order_id):
with open_ext_db("diagonalley") as db: with open_ext_db("diagonalley") as db:
db.execute("UPDATE orders SET shipped = ? WHERE id = ?", (True, order_id,)) db.execute(
"UPDATE orders SET shipped = ? WHERE id = ?",
(
True,
order_id,
),
)
order = db.fetchone("SELECT * FROM orders WHERE id = ?", (order_id,)) order = db.fetchone("SELECT * FROM orders WHERE id = ?", (order_id,))
return jsonify([order._asdict() for order in get_diagonalleys_orders(order["wallet"])]), HTTPStatus.OK return jsonify([order._asdict() for order in get_diagonalleys_orders(order["wallet"])]), HTTPStatus.OK

View File

@ -75,7 +75,15 @@ def m002_changed(db):
) )
VALUES (?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?)
""", """,
(row[0], row[1], row[2], row[3], row[4], row[5], True,), (
row[0],
row[1],
row[2],
row[3],
row[4],
row[5],
True,
),
) )
db.execute("DROP TABLE tickets") db.execute("DROP TABLE tickets")

View File

@ -18,9 +18,21 @@ from lnbits.extensions.example import example_ext
def api_example(): def api_example():
"""Try to add descriptions for others.""" """Try to add descriptions for others."""
tools = [ tools = [
{"name": "Flask", "url": "https://flask.palletsprojects.com/", "language": "Python",}, {
{"name": "Vue.js", "url": "https://vuejs.org/", "language": "JavaScript",}, "name": "Flask",
{"name": "Quasar Framework", "url": "https://quasar.dev/", "language": "JavaScript",}, "url": "https://flask.palletsprojects.com/",
"language": "Python",
},
{
"name": "Vue.js",
"url": "https://vuejs.org/",
"language": "JavaScript",
},
{
"name": "Quasar Framework",
"url": "https://quasar.dev/",
"language": "JavaScript",
},
] ]
return jsonify(tools), HTTPStatus.OK return jsonify(tools), HTTPStatus.OK

View File

@ -74,7 +74,16 @@ def m002_changed(db):
) )
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""", """,
(row[0], row[1], row[2], row[3], row[4], row[5], row[6], True,), (
row[0],
row[1],
row[2],
row[3],
row[4],
row[5],
row[6],
True,
),
) )
db.execute("DROP TABLE tickets") db.execute("DROP TABLE tickets")

View File

@ -106,7 +106,10 @@ def api_lnurl_response(link_id):
url = url_for("lnurlp.api_lnurl_callback", link_id=link.id, _external=True, _scheme=scheme) url = url_for("lnurlp.api_lnurl_callback", link_id=link.id, _external=True, _scheme=scheme)
resp = LnurlPayResponse( resp = LnurlPayResponse(
callback=url, min_sendable=link.amount * 1000, max_sendable=link.amount * 1000, metadata=link.lnurlpay_metadata, callback=url,
min_sendable=link.amount * 1000,
max_sendable=link.amount * 1000,
metadata=link.lnurlpay_metadata,
) )
return jsonify(resp.dict()), HTTPStatus.OK return jsonify(resp.dict()), HTTPStatus.OK

View File

@ -22,7 +22,11 @@ class LNbitsWallet(Wallet):
else: else:
data["memo"] = memo or "" data["memo"] = memo or ""
r = post(url=f"{self.endpoint}/api/v1/payments", headers=self.auth_invoice, json=data,) r = post(
url=f"{self.endpoint}/api/v1/payments",
headers=self.auth_invoice,
json=data,
)
ok, checking_id, payment_request, error_message = r.ok, None, None, None ok, checking_id, payment_request, error_message = r.ok, None, None, None
if r.ok: if r.ok:

View File

@ -55,7 +55,9 @@ class LndWallet(Wallet):
grpc_port=self.port, grpc_port=self.port,
) )
payinvoice = lnd_rpc.pay_invoice(payment_request=bolt11,) payinvoice = lnd_rpc.pay_invoice(
payment_request=bolt11,
)
ok, checking_id, fee_msat, error_message = True, None, 0, None ok, checking_id, fee_msat, error_message = True, None, 0, None

View File

@ -30,7 +30,12 @@ class LndRestWallet(Wallet):
else: else:
data["memo"] = memo or "" data["memo"] = memo or ""
r = post(url=f"{self.endpoint}/v1/invoices", headers=self.auth_invoice, verify=self.auth_cert, json=data,) r = post(
url=f"{self.endpoint}/v1/invoices",
headers=self.auth_invoice,
verify=self.auth_cert,
json=data,
)
ok, checking_id, payment_request, error_message = r.ok, None, None, None ok, checking_id, payment_request, error_message = r.ok, None, None, None
@ -38,7 +43,11 @@ class LndRestWallet(Wallet):
data = r.json() data = r.json()
payment_request = data["payment_request"] payment_request = data["payment_request"]
r = get(url=f"{self.endpoint}/v1/payreq/{payment_request}", headers=self.auth_read, verify=self.auth_cert,) r = get(
url=f"{self.endpoint}/v1/payreq/{payment_request}",
headers=self.auth_read,
verify=self.auth_cert,
)
print(r) print(r)
if r.ok: if r.ok:
checking_id = r.json()["payment_hash"].replace("/", "_") checking_id = r.json()["payment_hash"].replace("/", "_")
@ -56,7 +65,11 @@ class LndRestWallet(Wallet):
json={"payment_request": bolt11}, json={"payment_request": bolt11},
) )
ok, checking_id, fee_msat, error_message = r.ok, None, 0, None ok, checking_id, fee_msat, error_message = r.ok, None, 0, None
r = get(url=f"{self.endpoint}/v1/payreq/{bolt11}", headers=self.auth_admin, verify=self.auth_cert,) r = get(
url=f"{self.endpoint}/v1/payreq/{bolt11}",
headers=self.auth_admin,
verify=self.auth_cert,
)
if r.ok: if r.ok:
checking_id = r.json()["payment_hash"] checking_id = r.json()["payment_hash"]
@ -68,7 +81,11 @@ class LndRestWallet(Wallet):
def get_invoice_status(self, checking_id: str) -> PaymentStatus: def get_invoice_status(self, checking_id: str) -> PaymentStatus:
checking_id = checking_id.replace("_", "/") checking_id = checking_id.replace("_", "/")
print(checking_id) print(checking_id)
r = get(url=f"{self.endpoint}/v1/invoice/{checking_id}", headers=self.auth_invoice, verify=self.auth_cert,) r = get(
url=f"{self.endpoint}/v1/invoice/{checking_id}",
headers=self.auth_invoice,
verify=self.auth_cert,
)
print(r.json()["settled"]) print(r.json()["settled"])
if not r or r.json()["settled"] == False: if not r or r.json()["settled"] == False:
return PaymentStatus(None) return PaymentStatus(None)

View File

@ -25,7 +25,11 @@ class LNPayWallet(Wallet):
else: else:
data["memo"] = memo or "" data["memo"] = memo or ""
r = post(url=f"{self.endpoint}/user/wallet/{self.auth_invoice}/invoice", headers=self.auth_api, json=data,) r = post(
url=f"{self.endpoint}/user/wallet/{self.auth_invoice}/invoice",
headers=self.auth_api,
json=data,
)
ok, checking_id, payment_request, error_message = r.status_code == 201, None, None, r.text ok, checking_id, payment_request, error_message = r.status_code == 201, None, None, r.text
if ok: if ok:

View File

@ -23,7 +23,11 @@ class LntxbotWallet(Wallet):
else: else:
data["memo"] = memo or "" data["memo"] = memo or ""
r = post(url=f"{self.endpoint}/addinvoice", headers=self.auth_invoice, json=data,) r = post(
url=f"{self.endpoint}/addinvoice",
headers=self.auth_invoice,
json=data,
)
ok, checking_id, payment_request, error_message = r.ok, None, None, None ok, checking_id, payment_request, error_message = r.ok, None, None, None
if r.ok: if r.ok:

View File

@ -48,7 +48,9 @@ class SparkWallet(Wallet):
try: try:
if description_hash: if description_hash:
r = self.invoicewithdescriptionhash( r = self.invoicewithdescriptionhash(
msatoshi=amount * 1000, label=label, description_hash=description_hash.hex(), msatoshi=amount * 1000,
label=label,
description_hash=description_hash.hex(),
) )
else: else:
r = self.invoice( r = self.invoice(