diff --git a/blockstack_search/search/README.md b/blockstack_search/search/README.md index a8e47eff1..b11365438 100644 --- a/blockstack_search/search/README.md +++ b/blockstack_search/search/README.md @@ -1,5 +1,7 @@ # OneName Search +### Requirements: + ### Elastic Search Elastic Search library is not in github and resides at @@ -10,10 +12,7 @@ the current version we're using is *0.90.2*. Download from: > wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.90.2.zip - -### Requirements: - -requirements.txt files has been updated and contains all the project requriements. +#### requirements.txt files has been updated and contains all the project requriements. Notes: before installing pylimbmc make sure libmemcache is installed: @@ -25,7 +24,8 @@ before installing pylimbmc make sure libmemcache is installed: ---------------------------------------------- Create Index: - python create_search_index.py --create_index + +> python create_search_index.py --create_index Note: Make sure mongodb and elastic search are running before creating index @@ -43,58 +43,111 @@ To test if elastic search is running: "snapshot_build" : false, "lucene_version" : "4.3.1" }, - "tagline" : "You Know, for Search" - ---------------------------------------------- API usage: ---------------------------------------------- -1) Generate Developer key: +### Generate Developer key: + +Request parameters: + +Developer ID needs to be passed + +Sample Request: + +> curl -G http://localhost:5003/v1/gen_developer_key/ -d "developer_id=asjad" + +Sample Response: + + { + "access_token": "bba1e70e7af8bba213c52d6d9abe3389", + "developer_id": "asjad" + } -syntax: /v1/gen_developer_key/ +### Search API (powered by elastic search) -Example: +syntax: - curl -i http://localhost:5003/v1/gen_developer_key/asjad +> {machineip}/v1/people-search/?keywords={keywords} - ----------------------------------------------- -2) Search API (powered by elastic search) ----------------------------------------------- - -syntax: /v1/people-search//?keywords='' - -EXAMPLE: +EXAMPLE Usage: using username: - curl -i http://localhost:5003/v1/people-search/asjad/a0fe2f40415f7451c4ba2eae7da963d5?keywords=ryan + +> curl -G http://localhost:5003/v1/people-search/a0fe2f40415f7451c4ba2eae7da963d5 -d "keywords=muneeb" using btc_address: - curl -i http://localhost:5003/v1/people-search/asjad/a0fe2f40415f7451c4ba2eae7da963d5?keywords=1G6pazv8zjWKBWouXVgHHvgmRmSm7JmH3S +> curl -G http://localhost:5003/v1/people-search/a0fe2f40415f7451c4ba2eae7da963d5 -d "keywords=1G6pazv8zjWKBWouXVgHHvgmRmSm7JmH3S" + +using twitter handle: + +> curl -G http://localhost:5003/v1/people-search/a0fe2f40415f7451c4ba2eae7da963d5 -d "keywords=ryaneshea" + +### keywords can accept username, twitter handle and btc + +Sample Response: + +------------------------------------------------------- +{ + "people": [ + { + "avatar": { + "url": "http://muneebali.com/static/img/muneebali_thumb.jpg" + }, + "bio": "CTO at HalfmoonLabs. PhD candidate at Princeton. Interested in distributed systems and cryptocurrencies (like Bitcoin)", + "bitcoin": { + "address": "1G6pazv8zjWKBWouXVgHHvgmRmSm7JmH3S" + }, + "cover": { + "url": "http://muneebali.com/static/img/ny_skyline.jpg" + }, + "github": { + "username": "muneeb-ali" + }, + "instagram": { + "username": "muneeb" + }, + "linkedin": { + "url": "http://linkedin.com/in/muneebali" + }, + "location": { + "formatted": "New York" + }, + "name": { + "formatted": "Muneeb Ali" + }, + "twitter": { + "username": "muneeb" + }, + "v": "0.2", + "website": "http://muneebali.com" + } + ] +} - > keywords can accept username, twitter handle and btc +------------------------------------------------------- -* Experimental *: +** Experimental syntax for search queries ** (using the same backend implementation) - http://localhost:5003/v1/people-search/asjad/a0fe2f40415f7451c4ba2eae7da963d5?full-name = Muneeb Ali - http://localhost:5003/v1/people-search/asjad/a0fe2f40415f7451c4ba2eae7da963d5?twitter = muneeb - http://localhost:5003/v1/people-search/asjad/a0fe2f40415f7451c4ba2eae7da963d5?btc = muneeb + curl -i http://localhost:5003/v1/people-search/a0fe2f40415f7451c4ba2eae7da963d5?full-name=Muneeb Ali + curl -i http://localhost:5003/v1/people-search/a0fe2f40415f7451c4ba2eae7da963d5?twitter=ryaneshea + curl -i http://localhost:5003/v1/people-search/a0fe2f40415f7451c4ba2eae7da963d5?btc_address=1G6pazv8zjWKBWouXVgHHvgmRmSm7JmH3S ----------------------------------------------- 3) Profile API (powered by mongodb) ----------------------------------------------- -Syntax: - /v1/people/id= + +Syntax: + +> {machine_ip}/v1/people/id={onename_id} EXAMPLE: - - curl -i http://localhost:5003/v1/people/id=muneeb + +> curl -G http://localhost:5003/v1/people/id=muneeb @@ -125,7 +178,7 @@ The API returns a JSON object of the format: You can test the search API using curl: -> curl http:/// -G -d "query=fred%20wilson" +> curl http://server_ip>/ -G -d "query=fred%20wilson" OR by using the [test_client.py](test_client.py) @@ -135,4 +188,4 @@ Make sure that the packages listed in requirements.txt are installed before usin This will currently return upto a max of 20 results (can be less depending on the query) with data that follows structure of OneName profiles described here: -https://github.com/onenameio/onename \ No newline at end of file +https://github.com/onenameio/onename diff --git a/blockstack_search/search/helpers.py b/blockstack_search/search/helpers.py index 2a42b5166..5a06f7825 100644 --- a/blockstack_search/search/helpers.py +++ b/blockstack_search/search/helpers.py @@ -6,7 +6,7 @@ c = MongoClient() db = c['developers'] nodes = db.nodes -MAX_QUOTA = 5000 +MAX_QUOTA = 1000 #------------------------------------------------------------- def generate_key(username): @@ -18,28 +18,34 @@ def generate_key(username): return key #------------------------------------------------------------- -def is_key_valid(key): +def validate_token(access_token): """Checks if a 'key' is valid""" - if key == None: + if access_token == None: return False - return nodes.find({'api_key' : key}).limit(1).count() + return nodes.find({'api_key' : access_token}).limit(1).count() #------------------------------------------------------------- -def is_overquota(username): - """Returns True if quota associated with 'username' has expired and False otherwise""" +def verify_and_decrement_quota(access_token): + """Returns False if quota associated with 'username' has expired and Decrements quota otherwise""" - user = nodes.find_one({'username' : username}) - return user['api_quota'] < 1 + user = nodes.find_one({'api_key' : access_token}) + + if user['api_quota'] < 1: + return False + else: + decrement_quota(access_token) + return True #-------------------------------------- -def decrement_quota(username): +def decrement_quota(access_token): """Decrement API quota associated with the 'username'""" - user = nodes.find_one({'username' : username}) + user = nodes.find_one({'api_key' : access_token}) user['api_quota'] = user['api_quota'] - 1 + nodes.save(user) #-------------------------------------- diff --git a/blockstack_search/search/onename_api.py b/blockstack_search/search/onename_api.py index 2a315fb2e..761cf0d8b 100644 --- a/blockstack_search/search/onename_api.py +++ b/blockstack_search/search/onename_api.py @@ -22,13 +22,21 @@ DEFAULT_LIMIT = 35 from pymongo import MongoClient c = MongoClient() + #---------------------------------------------- -@app.route('/v1/gen_developer_key/', methods = ['GET']) -def create_account(developer_id): +#Create Developer Account +#saves the user and generates the access_token +#---------------------------------------------- +@app.route('/v1/gen_developer_key/', methods = ['GET']) +def create_account(): #saves the ID and returns the access token - access_token = save_user(developer_id, 'basic') - - return jsonify({'developer_id':developer_id, + request_val = request.values + if 'developer_id' in request_val: + access_token = save_user(request.values['developer_id'], 'basic') + else: + return make_response(jsonify( {'error': 'Invalid Request' } ), 400) + + return jsonify({'developer_id':request.values['developer_id'], 'access_token':access_token}) #---------------------------------------------- @@ -36,14 +44,14 @@ def create_account(developer_id): #The Search API returns the profiles based on keyword saerches. #Results are retrieved through indexed data #---------------------------------------------- -@app.route('/v1/people-search//', methods = ['GET']) -def search_people(developer_id,access_token): - #1. verify key - if not is_key_valid(access_token): +@app.route('/v1/people-search/', methods = ['GET']) +def search_people(access_token): + #1. verify access_token + if not validate_token(access_token): return make_response(jsonify( { 'error': 'Invalid Token' } ), 400) - #2. verify available quota - if is_overquota(developer_id): + #2. verify available quota and decrement + if not verify_and_decrement_quota(access_token): return make_response(jsonify( { 'error': 'Quota Exceeded' } ), 401) results = ""