def get_user_app_info(request):
  try:
    oauth_request = OAUTH_SERVER.extract_oauth_request(djangoutils.extract_request(request))
    consumer, token, parameters = OAUTH_SERVER.check_resource_access(oauth_request)
    return consumer, token, parameters, oauth_request
  except oauth.OAuthError:
    return None, None, None, None
def get_user_app_info(request):
    try:
        oauth_request = OAUTH_SERVER.extract_oauth_request(
            djangoutils.extract_request(request))
        consumer, token, parameters = OAUTH_SERVER.check_resource_access(
            oauth_request)
        return consumer, token, parameters, oauth_request
    except oauth.OAuthError:
        return None, None, None, None
def record_pha_setup(request, record, pha):
  """Set up a PHA in a record ahead of time

  FIXME: eventually, when there are permission restrictions on a PHA, make sure that
  any permission restrictions on the current PHA are transitioned accordingly
  """

  content = request.raw_post_data

  # if there is a document, create it
  if content:
    # is there already a setup doc
    setup_docs = Document.objects.filter(record=record, pha=pha, external_id='SETUP')
    if len(setup_docs) == 0:
      new_doc = _document_create( record      = record,
                                  creator     = request.principal,
                                  pha         = pha,
                                  content     = content,
                                  external_id = Document.prepare_external_id('SETUP', pha, pha_specific=True, record_specific=True))

  # preauthorize the token.
  from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
  access_token = OAUTH_SERVER.generate_and_preauthorize_access_token(pha, record=record)

  # return the token
  return HttpResponse(access_token.to_string(), mimetype="application/x-www-form-urlencoded")
Exemple #4
0
def request_token(request):
    """ Get a new request token, bound to a record or carenet if desired.

    request.POST may contain **EITHER**:

    * *indivo_record_id*: The record to which to bind the request token.
    
    * *indivo_carenet_id*: The carenet to which to bind the request token.

    Will return :http:statuscode:`200` with the request token on success,
    :http:statuscode:`403` if the oauth signature on the request was missing
    or faulty.

    """

    # ask the oauth server to generate a request token given the HTTP request
    try:
        # we already have the oauth_request in context, so we don't get it again
        from indivo.accesscontrol.oauth_servers import OAUTH_SERVER

        request_token = OAUTH_SERVER.generate_request_token(
            request.oauth_request,
            record_id=request.POST.get("indivo_record_id", None),
            carenet_id=request.POST.get("indivo_carenet_id", None),
        )
        return HttpResponse(request_token.to_string(), mimetype="text/plain")
    except oauth.OAuthError, e:
        # an exception can be raised if there is a bad signature (or no signature) in the request
        raise PermissionDenied()
Exemple #5
0
def request_token_approve(request, reqtoken):
  record_id = request.POST.get('record_id', None)
  carenet_id = request.POST.get('carenet_id', None)
  
  record = None
  if record_id:
    record = Record.objects.get(id = record_id)

  carenet = None
  if carenet_id:
    carenet = Carenet.objects.get(id = carenet_id)

  # if the request token was bound to a record, then it must match
  if reqtoken.record != None and reqtoken.record != record:
    raise PermissionDenied()

  # if the request token was bound to a carenet
  if reqtoken.carenet != None and reqtoken.carenet != carenet:
    raise PermissionDenied()

  # the permission check that the current user is authorized to connect to this record
  # or to this carenet is already done in accesscontrol
  
  # authorize the request token
  from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
  request_token = OAUTH_SERVER.authorize_request_token(reqtoken.token, record = record, carenet = carenet, account = request.principal)

  # where to redirect to + parameters
  redirect_url = request_token.oauth_callback or request_token.pha.callback_url
  redirect_url += "?oauth_token=%s&oauth_verifier=%s" % (request_token.token, request_token.verifier)

  # redirect to the request token's callback, or if null the PHA's default callback
  return HttpResponse(urllib.urlencode({'location': redirect_url}))
Exemple #6
0
def request_token(request):
    """ Get a new request token, bound to a record or carenet if desired.

    request.POST may contain **EITHER**:

    * *indivo_record_id*: The record to which to bind the request token.
    
    * *indivo_carenet_id*: The carenet to which to bind the request token.

    Will return :http:statuscode:`200` with the request token on success,
    :http:statuscode:`403` if the oauth signature on the request was missing
    or faulty.

    """

    # ask the oauth server to generate a request token given the HTTP request
    try:
        # we already have the oauth_request in context, so we don't get it again
        from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
        request_token = OAUTH_SERVER.generate_request_token(request.oauth_request, 
                                                            record_id = request.POST.get('indivo_record_id', None),
                                                            carenet_id = request.POST.get('indivo_carenet_id', None))
        return HttpResponse(request_token.to_string(), mimetype='text/plain')
    except oauth.OAuthError, e:
        # an exception can be raised if there is a bad signature (or no signature) in the request
        raise PermissionDenied()
Exemple #7
0
def exchange_token(request):
    # ask the oauth server to exchange a request token into an access token
    # this will check proper oauth for this action

    try:
        access_token = OAUTH_SERVER.exchange_request_token(request.oauth_request)
        # an exception can be raised if there is a bad signature (or no signature) in the request
    except:
        raise PermissionDenied()

    return HttpResponse(access_token.to_string(), mimetype="text/plain")
Exemple #8
0
def request_token_approve(request, reqtoken):
    """ Indicate a user's consent to bind an app to a record or carenet.

  request.POST must contain **EITHER**:
  
  * *record_id*: The record to bind to.

  * *carenet_id*: The carenet to bind to.

  Will return :http:statuscode:`200` with a redirect url to the app on success,
  :http:statuscode:`403` if *record_id*/*carenet_id* don't match *reqtoken*.

  """

    record_id = request.POST.get('record_id', None)
    carenet_id = request.POST.get('carenet_id', None)

    record = None
    if record_id:
        record = Record.objects.get(id=record_id)

    carenet = None
    if carenet_id:
        carenet = Carenet.objects.get(id=carenet_id)

    # if the request token was bound to a record, then it must match
    if reqtoken.record != None and reqtoken.record != record:
        raise PermissionDenied()

    # if the request token was bound to a carenet
    if reqtoken.carenet != None and reqtoken.carenet != carenet:
        raise PermissionDenied()

    # the permission check that the current user is authorized to connect to this record
    # or to this carenet is already done in accesscontrol

    # authorize the request token
    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
    request_token = OAUTH_SERVER.authorize_request_token(
        reqtoken.token,
        record=record,
        carenet=carenet,
        account=request.principal)

    # where to redirect to + parameters
    redirect_url = request_token.oauth_callback or request_token.pha.callback_url
    redirect_url += "?oauth_token=%s&oauth_verifier=%s" % (
        request_token.token, request_token.verifier)

    # redirect to the request token's callback, or if null the PHA's default callback
    return HttpResponse(urllib.urlencode({'location': redirect_url}))
Exemple #9
0
def request_token(request):
    """
    the request-token request URL
    """
    # ask the oauth server to generate a request token given the HTTP request
    try:
      # we already have the oauth_request in context, so we don't get it again
      request_token = OAUTH_SERVER.generate_request_token(request.oauth_request, 
                                                          record_id = request.POST.get('indivo_record_id', None),
                                                          carenet_id = request.POST.get('indivo_carenet_id', None))
      return HttpResponse(request_token.to_string(), mimetype='text/plain')
    except oauth.OAuthError, e:
      # an exception can be raised if there is a bad signature (or no signature) in the request
      raise PermissionDenied()
Exemple #10
0
def request_token_approve(request, reqtoken):
    """ Indicate a user's consent to bind an app to a record or carenet.

    request.POST must contain **EITHER**:
    
    * *record_id*: The record to bind to.

    * *carenet_id*: The carenet to bind to.

    Will return :http:statuscode:`200` with a redirect url to the app on success,
    :http:statuscode:`403` if *record_id*/*carenet_id* don't match *reqtoken*.

    """

    record_id = request.POST.get("record_id", None)
    carenet_id = request.POST.get("carenet_id", None)

    record = None
    if record_id:
        record = Record.objects.get(id=record_id)

    carenet = None
    if carenet_id:
        carenet = Carenet.objects.get(id=carenet_id)

    # if the request token was bound to a record, then it must match
    if reqtoken.record != None and reqtoken.record != record:
        raise PermissionDenied()

    # if the request token was bound to a carenet
    if reqtoken.carenet != None and reqtoken.carenet != carenet:
        raise PermissionDenied()

    # the permission check that the current user is authorized to connect to this record
    # or to this carenet is already done in accesscontrol

    # authorize the request token
    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER

    request_token = OAUTH_SERVER.authorize_request_token(
        reqtoken.token, record=record, carenet=carenet, account=request.principal
    )

    # where to redirect to + parameters
    redirect_url = request_token.oauth_callback or request_token.pha.callback_url
    redirect_url += "?oauth_token=%s&oauth_verifier=%s" % (request_token.token, request_token.verifier)

    # redirect to the request token's callback, or if null the PHA's default callback
    return HttpResponse(urllib.urlencode({"location": redirect_url}))
Exemple #11
0
def record_pha_setup(request, record, pha):
    """ Bind an app to a record without user authorization.

  This call should be used to set up new records with apps required
  for this instance of Indivo to run (i.e. syncer apps that connect to 
  data sources). It can only be made by admins, since it skips the
  normal app authorization process.

  ``request.POST`` may contain raw content that will be used
  as a setup document for the record.

  Will return :http:statuscode:`200` with a valid access token for the
  app bound to the record on success.
  
  """

    # TODO: eventually, when there are permission restrictions on a PHA,
    # make sure that any permission restrictions on the current PHA are
    # transitioned accordingly.

    content = request.raw_post_data

    # if there is a document, create it
    if content:
        # is there already a setup doc
        setup_docs = Document.objects.filter(record=record,
                                             pha=pha,
                                             external_id='SETUP')
        if len(setup_docs) == 0:
            new_doc = _document_create(
                record=record,
                creator=request.principal,
                pha=pha,
                content=content,
                external_id=Document.prepare_external_id('SETUP',
                                                         pha,
                                                         pha_specific=True,
                                                         record_specific=True))

    # preauthorize the token.
    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
    access_token = OAUTH_SERVER.generate_and_preauthorize_access_token(
        pha, record=record)

    # return the token
    return HttpResponse(access_token.to_string(),
                        mimetype="application/x-www-form-urlencoded")
Exemple #12
0
def autonomous_access_token(request, pha, record):
    """ Fetch an access token for an autonomous app to access a record.

    This call *assumes* that the app has already been enabled on the record, and 
    that the user has already authorized it (this must be checked in the access control 
    for the function). Otherwise, this will automatically enable the app on the record
    (a BAD idea).

    This call should be made by autonomous apps to get access tokens for records which
    have already enabled them (presumably after a call to app_record_list).

    Will return :http:statuscode:`200` with a valid access token for the app bound to the
    record on success.
   
    """

    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
    access_token = OAUTH_SERVER.generate_and_preauthorize_access_token(pha, record=record)
    return HttpResponse(access_token.to_string(), mimetype="application/x-www-form-urlencoded")
Exemple #13
0
def record_pha_setup(request, record, pha):
    """ Bind an app to a record without user authorization.

  This call should be used to set up new records with apps required
  for this instance of Indivo to run (i.e. syncer apps that connect to 
  data sources). It can only be made by admins, since it skips the
  normal app authorization process.

  ``request.POST`` may contain raw content that will be used
  as a setup document for the record.

  Will return :http:statuscode:`200` with a valid access token for the
  app bound to the record on success.
  
  """

    # TODO: eventually, when there are permission restrictions on a PHA,
    # make sure that any permission restrictions on the current PHA are
    # transitioned accordingly.

    content = request.raw_post_data

    # if there is a document, create it
    if content:
        # is there already a setup doc
        setup_docs = Document.objects.filter(record=record, pha=pha, external_id="SETUP")
        if len(setup_docs) == 0:
            new_doc = _document_create(
                record=record,
                creator=request.principal,
                pha=pha,
                content=content,
                external_id=Document.prepare_external_id("SETUP", pha, pha_specific=True, record_specific=True),
            )

    # preauthorize the token.
    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER

    access_token = OAUTH_SERVER.generate_and_preauthorize_access_token(pha, record=record)

    # return the token
    return HttpResponse(access_token.to_string(), mimetype="application/x-www-form-urlencoded")
Exemple #14
0
def autonomous_access_token(request, pha, record):
    """ Fetch an access token for an autonomous app to access a record.

    This call *assumes* that the app has already been enabled on the record, and 
    that the user has already authorized it (this must be checked in the access control 
    for the function). Otherwise, this will automatically enable the app on the record
    (a BAD idea).

    This call should be made by autonomous apps to get access tokens for records which
    have already enabled them (presumably after a call to app_record_list).

    Will return :http:statuscode:`200` with a valid access token for the app bound to the
    record on success.
   
    """

    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
    access_token = OAUTH_SERVER.generate_and_preauthorize_access_token(
        pha, record=record)
    return HttpResponse(access_token.to_string(),
                        mimetype="application/x-www-form-urlencoded")
Exemple #15
0
def exchange_token(request):
    """ Exchange a request token for a valid access token.

    This call requires that the request be signed with a valid oauth request
    token that has previously been authorized.

    Will return :http:statuscode:`200` with the access token on success,
    :http:statuscode:`403` if the oauth signature is missing or invalid.

    """
    
    # ask the oauth server to exchange a request token into an access token
    # this will check proper oauth for this action

    try:
        from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
        access_token = OAUTH_SERVER.exchange_request_token(request.oauth_request)
        # an exception can be raised if there is a bad signature (or no signature) in the request
    except:
        raise PermissionDenied()
    
    return HttpResponse(access_token.to_string(), mimetype='text/plain')
Exemple #16
0
def exchange_token(request):
    """ Exchange a request token for a valid access token.

    This call requires that the request be signed with a valid oauth request
    token that has previously been authorized.

    Will return :http:statuscode:`200` with the access token on success,
    :http:statuscode:`403` if the oauth signature is missing or invalid.

    """
    
    # ask the oauth server to exchange a request token into an access token
    # this will check proper oauth for this action

    try:
        from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
        access_token = OAUTH_SERVER.exchange_request_token(request.oauth_request)
        # an exception can be raised if there is a bad signature (or no signature) in the request
    except:
        raise PermissionDenied()
    
    return HttpResponse(access_token.to_string(), mimetype='text/plain')
Exemple #17
0
def user_authorization(request):
  """Authorize a request token, binding it to a single record.

  A request token *must* be bound to a record before it is approved.
  """

  try:
    token = ReqToken.objects.get(token = request.REQUEST['oauth_token'])
  except ReqToken.DoesNotExist:
    raise Http404

  # are we processing the form
  # OR, is this app already authorized
  if request.method == "POST" or (token.record and token.record.has_pha(token.pha)):
    # get the record from the token
    record = token.record

    # are we dealing with a record already
    if not (record and record.has_pha(token.pha)):
      record = Record.objects.get(id = request.POST['record_id'])
    
      # allowed to administer the record? Needed if the record doesn't have the PHA yet
      if not record.can_admin(request.principal):
        raise Exception("cannot administer this record")

    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
    request_token = OAUTH_SERVER.authorize_request_token(token.token, record = record, account = request.principal)

    # where to redirect to + parameters
    redirect_url = request_token.oauth_callback or request_token.pha.callback_url
    redirect_url += "?oauth_token=%s&oauth_verifier=%s" % (request_token.token, request_token.verifier)

    # redirect to the request token's callback, or if null the PHA's default callback
    return HttpResponseRedirect(redirect_url)
  else:
    records = request.principal.records_administered.all()
    return render_template('authorize', {'token' : token, 'records': records})
Exemple #18
0
def get_connect_credentials(request, account, pha):
    """ Get oAuth credentials for an app to run in Connect or SMART REST mode.

    Generates access tokens for *pha* to run against the *record_id* specified in ``request.POST``, authorized by
    *account*. Generates 2 tokens: one for SMART Connect use, and one for SMART REST use.

    If the app is not yet enabled for the record/carenet, this will return a :http:statuscode:`403`.
    
    """

    carenet = record = None
    carenet_id = request.POST.get('carenet_id', None)
    record_id = request.POST.get('record_id', None)

    if carenet_id:
        try:
            carenet=Carenet.objects.get(id=carenet_id)
        except Carenet.DoesNotExist:
            raise Http404
        except Carenet.MultipleObjectsReturned:
            raise Exception("Multiple carenets with same id--database is corrupt")

    elif record_id:
        try:
            record = Record.objects.get(id=record_id)
        except Record.DoesNotExist:
            raise Http404
        except Record.MultipleObjectsReturned:
            raise Exception("Multiple records with same id--database is corrupt")

    # Make sure that the app is enabled
    if (record and not PHAShare.objects.filter(record=record, with_pha=pha).exists()) or \
            (carenet and not CarenetPHA.objects.filter(carenet=carenet, pha=pha).exists()):
        raise PermissionDenied("Cannot generate credentials before app is enabled")

    # Generate the tokens
    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
    rest_token = OAUTH_SERVER.generate_and_preauthorize_access_token(pha, record=record, 
                                                                     carenet=carenet, account=account)
    connect_token = OAUTH_SERVER.generate_and_preauthorize_access_token(pha, record=record, 
                                                                        carenet=carenet, account=account)
    connect_token.connect_auth_p = True
    connect_token.save()

    # Generate a 2-legged oauth header for the rest token, based on the pha's start_url
    url = utils.url_interpolate(pha.start_url_template, {'record_id':record_id or '', 'carenet_id':carenet_id or ''})
    request = HTTPRequest("GET", url, HTTPRequest.FORM_URLENCODED_TYPE, '', {})
    oauth_params = {
        'smart_container_api_base': settings.SITE_URL_PREFIX,
        'smart_oauth_token': rest_token.token,
        'smart_oauth_token_secret': rest_token.token_secret,
        'smart_user_id': account.email,
        'smart_app_id': pha.email,
        'smart_record_id': record_id,
        }
    oauth_request = OAuthRequest(consumer=pha,
                                 token=None, # no access tokens: 2-legged request
                                 http_request=request,
                                 oauth_parameters=oauth_params)
    oauth_request.sign()
    auth_header = oauth_request.to_header()["Authorization"]

    return render_template('connect_credentials', 
                           { 'connect_token': connect_token,
                             'rest_token': rest_token,
                             'api_base': settings.SITE_URL_PREFIX,
                             'oauth_header': auth_header,
                             'app_email':pha.email}, 
                           type='xml')
Exemple #19
0
def get_connect_credentials(request, account, pha):
    """ Get oAuth credentials for an app to run in Connect or SMART REST mode.

    Generates access tokens for *pha* to run against the *record_id* specified in ``request.POST``, authorized by
    *account*. Generates 2 tokens: one for SMART Connect use, and one for SMART REST use.

    If the app is not yet enabled for the record/carenet, this will return a :http:statuscode:`403`.
    
    """

    carenet = record = None
    carenet_id = request.POST.get('carenet_id', None)
    record_id = request.POST.get('record_id', None)

    if carenet_id:
        try:
            carenet = Carenet.objects.get(id=carenet_id)
        except Carenet.DoesNotExist:
            raise Http404
        except Carenet.MultipleObjectsReturned:
            raise Exception(
                "Multiple carenets with same id--database is corrupt")

    elif record_id:
        try:
            record = Record.objects.get(id=record_id)
        except Record.DoesNotExist:
            raise Http404
        except Record.MultipleObjectsReturned:
            raise Exception(
                "Multiple records with same id--database is corrupt")

    # Make sure that the app is enabled
    if (record and not PHAShare.objects.filter(record=record, with_pha=pha).exists()) or \
            (carenet and not CarenetPHA.objects.filter(carenet=carenet, pha=pha).exists()):
        raise PermissionDenied(
            "Cannot generate credentials before app is enabled")

    # Generate the tokens
    from indivo.accesscontrol.oauth_servers import OAUTH_SERVER
    rest_token = OAUTH_SERVER.generate_and_preauthorize_access_token(
        pha, record=record, carenet=carenet, account=account)
    connect_token = OAUTH_SERVER.generate_and_preauthorize_access_token(
        pha, record=record, carenet=carenet, account=account)
    connect_token.connect_auth_p = True
    connect_token.save()

    # Generate a 2-legged oauth header for the rest token, based on the pha's start_url
    url = utils.url_interpolate(pha.start_url_template, {
        'record_id': record_id or '',
        'carenet_id': carenet_id or ''
    })
    request = HTTPRequest("GET", url, HTTPRequest.FORM_URLENCODED_TYPE, '', {})
    oauth_params = {
        'smart_container_api_base': settings.SITE_URL_PREFIX,
        'smart_oauth_token': rest_token.token,
        'smart_oauth_token_secret': rest_token.token_secret,
        'smart_user_id': account.email,
        'smart_app_id': pha.email,
        'smart_record_id': record_id,
    }
    oauth_request = OAuthRequest(
        consumer=pha,
        token=None,  # no access tokens: 2-legged request
        http_request=request,
        oauth_parameters=oauth_params)
    oauth_request.sign()
    auth_header = oauth_request.to_header()["Authorization"]

    return render_template('connect_credentials', {
        'connect_token': connect_token,
        'rest_token': rest_token,
        'api_base': settings.SITE_URL_PREFIX,
        'oauth_header': auth_header,
        'app_email': pha.email
    },
                           type='xml')