more cleaning up

This commit is contained in:
Jack 2016-09-21 21:36:06 -04:00
parent aecafbbebd
commit 4d79a7828c
7 changed files with 276 additions and 222 deletions

View file

@ -45,9 +45,6 @@ KNOWN_DHT_NODES = [('104.236.42.182', 4000),
POINTTRADER_SERVER = 'http://ec2-54-187-192-68.us-west-2.compute.amazonaws.com:2424' POINTTRADER_SERVER = 'http://ec2-54-187-192-68.us-west-2.compute.amazonaws.com:2424'
#POINTTRADER_SERVER = 'http://127.0.0.1:2424' #POINTTRADER_SERVER = 'http://127.0.0.1:2424'
if IS_DEVELOPMENT_VERSION:
SEARCH_SERVERS = ["http://107.170.207.64:50005"]
else:
SEARCH_SERVERS = ["http://lighthouse1.lbry.io:50005", SEARCH_SERVERS = ["http://lighthouse1.lbry.io:50005",
"http://lighthouse2.lbry.io:50005", "http://lighthouse2.lbry.io:50005",
"http://lighthouse3.lbry.io:50005"] "http://lighthouse3.lbry.io:50005"]
@ -67,6 +64,9 @@ if os.name == "nt":
else: else:
ICON_PATH = "app.icns" ICON_PATH = "app.icns"
APP_NAME = "LBRY" APP_NAME = "LBRY"
ORIGIN = "http://%s:%i" % (API_INTERFACE, API_PORT)
REFERER = "http://%s:%i/" % (API_INTERFACE, API_PORT)
API_CONNECTION_STRING = "http://%s:%i/%s" % (API_INTERFACE, API_PORT, API_ADDRESS) API_CONNECTION_STRING = "http://%s:%i/%s" % (API_INTERFACE, API_PORT, API_ADDRESS)
UI_ADDRESS = "http://%s:%i" % (API_INTERFACE, API_PORT) UI_ADDRESS = "http://%s:%i" % (API_INTERFACE, API_PORT)
PROTOCOL_PREFIX = "lbry" PROTOCOL_PREFIX = "lbry"
@ -88,11 +88,6 @@ CURRENCIES = {
'USD': {'type': 'fiat'}, 'USD': {'type': 'fiat'},
} }
ALLOWED_DURING_STARTUP = ['is_running', 'is_first_run',
'get_time_behind_blockchain', 'stop',
'daemon_status', 'get_start_notice',
'version', 'get_search_servers']
LOGGLY_TOKEN = 'LJEzATH4AzRgAwxjAP00LwZ2YGx3MwVgZTMuBQZ3MQuxLmOv' LOGGLY_TOKEN = 'LJEzATH4AzRgAwxjAP00LwZ2YGx3MwVgZTMuBQZ3MQuxLmOv'
ANALYTICS_ENDPOINT = 'https://api.segment.io/v1' ANALYTICS_ENDPOINT = 'https://api.segment.io/v1'

View file

@ -94,3 +94,6 @@ class InvalidHeaderError(Exception):
class InvalidAuthenticationToken(Exception): class InvalidAuthenticationToken(Exception):
pass pass
class SubhandlerError(Exception):
pass

View file

@ -40,7 +40,8 @@ from lbrynet.lbrynet_daemon.LBRYDownloader import GetStream
from lbrynet.lbrynet_daemon.LBRYPublisher import Publisher from lbrynet.lbrynet_daemon.LBRYPublisher import Publisher
from lbrynet.lbrynet_daemon.LBRYExchangeRateManager import ExchangeRateManager from lbrynet.lbrynet_daemon.LBRYExchangeRateManager import ExchangeRateManager
from lbrynet.lbrynet_daemon.Lighthouse import LighthouseClient from lbrynet.lbrynet_daemon.Lighthouse import LighthouseClient
from lbrynet.lbrynet_daemon.auth.server import LBRYJSONRPCServer, auth_required, authorizer from lbrynet.lbrynet_daemon.auth.server import AuthJSONRPCServer
from lbrynet.lbrynet_daemon.auth.util import get_auth_message
from lbrynet.metadata.LBRYMetadata import Metadata, verify_name_characters from lbrynet.metadata.LBRYMetadata import Metadata, verify_name_characters
from lbrynet.core import log_support from lbrynet.core import log_support
from lbrynet.core import utils from lbrynet.core import utils
@ -49,7 +50,7 @@ from lbrynet.lbrynet_console.LBRYSettings import LBRYSettings
from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE, DEFAULT_MAX_SEARCH_RESULTS, \ from lbrynet.conf import MIN_BLOB_DATA_PAYMENT_RATE, DEFAULT_MAX_SEARCH_RESULTS, \
KNOWN_DHT_NODES, DEFAULT_MAX_KEY_FEE, DEFAULT_WALLET, \ KNOWN_DHT_NODES, DEFAULT_MAX_KEY_FEE, DEFAULT_WALLET, \
DEFAULT_SEARCH_TIMEOUT, DEFAULT_CACHE_TIME, DEFAULT_UI_BRANCH, \ DEFAULT_SEARCH_TIMEOUT, DEFAULT_CACHE_TIME, DEFAULT_UI_BRANCH, \
LOG_POST_URL, LOG_FILE_NAME, REFLECTOR_SERVERS, SEARCH_SERVERS, ALLOWED_DURING_STARTUP LOG_POST_URL, LOG_FILE_NAME, REFLECTOR_SERVERS, SEARCH_SERVERS
from lbrynet.conf import DEFAULT_SD_DOWNLOAD_TIMEOUT from lbrynet.conf import DEFAULT_SD_DOWNLOAD_TIMEOUT
from lbrynet.conf import DEFAULT_TIMEOUT from lbrynet.conf import DEFAULT_TIMEOUT
from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob, BlobStreamDescriptorReader from lbrynet.core.StreamDescriptor import StreamDescriptorIdentifier, download_sd_blob, BlobStreamDescriptorReader
@ -122,10 +123,8 @@ BAD_REQUEST = 400
NOT_FOUND = 404 NOT_FOUND = 404
OK_CODE = 200 OK_CODE = 200
# TODO add login credentials in a conf file
# TODO alert if your copy of a lbry file is out of date with the name record # TODO alert if your copy of a lbry file is out of date with the name record
REMOTE_SERVER = "www.google.com" REMOTE_SERVER = "www.google.com"
@ -134,14 +133,17 @@ class Parameters(object):
self.__dict__.update(kwargs) self.__dict__.update(kwargs)
@authorizer class LBRYDaemon(AuthJSONRPCServer):
class LBRYDaemon(LBRYJSONRPCServer):
""" """
LBRYnet daemon, a jsonrpc interface to lbry functions LBRYnet daemon, a jsonrpc interface to lbry functions
""" """
def __init__(self, root, wallet_type=None): def __init__(self, root, wallet_type=None):
LBRYJSONRPCServer.__init__(self) AuthJSONRPCServer.__init__(self)
self.allowed_during_startup = ['is_running', 'is_first_run',
'get_time_behind_blockchain', 'stop',
'daemon_status', 'get_start_notice',
'version', 'get_search_servers']
reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown) reactor.addSystemEventTrigger('before', 'shutdown', self._shutdown)
self.startup_status = STARTUP_STAGES[0] self.startup_status = STARTUP_STAGES[0]
@ -392,6 +394,17 @@ class LBRYDaemon(LBRYJSONRPCServer):
f.write("rpcpassword=" + password) f.write("rpcpassword=" + password)
log.info("Done writing lbrycrd.conf") log.info("Done writing lbrycrd.conf")
@AuthJSONRPCServer.subhandler
def _exclude_lbrycrd_only_commands_from_lbryum_session(self, request):
request.content.seek(0, 0)
content = request.content.read()
parsed = jsonrpclib.loads(content)
function_path = parsed.get("method")
if self.wallet_type == "lbryum" and function_path in ['set_miner', 'get_miner_status']:
log.warning("Mining commands are not available in lbryum")
raise Exception("Command not available in lbryum")
return True
def setup(self, branch=DEFAULT_UI_BRANCH, user_specified=False, branch_specified=False, host_ui=True): def setup(self, branch=DEFAULT_UI_BRANCH, user_specified=False, branch_specified=False, host_ui=True):
def _log_starting_vals(): def _log_starting_vals():
log.info("Starting balance: " + str(self.session.wallet.wallet_balance)) log.info("Starting balance: " + str(self.session.wallet.wallet_balance))
@ -1337,7 +1350,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
def _search(self, search): def _search(self, search):
return self.lighthouse_client.search(search) return self.lighthouse_client.search(search)
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_is_running(self): def jsonrpc_is_running(self):
""" """
Check if lbrynet daemon is running Check if lbrynet daemon is running
@ -1354,7 +1367,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
else: else:
return self._render_response(False, OK_CODE) return self._render_response(False, OK_CODE)
@auth_required
def jsonrpc_daemon_status(self): def jsonrpc_daemon_status(self):
""" """
Get lbrynet daemon status information Get lbrynet daemon status information
@ -1386,10 +1398,8 @@ class LBRYDaemon(LBRYJSONRPCServer):
else: else:
r['message'] = "Catching up with the blockchain" r['message'] = "Catching up with the blockchain"
r['progress'] = 0 r['progress'] = 0
log.info("daemon status: " + str(r))
return self._render_response(r, OK_CODE) return self._render_response(r, OK_CODE)
@auth_required
def jsonrpc_is_first_run(self): def jsonrpc_is_first_run(self):
""" """
Check if this is the first time lbrynet daemon has been run Check if this is the first time lbrynet daemon has been run
@ -1410,7 +1420,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required
def jsonrpc_get_start_notice(self): def jsonrpc_get_start_notice(self):
""" """
Get special message to be displayed at startup Get special message to be displayed at startup
@ -1430,7 +1439,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
else: else:
self._render_response(self.startup_message, OK_CODE) self._render_response(self.startup_message, OK_CODE)
@auth_required
def jsonrpc_version(self): def jsonrpc_version(self):
""" """
Get lbry version information Get lbry version information
@ -1465,7 +1473,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
log.info("Get version info: " + json.dumps(msg)) log.info("Get version info: " + json.dumps(msg))
return self._render_response(msg, OK_CODE) return self._render_response(msg, OK_CODE)
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_settings(self): def jsonrpc_get_settings(self):
""" """
Get lbrynet daemon settings Get lbrynet daemon settings
@ -1494,7 +1502,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
log.info("Get daemon settings") log.info("Get daemon settings")
return self._render_response(self.session_settings, OK_CODE) return self._render_response(self.session_settings, OK_CODE)
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_set_settings(self, p): def jsonrpc_set_settings(self, p):
""" """
Set lbrynet daemon settings Set lbrynet daemon settings
@ -1522,7 +1530,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required
def jsonrpc_help(self, p=None): def jsonrpc_help(self, p=None):
""" """
Function to retrieve docstring for API function Function to retrieve docstring for API function
@ -1537,17 +1544,17 @@ class LBRYDaemon(LBRYJSONRPCServer):
""" """
if not p: if not p:
return self._render_response(self._listFunctions(), OK_CODE) return self._render_response(self.callable_methods.keys(), OK_CODE)
elif 'callable_during_start' in p.keys(): elif 'callable_during_start' in p.keys():
return self._render_response(ALLOWED_DURING_STARTUP, OK_CODE) return self._render_response(self.allowed_during_startup, OK_CODE)
elif 'function' in p.keys(): elif 'function' in p.keys():
func_path = p['function'] func_path = p['function']
function = self._getFunction(func_path) function = self.callable_methods.get(func_path)
return self._render_response(function.__doc__, OK_CODE) return self._render_response(function.__doc__, OK_CODE)
else: else:
return self._render_response(self.jsonrpc_help.__doc__, OK_CODE) return self._render_response(self.jsonrpc_help.__doc__, OK_CODE)
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_balance(self): def jsonrpc_get_balance(self):
""" """
Get balance Get balance
@ -1561,7 +1568,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
log.info("Get balance") log.info("Get balance")
return self._render_response(float(self.session.wallet.wallet_balance), OK_CODE) return self._render_response(float(self.session.wallet.wallet_balance), OK_CODE)
@auth_required
def jsonrpc_stop(self): def jsonrpc_stop(self):
""" """
Stop lbrynet-daemon Stop lbrynet-daemon
@ -1581,7 +1587,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return self._render_response("Shutting down", OK_CODE) return self._render_response("Shutting down", OK_CODE)
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_lbry_files(self): def jsonrpc_get_lbry_files(self):
""" """
Get LBRY files Get LBRY files
@ -1608,7 +1614,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_lbry_file(self, p): def jsonrpc_get_lbry_file(self, p):
""" """
Get lbry file Get lbry file
@ -1638,7 +1644,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required
def jsonrpc_resolve_name(self, p): def jsonrpc_resolve_name(self, p):
""" """
Resolve stream info from a LBRY uri Resolve stream info from a LBRY uri
@ -1660,7 +1665,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallbacks(lambda info: self._render_response(info, OK_CODE), lambda _: server.failure) d.addCallbacks(lambda info: self._render_response(info, OK_CODE), lambda _: server.failure)
return d return d
@auth_required
def jsonrpc_get_claim_info(self, p): def jsonrpc_get_claim_info(self, p):
""" """
Resolve claim info from a LBRY uri Resolve claim info from a LBRY uri
@ -1685,7 +1689,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def _process_get_parameters(self, p): def _process_get_parameters(self, p):
"""Extract info from input parameters and fill in default values for `get` call.""" """Extract info from input parameters and fill in default values for `get` call."""
# TODO: this process can be abstracted s.t. each method # TODO: this process can be abstracted s.t. each method
@ -1707,7 +1711,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
name=name name=name
) )
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get(self, p): def jsonrpc_get(self, p):
"""Download stream from a LBRY uri. """Download stream from a LBRY uri.
@ -1738,7 +1742,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda message: self._render_response(message, OK_CODE)) d.addCallback(lambda message: self._render_response(message, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_stop_lbry_file(self, p): def jsonrpc_stop_lbry_file(self, p):
""" """
Stop lbry file Stop lbry file
@ -1764,7 +1768,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_start_lbry_file(self, p): def jsonrpc_start_lbry_file(self, p):
""" """
Stop lbry file Stop lbry file
@ -1789,7 +1793,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required
def jsonrpc_get_est_cost(self, p): def jsonrpc_get_est_cost(self, p):
""" """
Get estimated cost for a lbry uri Get estimated cost for a lbry uri
@ -1811,7 +1814,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_search_nametrie(self, p): def jsonrpc_search_nametrie(self, p):
""" """
Search the nametrie for claims Search the nametrie for claims
@ -1848,7 +1851,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_delete_lbry_file(self, p): def jsonrpc_delete_lbry_file(self, p):
""" """
Delete a lbry file Delete a lbry file
@ -1878,7 +1881,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_publish(self, p): def jsonrpc_publish(self, p):
""" """
Make a new name claim and publish associated data to lbrynet Make a new name claim and publish associated data to lbrynet
@ -1955,7 +1958,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_abandon_claim(self, p): def jsonrpc_abandon_claim(self, p):
""" """
Abandon a name and reclaim credits from the claim Abandon a name and reclaim credits from the claim
@ -1982,7 +1985,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_abandon_name(self, p): def jsonrpc_abandon_name(self, p):
""" """
DEPRECIATED, use abandon_claim DEPRECIATED, use abandon_claim
@ -1995,7 +1998,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return self.jsonrpc_abandon_claim(p) return self.jsonrpc_abandon_claim(p)
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_support_claim(self, p): def jsonrpc_support_claim(self, p):
""" """
Support a name claim Support a name claim
@ -2015,7 +2018,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_name_claims(self): def jsonrpc_get_name_claims(self):
""" """
Get my name claims Get my name claims
@ -2039,7 +2042,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required
def jsonrpc_get_claims_for_name(self, p): def jsonrpc_get_claims_for_name(self, p):
""" """
Get claims for a name Get claims for a name
@ -2055,7 +2057,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_transaction_history(self): def jsonrpc_get_transaction_history(self):
""" """
Get transaction history Get transaction history
@ -2070,7 +2072,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required
def jsonrpc_get_transaction(self, p): def jsonrpc_get_transaction(self, p):
""" """
Get a decoded transaction from a txid Get a decoded transaction from a txid
@ -2087,7 +2088,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_address_is_mine(self, p): def jsonrpc_address_is_mine(self, p):
""" """
Checks if an address is associated with the current wallet. Checks if an address is associated with the current wallet.
@ -2105,7 +2106,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_public_key_from_wallet(self, p): def jsonrpc_get_public_key_from_wallet(self, p):
""" """
Get public key from wallet address Get public key from wallet address
@ -2120,7 +2121,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d = self.session.wallet.get_pub_keys(wallet) d = self.session.wallet.get_pub_keys(wallet)
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
@auth_required
def jsonrpc_get_time_behind_blockchain(self): def jsonrpc_get_time_behind_blockchain(self):
""" """
Get number of blocks behind the blockchain Get number of blocks behind the blockchain
@ -2144,7 +2144,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_new_address(self): def jsonrpc_get_new_address(self):
""" """
Generate a new wallet address Generate a new wallet address
@ -2164,7 +2164,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda address: self._render_response(address, OK_CODE)) d.addCallback(lambda address: self._render_response(address, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_send_amount_to_address(self, p): def jsonrpc_send_amount_to_address(self, p):
""" """
Send credits to an address Send credits to an address
@ -2189,7 +2189,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda _: self._render_response(True, OK_CODE)) d.addCallback(lambda _: self._render_response(True, OK_CODE))
return d return d
@auth_required
def jsonrpc_get_best_blockhash(self): def jsonrpc_get_best_blockhash(self):
""" """
Get hash of most recent block Get hash of most recent block
@ -2204,7 +2203,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required
def jsonrpc_get_block(self, p): def jsonrpc_get_block(self, p):
""" """
Get contents of a block Get contents of a block
@ -2227,7 +2225,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required
def jsonrpc_get_claims_for_tx(self, p): def jsonrpc_get_claims_for_tx(self, p):
""" """
Get claims for tx Get claims for tx
@ -2247,7 +2244,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_download_descriptor(self, p): def jsonrpc_download_descriptor(self, p):
""" """
Download and return a sd blob Download and return a sd blob
@ -2264,7 +2261,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallbacks(lambda r: self._render_response(r, OK_CODE), lambda _: self._render_response(False, OK_CODE)) d.addCallbacks(lambda r: self._render_response(r, OK_CODE), lambda _: self._render_response(False, OK_CODE))
return d return d
@auth_required
def jsonrpc_get_nametrie(self): def jsonrpc_get_nametrie(self):
""" """
Get the nametrie Get the nametrie
@ -2280,7 +2276,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_set_miner(self, p): def jsonrpc_set_miner(self, p):
""" """
Start of stop the miner, function only available when lbrycrd is set as the wallet Start of stop the miner, function only available when lbrycrd is set as the wallet
@ -2300,7 +2296,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_miner_status(self): def jsonrpc_get_miner_status(self):
""" """
Get status of miner Get status of miner
@ -2315,7 +2311,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required
def jsonrpc_log(self, p): def jsonrpc_log(self, p):
""" """
Log message Log message
@ -2330,7 +2325,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
log.info("API client log request: %s" % message) log.info("API client log request: %s" % message)
return self._render_response(True, OK_CODE) return self._render_response(True, OK_CODE)
@auth_required
def jsonrpc_upload_log(self, p=None): def jsonrpc_upload_log(self, p=None):
""" """
Upload log Upload log
@ -2372,7 +2366,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda _: self._render_response(True, OK_CODE)) d.addCallback(lambda _: self._render_response(True, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_configure_ui(self, p): def jsonrpc_configure_ui(self, p):
""" """
Configure the UI being hosted Configure the UI being hosted
@ -2397,7 +2391,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_reveal(self, p): def jsonrpc_reveal(self, p):
""" """
Reveal a file or directory in file browser Reveal a file or directory in file browser
@ -2417,7 +2411,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda _: self._render_response(True, OK_CODE)) d.addCallback(lambda _: self._render_response(True, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_peers_for_hash(self, p): def jsonrpc_get_peers_for_hash(self, p):
""" """
Get peers for blob hash Get peers for blob hash
@ -2435,7 +2429,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_announce_all_blobs_to_dht(self): def jsonrpc_announce_all_blobs_to_dht(self):
""" """
Announce all blobs to the dht Announce all blobs to the dht
@ -2450,7 +2444,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda _: self._render_response("Announced", OK_CODE)) d.addCallback(lambda _: self._render_response("Announced", OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_reflect(self, p): def jsonrpc_reflect(self, p):
""" """
Reflect a stream Reflect a stream
@ -2467,7 +2461,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallbacks(lambda _: self._render_response(True, OK_CODE), lambda err: self._render_response(err.getTraceback(), OK_CODE)) d.addCallbacks(lambda _: self._render_response(True, OK_CODE), lambda err: self._render_response(err.getTraceback(), OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_get_blob_hashes(self): def jsonrpc_get_blob_hashes(self):
""" """
Returns all blob hashes Returns all blob hashes
@ -2482,7 +2476,7 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required @AuthJSONRPCServer.auth_required
def jsonrpc_reflect_all_blobs(self): def jsonrpc_reflect_all_blobs(self):
""" """
Reflects all saved blobs Reflects all saved blobs
@ -2498,20 +2492,6 @@ class LBRYDaemon(LBRYJSONRPCServer):
d.addCallback(lambda r: self._render_response(r, OK_CODE)) d.addCallback(lambda r: self._render_response(r, OK_CODE))
return d return d
@auth_required
def jsonrpc_get_search_servers(self):
"""
Get list of lighthouse servers
Args:
None
Returns:
List of address:port
"""
d = self._render_response(SEARCH_SERVERS, OK_CODE)
return d
def get_lbrynet_version_from_github(): def get_lbrynet_version_from_github():
"""Return the latest released version from github.""" """Return the latest released version from github."""

View file

@ -14,7 +14,7 @@ class HttpPasswordRealm(object):
self.resource = resource self.resource = resource
def requestAvatar(self, avatarId, mind, *interfaces): def requestAvatar(self, avatarId, mind, *interfaces):
log.info("Processing request for %s", avatarId) log.debug("Processing request for %s", avatarId)
if resource.IResource in interfaces: if resource.IResource in interfaces:
return (resource.IResource, self.resource, lambda: None) return (resource.IResource, self.resource, lambda: None)
raise NotImplementedError() raise NotImplementedError()

View file

@ -5,7 +5,7 @@ import os
import base64 import base64
import json import json
from lbrynet.lbrynet_daemon.auth.util import load_api_keys, APIKey, API_KEY_NAME from lbrynet.lbrynet_daemon.auth.util import load_api_keys, APIKey, API_KEY_NAME, get_auth_message
from lbrynet.conf import API_INTERFACE, API_ADDRESS, API_PORT from lbrynet.conf import API_INTERFACE, API_ADDRESS, API_PORT
from lbrynet.conf import DATA_DIR from lbrynet.conf import DATA_DIR
@ -55,8 +55,8 @@ class LBRYAPIClient(object):
'method': self.__service_name, 'method': self.__service_name,
'params': args, 'params': args,
'id': self.__id_count} 'id': self.__id_count}
to_auth = str(pre_auth_postdata['method']).encode('hex') + str(pre_auth_postdata['id']).encode('hex') to_auth = get_auth_message(pre_auth_postdata)
token = self.__api_key.get_hmac(to_auth.decode('hex')) token = self.__api_key.get_hmac(to_auth)
pre_auth_postdata.update({'hmac': token}) pre_auth_postdata.update({'hmac': token})
postdata = json.dumps(pre_auth_postdata) postdata = json.dumps(pre_auth_postdata)
service_url = self.__service_url service_url = self.__service_url
@ -79,16 +79,13 @@ class LBRYAPIClient(object):
next_secret = headers.get(LBRY_SECRET, False) next_secret = headers.get(LBRY_SECRET, False)
if next_secret: if next_secret:
# print "Next secret: %s" % next_secret
self.__api_key.secret = next_secret self.__api_key.secret = next_secret
self.__cookies = cookies self.__cookies = cookies
# print "Postdata: %s" % postdata
if http_response is None: if http_response is None:
raise JSONRPCException({ raise JSONRPCException({
'code': -342, 'message': 'missing HTTP response from server'}) 'code': -342, 'message': 'missing HTTP response from server'})
# print "-----\n%s\n------" % http_response.text
http_response.raise_for_status() http_response.raise_for_status()
response = http_response.json() response = http_response.json()
@ -104,20 +101,18 @@ class LBRYAPIClient(object):
@classmethod @classmethod
def config(cls, key_name=None, key=None, pw_path=None, timeout=HTTP_TIMEOUT, connection=None, count=0, def config(cls, key_name=None, key=None, pw_path=None, timeout=HTTP_TIMEOUT, connection=None, count=0,
service=None, cookies=None, auth=None, url=None, login_url=None): service=None, cookies=None, auth=None, url=None, login_url=None):
api_key_name = API_KEY_NAME if not key_name else key_name api_key_name = API_KEY_NAME if not key_name else key_name
pw_path = os.path.join(DATA_DIR, ".api_keys") if not pw_path else pw_path pw_path = os.path.join(DATA_DIR, ".api_keys") if not pw_path else pw_path
if not key: if not key:
keys = load_api_keys(pw_path) keys = load_api_keys(pw_path)
api_key = keys.get(api_key_name, False) api_key = keys.get(api_key_name, False)
else: else:
api_key = APIKey(name=api_key_name, secret=key) api_key = APIKey(name=api_key_name, secret=key)
if login_url is None: if login_url is None:
service_url = "http://%s:%s@%s:%i/%s" % (api_key_name, api_key.secret, API_INTERFACE, API_PORT, API_ADDRESS) service_url = "http://%s:%s@%s:%i/%s" % (api_key_name, api_key.secret, API_INTERFACE, API_PORT, API_ADDRESS)
else: else:
service_url = login_url service_url = login_url
id_count = count id_count = count
if auth is None and connection is None and cookies is None and url is None: if auth is None and connection is None and cookies is None and url is None:
@ -134,10 +129,8 @@ class LBRYAPIClient(object):
pass pass
authpair = user + b':' + passwd authpair = user + b':' + passwd
auth_header = b'Basic ' + base64.b64encode(authpair) auth_header = b'Basic ' + base64.b64encode(authpair)
conn = requests.Session() conn = requests.Session()
conn.auth = (user, passwd) conn.auth = (user, passwd)
req = requests.Request(method='POST', req = requests.Request(method='POST',
url=service_url, url=service_url,
auth=conn.auth, auth=conn.auth,
@ -148,11 +141,9 @@ class LBRYAPIClient(object):
r = req.prepare() r = req.prepare()
http_response = conn.send(r) http_response = conn.send(r)
cookies = http_response.cookies cookies = http_response.cookies
# print "Logged in"
uid = cookies.get(TWISTED_SESSION) uid = cookies.get(TWISTED_SESSION)
api_key = APIKey.new(seed=uid) api_key = APIKey.new(seed=uid)
# print "Created temporary api key"
else: else:
# This is a client that already has a session, use it # This is a client that already has a session, use it
auth_header = auth auth_header = auth

View file

@ -1,16 +1,15 @@
import logging import logging
from decimal import Decimal from decimal import Decimal
from twisted.web import server from zope.interface import implements
from twisted.web import server, resource
from twisted.internet import defer from twisted.internet import defer
from txjsonrpc import jsonrpclib from txjsonrpc import jsonrpclib
from txjsonrpc.web import jsonrpc
from txjsonrpc.web.jsonrpc import Handler
from lbrynet.core.Error import InvalidAuthenticationToken, InvalidHeaderError from lbrynet.core.Error import InvalidAuthenticationToken, InvalidHeaderError, SubhandlerError
from lbrynet.lbrynet_daemon.auth.util import APIKey from lbrynet.conf import API_INTERFACE, REFERER, ORIGIN
from lbrynet.lbrynet_daemon.auth.util import APIKey, get_auth_message
from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET from lbrynet.lbrynet_daemon.auth.client import LBRY_SECRET
from lbrynet.conf import ALLOWED_DURING_STARTUP
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -20,42 +19,166 @@ def default_decimal(obj):
return float(obj) return float(obj)
def authorizer(cls): class AuthorizedBase(object):
cls.authorized_functions = [] def __init__(self):
for methodname in dir(cls): self.authorized_functions = []
self.subhandlers = []
self.callable_methods = {}
for methodname in dir(self):
if methodname.startswith("jsonrpc_"): if methodname.startswith("jsonrpc_"):
method = getattr(cls, methodname) method = getattr(self, methodname)
self.callable_methods.update({methodname.split("jsonrpc_")[1]: method})
if hasattr(method, '_auth_required'): if hasattr(method, '_auth_required'):
cls.authorized_functions.append(methodname.split("jsonrpc_")[1]) self.authorized_functions.append(methodname.split("jsonrpc_")[1])
return cls elif not methodname.startswith("__"):
method = getattr(self, methodname)
if hasattr(method, '_subhandler'):
self.subhandlers.append(method)
@staticmethod
def auth_required(f): def auth_required(f):
f._auth_required = True f._auth_required = True
return f return f
@staticmethod
def subhandler(f):
f._subhandler = True
return f
@authorizer
class LBRYJSONRPCServer(jsonrpc.JSONRPC): class AuthJSONRPCServer(AuthorizedBase):
"""
Authorized JSONRPC server used as the base class for the LBRY API
API methods are named with a leading "jsonrpc_"
Decorators:
@AuthJSONRPCServer.auth_required: this requires the client include a valid hmac authentication token in their
request
@AuthJSONRPCServer.subhandler: include the tagged method in the processing of requests, to allow inheriting
classes to modify request handling. Tagged methods will be passed the request
object, and return True when finished to indicate success
Attributes:
allowed_during_startup (list): list of api methods that are callable before the server has finished
startup
sessions (dict): dictionary of active session_id: lbrynet.lbrynet_daemon.auth.util.APIKey values
authorized_functions (list): list of api methods that require authentication
subhandlers (list): list of subhandlers
callable_methods (dict): dictionary of api_callable_name: method values
"""
implements(resource.IResource)
isLeaf = True isLeaf = True
OK = 200
UNAUTHORIZED = 401
NOT_FOUND = 8001
FAILURE = 8002
def __init__(self): def __init__(self):
jsonrpc.JSONRPC.__init__(self) AuthorizedBase.__init__(self)
self.allowed_during_startup = []
self.sessions = {} self.sessions = {}
def setup(self):
return NotImplementedError()
def render(self, request):
assert self._check_headers(request), InvalidHeaderError
session = request.getSession()
session_id = session.uid
# if this is a new session, send a new secret and set the expiration, otherwise, session.touch()
if self._initialize_session(session_id):
def expire_session():
self._unregister_user_session(session_id)
session.startCheckingExpiration()
session.notifyOnExpire(expire_session)
message = "OK"
request.setResponseCode(self.OK)
self._set_headers(request, message, True)
self._render_message(request, message)
return server.NOT_DONE_YET
session.touch()
request.content.seek(0, 0)
content = request.content.read()
try:
parsed = jsonrpclib.loads(content)
except ValueError:
return server.failure
function_name = parsed.get('method')
args = parsed.get('params')
id = parsed.get('id')
token = parsed.pop('hmac', None)
version = self._get_jsonrpc_version(parsed.get('jsonrpc'), id)
try:
self._run_subhandlers(request)
except SubhandlerError:
return server.failure
reply_with_next_secret = False
if function_name in self.authorized_functions:
try:
self._verify_token(session_id, parsed, token)
except InvalidAuthenticationToken:
log.warning("API validation failed")
request.setResponseCode(self.UNAUTHORIZED)
request.finish()
return server.NOT_DONE_YET
self._update_session_secret(session_id)
reply_with_next_secret = True
try:
function = self._get_jsonrpc_method(function_name)
except Exception:
log.warning("Unknown method: %s", function_name)
return server.failure
d = defer.maybeDeferred(function) if args == [{}] else defer.maybeDeferred(function, *args)
# cancel the response if the connection is broken
notify_finish = request.notifyFinish()
notify_finish.addErrback(self._response_failed, d)
d.addErrback(self._errback_render, id)
d.addCallback(self._callback_render, request, id, version, reply_with_next_secret)
d.addErrback(notify_finish.errback)
return server.NOT_DONE_YET
def _register_user_session(self, session_id): def _register_user_session(self, session_id):
"""
Add or update a HMAC secret for a session
@param session_id:
@return: secret
"""
token = APIKey.new() token = APIKey.new()
self.sessions.update({session_id: token}) self.sessions.update({session_id: token})
return token return token
def _responseFailed(self, err, call): def _unregister_user_session(self, session_id):
log.info("Unregister API session")
del self.sessions[session_id]
def _response_failed(self, err, call):
log.debug(err.getTraceback()) log.debug(err.getTraceback())
def _set_headers(self, request, data): def _set_headers(self, request, data, update_secret=False):
request.setHeader("Access-Control-Allow-Origin", "localhost") request.setHeader("Access-Control-Allow-Origin", API_INTERFACE)
request.setHeader("Content-Type", "text/json") request.setHeader("Content-Type", "text/json")
request.setHeader("Content-Length", str(len(data))) request.setHeader("Content-Length", str(len(data)))
if update_secret:
session_id = request.getSession().uid
request.setHeader(LBRY_SECRET, self.sessions.get(session_id).secret)
def _render_message(self, request, message): def _render_message(self, request, message):
request.write(message) request.write(message)
@ -64,112 +187,81 @@ class LBRYJSONRPCServer(jsonrpc.JSONRPC):
def _check_headers(self, request): def _check_headers(self, request):
origin = request.getHeader("Origin") origin = request.getHeader("Origin")
referer = request.getHeader("Referer") referer = request.getHeader("Referer")
if origin not in [None, ORIGIN]:
if origin not in [None, 'http://localhost:5279']:
log.warning("Attempted api call from %s", origin) log.warning("Attempted api call from %s", origin)
raise InvalidHeaderError return False
if referer is not None and not referer.startswith(REFERER):
if referer is not None and not referer.startswith('http://localhost:5279/'):
log.warning("Attempted api call from %s", referer) log.warning("Attempted api call from %s", referer)
raise InvalidHeaderError return False
return True
def _handle(self, request): def _check_function_path(self, function_path):
def _check_function_path(function_path): if function_path not in self.callable_methods:
log.warning("Unknown method: %s", function_path)
return False
if not self.announced_startup: if not self.announced_startup:
if function_path not in ALLOWED_DURING_STARTUP: if function_path not in self.allowed_during_startup:
log.warning("Cannot call %s during startup", function_path) log.warning("Cannot call %s during startup", function_path)
raise Exception("Function not allowed") return False
return True
def _get_function(function_path): def _get_jsonrpc_method(self, function_path):
function = self._getFunction(function_path) assert self._check_function_path(function_path)
return function return self.callable_methods.get(function_path)
def _verify_token(session_id, message, token): def _initialize_session(self, session_id):
request.setHeader(LBRY_SECRET, "") if not self.sessions.get(session_id, False):
api_key = self.sessions.get(session_id, None) log.info("Initializing new api session")
assert api_key is not None, InvalidAuthenticationToken self.sessions.update({session_id: APIKey.new(seed=session_id, name=session_id)})
r = api_key.compare_hmac(message, token) return True
assert r, InvalidAuthenticationToken return False
def _verify_token(self, session_id, message, token):
to_auth = get_auth_message(message)
api_key = self.sessions.get(session_id)
assert api_key.compare_hmac(to_auth, token), InvalidAuthenticationToken
def _update_session_secret(self, session_id):
# log.info("Generating new token for next request") # log.info("Generating new token for next request")
self.sessions.update({session_id: APIKey.new(name=session_id)}) self.sessions.update({session_id: APIKey.new(name=session_id)})
request.setHeader(LBRY_SECRET, self.sessions.get(session_id).secret)
session = request.getSession()
session_id = session.uid
session_store = self.sessions.get(session_id, False)
if not session_store:
token = APIKey.new(seed=session_id, name=session_id)
log.info("Initializing new api session")
self.sessions.update({session_id: token})
# log.info("Generated token %s", str(self.sessions[session_id]))
request.content.seek(0, 0)
content = request.content.read()
parsed = jsonrpclib.loads(content)
functionPath = parsed.get("method")
_check_function_path(functionPath)
require_auth = functionPath in self.authorized_functions
if require_auth:
token = parsed.pop('hmac')
to_auth = functionPath.encode('hex') + str(parsed.get('id')).encode('hex')
_verify_token(session_id, to_auth.decode('hex'), token)
args = parsed.get('params')
id = parsed.get('id')
version = parsed.get('jsonrpc')
def _get_jsonrpc_version(self, version=None, id=None):
if version: if version:
version = int(float(version)) version_for_return = int(float(version))
elif id and not version: elif id and not version:
version = jsonrpclib.VERSION_1 version_for_return = jsonrpclib.VERSION_1
else: else:
version = jsonrpclib.VERSION_PRE1 version_for_return = jsonrpclib.VERSION_PRE1
return version_for_return
if self.wallet_type == "lbryum" and functionPath in ['set_miner', 'get_miner_status']:
log.warning("Mining commands are not available in lbryum")
raise Exception("Command not available in lbryum")
def _run_subhandlers(self, request):
for handler in self.subhandlers:
try: try:
function = _get_function(functionPath) assert handler(request)
if args == [{}]: except Exception as err:
d = defer.maybeDeferred(function) log.error(err.message)
else: raise SubhandlerError
d = defer.maybeDeferred(function, *args)
except jsonrpclib.Fault as f:
d = self._cbRender(f, request, id, version)
finally:
# cancel the response if the connection is broken
notify_finish = request.notifyFinish()
notify_finish.addErrback(self._responseFailed, d)
d.addErrback(self._ebRender, id)
d.addCallback(self._cbRender, request, id, version)
d.addErrback(notify_finish.errback)
def _cbRender(self, result, request, id, version):
if isinstance(result, Handler):
result = result.result
if isinstance(result, dict): def _callback_render(self, result, request, id, version, auth_required=False):
result = result['result'] result_for_return = result if not isinstance(result, dict) else result['result']
if version == jsonrpclib.VERSION_PRE1: if version == jsonrpclib.VERSION_PRE1:
if not isinstance(result, jsonrpclib.Fault): if not isinstance(result, jsonrpclib.Fault):
result = (result,) result_for_return = (result_for_return,)
# Convert the result (python) to JSON-RPC # Convert the result (python) to JSON-RPC
try: try:
s = jsonrpclib.dumps(result, version=version, default=default_decimal) encoded_message = jsonrpclib.dumps(result_for_return, version=version, default=default_decimal)
self._render_message(request, s) self._set_headers(request, encoded_message, auth_required)
self._render_message(request, encoded_message)
except: except:
f = jsonrpclib.Fault(self.FAILURE, "can't serialize output") fault = jsonrpclib.Fault(self.FAILURE, "can't serialize output")
s = jsonrpclib.dumps(f, version=version) encoded_message = jsonrpclib.dumps(fault, version=version)
self._set_headers(request, s) self._set_headers(request, encoded_message)
self._render_message(request, s) self._render_message(request, encoded_message)
def _ebRender(self, failure, id): def _errback_render(self, failure, id):
log.error("Request failed:")
log.error(failure) log.error(failure)
log.error(failure.value) log.error(failure.value)
log.error(id) log.error(id)
@ -177,19 +269,6 @@ class LBRYJSONRPCServer(jsonrpc.JSONRPC):
return failure.value return failure.value
return server.failure return server.failure
def render(self, request):
try:
self._check_headers(request)
except InvalidHeaderError:
return server.failure
try:
self._handle(request)
except:
return server.failure
return server.NOT_DONE_YET
def _render_response(self, result, code): def _render_response(self, result, code):
return defer.succeed({'result': result, 'code': code}) return defer.succeed({'result': result, 'code': code})

View file

@ -85,3 +85,9 @@ def initialize_api_key_file(key_path):
new_api_key = APIKey.new(name=API_KEY_NAME) new_api_key = APIKey.new(name=API_KEY_NAME)
keys.update({new_api_key.name: new_api_key}) keys.update({new_api_key.name: new_api_key})
save_api_keys(keys, key_path) save_api_keys(keys, key_path)
def get_auth_message(message_dict):
to_auth = message_dict.get('method').encode('hex')
to_auth += str(message_dict.get('id')).encode('hex')
return to_auth.decode('hex')