예제 #1
0
파일: views.py 프로젝트: Code4SA/med-db
def country_report(country_code):
    """
    """

    country_code = country_code.upper()
    if not available_countries.get(country_code):
        raise ApiException(400, "Reports are not available for the country that you specified.")
    if g.user is None or not g.user.is_active():
        raise ApiException(401, "You need to be logged-in in order to access this resource.")

    country = Country.query.filter_by(code=country_code).one()

    report_json = cache.retrieve('country_overview_' + country.code)
    if report_json:
        logger.debug('loading country overview from cache')
    else:
        report = {}
        procurement_list = []
        procurements = Procurement.query.filter_by(country=country).filter_by(approved=True).order_by(Procurement.start_date.desc(), Procurement.end_date.desc()).all()
        for procurement in procurements:
            procurement_list.append(procurement.to_dict(include_related=True))
        report['country'] = country.to_dict()
        report['medicines'] = calculate_country_overview(country)
        report['procurements'] = procurement_list
        report_json = json.dumps(report, cls=serializers.CustomEncoder)
        cache.store('country_overview_' + country.code, report_json)

    return send_api_response(report_json)
예제 #2
0
파일: forms.py 프로젝트: Code4SA/med-db
def get_source_choices():
    source_choices = []
    sources = models.Source.query.all()
    for source in sources:
        source_choices.append((source.source_id, str(source)))
    logger.debug(source_choices)
    return source_choices
예제 #3
0
파일: views.py 프로젝트: Code4SA/med-db
def autocomplete(query):
    """
    Return the name and medicine_id of each medicine that matches the given query.
    """

    out = []
    medicine_list_json = cache.retrieve('medicine_list')
    if medicine_list_json:
        logger.debug('calculating autocomplete from cache')
        medicine_list = json.loads(medicine_list_json)
    else:
        medicine_list = calculate_autocomplete()
        cache.store('medicine_list', json.dumps(medicine_list, cls=serializers.CustomEncoder))
    for medicine in medicine_list:
        tmp = {}
        query_index = medicine['name'].lower().find(query.lower())
        if query_index > -1:
            tmp['medicine_id'] = medicine['medicine_id']
            tmp['name'] = medicine['name']
            tmp['index'] = query_index
            out.append(tmp)
        if len(out) > 20:
            break
    out = sorted(out, key=itemgetter('index'))
    if len(out) > 10:
        out = out[0:10]
    return send_api_response(json.dumps(out))
예제 #4
0
파일: views.py 프로젝트: Code4SA/med-db
def calculate_autocomplete():
    """
    Retrieve all medicine records and serialize them for use by the autocomplete endpoint.
    THIS IS slightly COMPUTATIONALLY EXPENSIVE
    """

    cutoff = datetime.datetime.today() - datetime.timedelta(days=MAX_AGE)

    logger.debug("Calculating autocomplete")
    # medicines = Medicine.query.order_by(Medicine.name).all()
    procurements = Procurement.query.join(Product).filter(
        or_(
            Procurement.start_date > cutoff,
            Procurement.end_date > cutoff
        )
    ).filter(
        Procurement.approved != False
    ).all()
    medicines = []
    for procurement in procurements:
        if not procurement.product.medicine in medicines:
            medicines.append(procurement.product.medicine)
    out = []
    for medicine in medicines:
        tmp_dict = {
            'name': medicine.name,
            'medicine_id': medicine.medicine_id,
            }
        out.append(tmp_dict)
    return out
예제 #5
0
def revoke_token(access_token):
    h = Http(disable_ssl_certificate_validation=True)
    logger.debug('revoking %s' % access_token)
    resp, cont = h.request(
        'https://accounts.google.com/o/oauth2/revoke?token=%s' % access_token,
        headers={
            'Host': 'www.googleapis.com',
            'Authorization': 'Bearer %s' % access_token
        })

    return resp
예제 #6
0
파일: views.py 프로젝트: Code4SA/med-db
def country_ranking():
    """
    """

    ranking_json = cache.retrieve('country_ranking')
    if ranking_json:
        logger.debug('loading country ranking from cache')
    else:
        ranking = calculate_country_rankings()
        ranking_json = json.dumps(ranking)
        cache.store('country_ranking', ranking_json)
    return send_api_response(ranking_json)
예제 #7
0
파일: views.py 프로젝트: Code4SA/med-db
def overview():
    """
    Give a broad overview of the size of -, and recent activity related to, the database.
    """

    tmp = cache.retrieve('db_overview')
    if tmp:
        logger.debug("DB overview served from cache")
        return send_api_response(tmp)
    else:
        tmp = calculate_db_overview()
        cache.store('db_overview', json.dumps(tmp, cls=serializers.CustomEncoder))
        return send_api_response(json.dumps(tmp))
예제 #8
0
파일: views.py 프로젝트: Code4SA/med-db
def calculate_country_rankings():
    """
    THIS IS COMPUTATIONALLY EXPENSIVE
    """

    logger.debug("Calculating country rankings")

    ranking = {}
    for country_code in available_countries.keys():
        ranking[country_code] = {
            'score': 0,
            'overall_spend': 0,
            'potential_savings': 0,
            }
    # iterate through all medicines in the db
    medicines = Medicine.query.order_by(Medicine.name).all()
    for medicine in medicines:
        # serialize medicine, so that procurements may be ordered
        medicine_dict = medicine.to_dict(include_related=True)
        procurements = medicine_dict['procurements']
        if not procurements:
            continue
        # calculate the total spend and potential savings for each transaction
        best_price = procurements[0]['unit_price_usd']
        benchmarks = medicine_dict['benchmarks']
        for benchmark in benchmarks:
            if benchmark['price'] < best_price:
                best_price = benchmark['price']
        for procurement in procurements:
            if ranking.get(procurement['country']['code']):
                total = procurement['quantity'] * procurement['pack_price_usd']
                tmp_diff = procurement['unit_price_usd'] - best_price
                potential_saving = procurement['quantity'] * procurement['pack_size'] * tmp_diff
                ranking[procurement['country']['code']]['overall_spend'] += total
                ranking[procurement['country']['code']]['potential_savings'] += potential_saving
    # score countries by how close their spend is to the theoretical best
    ranked_list = []
    for country_code, entry in ranking.iteritems():
        if entry['overall_spend']:
            entry['score'] = 1 - (entry['potential_savings']/float(entry['overall_spend']))
        entry['country'] = Country.query.filter_by(code=country_code).one().to_dict()
        ranked_list.append(entry)
    ranked_list = sorted(ranked_list, key=itemgetter("score"))
    ranked_list.reverse()
    out = {'count': len(ranked_list), 'countries': ranked_list}
    return out
예제 #9
0
파일: views.py 프로젝트: Code4SA/med-db
def calculate_country_overview(country):
    """
    THIS IS COMPUTATIONALLY EXPENSIVE
    """

    logger.debug("Calculating country overview")

    # iterate through all medicines in the db
    medicines = Medicine.query.order_by(Medicine.name).all()
    medicines_out = []
    for medicine in medicines:
        tmp = {
            'score': 0,
            'overall_spend': 0,
            'potential_savings': 0,
            }
        # serialize medicine, so that procurements may be ordered
        medicine_dict = medicine.to_dict(include_related=True)
        procurements = medicine_dict['procurements']
        if not procurements:
            continue
        # calculate the total spend and potential savings for each transaction
        best_price = procurements[0]['unit_price_usd']
        benchmarks = medicine_dict['benchmarks']
        for benchmark in benchmarks:
            if benchmark['price'] < best_price:
                best_price = benchmark['price']
        for procurement in procurements:
            if procurement['country']['code']==country.code:
                total = procurement['quantity'] * procurement['pack_price_usd']
                tmp_diff = procurement['unit_price_usd'] - best_price
                potential_saving = procurement['quantity'] * procurement['pack_size'] * tmp_diff
                tmp['overall_spend'] += total
                tmp['potential_savings'] += potential_saving
        if tmp['overall_spend'] and tmp['overall_spend'] > 1000:
            tmp['name'] = medicine.name
            tmp['medicine_id'] = medicine.medicine_id
            tmp['score'] = 1 - (tmp['potential_savings']/float(tmp['overall_spend']))
            medicines_out.append(tmp)

    # score medicines by how close their spend is to the theoretical best
    medicines_out = sorted(medicines_out, key=itemgetter("potential_savings"))
    medicines_out.reverse()
    return medicines_out
예제 #10
0
    def get(self, user):
        """Search stack by query param. Query is passed by 'q' URL param.."""
        query = {
            "sort": [{
                "last_activity": {
                    "order": "desc"
                }
            }],
            "query": {
                "query_string": {
                    "query": request.args.get('q')
                }
            }
        }
        logger.debug('query %s' % query)

        return repository.search_data_by_query(index=index,
                                               doc_type=doc_type,
                                               query=query)
예제 #11
0
파일: views.py 프로젝트: Code4SA/med-db
def calculate_db_overview():
    """
    Run a set of queries to get an overview of the database.
    THIS IS COMPUTATIONALLY EXPENSIVE
    """

    logger.debug("Calculating DB overview")
    overview = {}

    # number of recent products & medicines
    count_procurements, count_products, count_medicines = Procurement.query.join(Product).filter(
        Procurement.approved != False
    ).with_entities(
        func.count(Procurement.procurement_id),
        func.count(distinct(Procurement.product_id)),
        func.count(distinct(Product.medicine_id))
    ).first()
    overview['count_procurements'] = count_procurements
    overview['count_products'] = count_products
    overview['count_medicines'] = count_medicines

    # number of recent procurements logged per country
    top_sources = []
    sources = db.session.query(Procurement.country_id,
                               func.count(Procurement.procurement_id)) \
        .filter(
        Procurement.approved != False
    ).group_by(Procurement.country_id) \
        .order_by(func.count(Procurement.procurement_id).desc()).all()

    for country_id, count in sources[0:5]:
        print 'Country ID %d: %d' % (country_id, count)
        country = Country.query.get(country_id)
        top_sources.append(
            {
                'country': country.to_dict(),
                'procurement_count': count
            }
        )
    overview['top_sources'] = top_sources
    return overview
예제 #12
0
def try_dispach_whti_refresh_token(fn, *args, **kwargs):
    json_web_token = parse_token_no_validade(request)
    logger.debug('=== Trying to refresh access_token')
    if 'refresh_token' in json_web_token['user']:
        refresh_token = json_web_token['user']['refresh_token']
        logger.debug('=== Refresh access_token using %s' % refresh_token)
        new_token = refresh_access_token(refresh_token)
        logger.debug('=== Getting user by access_token')
        user = validate_token(new_token['access_token'])

        if user is not None:
            return fn(user=user, *args, **kwargs)
        else:
            logger.debug('=== Refresh access_token not work')
예제 #13
0
def refresh_access_token(refresh_token):
    """"Refresh access_token"""
    payload = dict(grant_type='refresh_token',
                   client_id=app.config['GOOGLE_CLIENT_ID'],
                   client_secret=app.config['GOOGLE_CLIENT_SECRET'],
                   refresh_token=refresh_token)
    # h = Http(disable_ssl_certificate_validation=True)
    # resp, cont = h.request(
    #     "https://www.googleapis.com/oauth2/v3/userinfo",
    #     method='POST',
    #     body=json.dumps(payload),
    #     )

    logger.debug(payload)

    headers = {'Content-Type': 'application/x-www-form-urlencoded'}

    r = requests.post("https://accounts.google.com/o/oauth2/token",
                      data=payload,
                      headers=headers)

    logger.debug('=====> %s' % r.status_code)

    if not r.status_code == 200:
        return None

    logger.debug(r.text)
    return json.loads(r.text)
예제 #14
0
    def post(self):
        """Autenticate google user account.

        Expect a request json with clientId, redirectUri and code attributes.
        Samples:
         {
         'clientId': your-google-client-id,
         'code': '4/xHYKb3CD9gbiXBiL2XPaj_ILlMjXTJbVmBTFCVGBjKo',
         'accessType': 'offline',
         'redirectUri': u'http://localhost:8080'
         }

        """
        access_token_url = 'https://www.googleapis.com/oauth2/v4/token'
        people_api_url = 'https://www.googleapis.com/oauth2/v3/userinfo'
        tokeninfo_url = 'https://www.googleapis.com/oauth2/v3/tokeninfo'

        logger.debug('google request =>')
        logger.debug(request.json)

        payload = dict(client_id=request.json['clientId'],
                       redirect_uri=request.json['redirectUri'],
                       client_secret=app.config['GOOGLE_CLIENT_SECRET'],
                       code=request.json['code'],
                       grant_type='authorization_code')

        logger.debug('Google Payload =>')
        logger.debug(payload)

        # Step 2. Exchange authorization code for access token.
        r = requests.post(access_token_url, data=payload)
        token = json.loads(r.text)
        logger.debug('Access Token =>')
        logger.debug(token)

        # Step 2. Retrieve information about the current user.

        headers = {'Authorization': 'Bearer {0}'.format(token['access_token'])}
        r = requests.get(people_api_url, headers=headers)
        profile = json.loads(r.text)
        logger.info('Login as => %s' % profile['email'])
        logger.debug(profile)

        if security.is_valid_email(profile['email']):
            # Step 4. Create a new account or return an existing one.
            r = requests.get('%s?access_token=%s' % (tokeninfo_url, token['access_token']))
            token_info = json.loads(r.text)
            logger.debug('Tokeninfo =>')
            logger.debug(token_info)

            # Step 5. Sign-up a user process
            account = {}
            try:
                account = repository.get_document(
                    index=index,
                    doc_type=doc_type,
                    id=profile['sub'])

                # update refresh_token if it was informed (after revoke token)
                logger.debug('Account found for %s' % profile['email'])
                if 'refresh_token' in token:
                    logger.debug('A new refresh_token was defined. It will be updated')
                    repository.update(
                        index=index,
                        doc_type=doc_type,
                        id=profile['sub'],
                        body={"doc": {"refresh_token":  token['refresh_token']}}
                    )
                # if extits, profile will be the accound founded

                # profile['refresh_token'] = account["_source"]['refresh_token']
            except NotFoundError as e:
                # create a new user if not exists one account
                logger.warning('First logging for  %s' % profile['email'])

                account = profile.copy()
                account['created_at'] = datetime.utcnow()

                if 'refresh_token' in token:
                    account['refresh_token'] = token['refresh_token']

                repository.insert(index=index, doc_type=doc_type, login=account['sub'], document=account)

            # Step 6. Build and return a json web token.
            jwt_payload = {
                'sub': profile['sub'],
                'iat': datetime.utcnow(),
                'exp': datetime.utcnow() + timedelta(days=5),
                'access_token':token['access_token'],
                'user': profile
            }

            jwt = security.create_token(jwt_payload)
            return jsonify(token=jwt)
            # return jsonify(token=token['access_token'])
        else:
            return security.response_not_authorized(
                403,
                'Invalid email domain. Please sign with ciandt.com acccount'
                )
예제 #15
0
    def decorated_function(*args, **kwargs):
        logger.debug('=== Authorization check ===')
        if 'Authorization' in request.headers:
            logger.debug('=== Check Authorization token')
            access_token = request.headers.get('Authorization').split()[1]
            user = validate_token(access_token)
            if user is not None:
                return fn(user=user, *args, **kwargs)

            response = jsonify(message='Check access token failed')
            response.status_code = 403
            return response

        # try parser json web token
        if 'jwt-authorization' in request.headers:

            logger.debug('=== Check JWT Authorization')
            try:
                json_web_token = parse_token(request)

                if 'user' in json_web_token:
                    logger.debug("Getting user from JWT TOKEN ===>")
                    return fn(user=json_web_token['user'], *args, **kwargs)

                access_token = get_oauth_token(json_web_token)
                logger.debug('=== access_token: %s' % access_token)

                logger.debug(
                    '=== Getting user data from google by access_token')
                user = validate_token(access_token)
                if user is not None:
                    return fn(user=user, *args, **kwargs)

                response = jsonify(message='Check access token failed')
                response.status_code = 403
                return response

            except DecodeError:
                response = jsonify(message='Token is invalid')
                response.status_code = 401
                return response
            except ExpiredSignature:
                # try_dispach_whti_refresh_token(fn, *args, **kwargs)
                response = jsonify(message='JSON Web Token has expired')
                response.status_code = 403
                return response

        response = jsonify(message='Missing authorization header')
        response.status_code = 401
        return response