Example #1
0
 def __init__(self, *args, **kwargs):
     self.oauth_server = DataStoreServer(data_store=MockDataStore())
     self.oauth_server.add_signature_method(
         oauth2.SignatureMethod_PLAINTEXT())
     self.oauth_server.add_signature_method(
         oauth2.SignatureMethod_HMAC_SHA1())
     BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
Example #2
0
    def __init__(self,
                 consumer_key=None,
                 consumer_secret=None,
                 access_token_key=None,
                 access_token_secret=None,
                 cache=DEFAULT_CACHE,
                 cache_timeout=DEFAULT_CACHE_TIMEOUT
                 ):

        self.consumer_key = consumer_key
        self.consumer_secret = consumer_secret
        self.access_token_key = access_token_key
        self.access_token_secret = access_token_secret
        self.host = "api.yelp.com"
        self.SetCache(cache)
        self.SetCacheTimeout(cache_timeout)

        if consumer_key is not None \
            and consumer_secret is not None \
            and access_token_key is not None \
            and access_token_secret is not None:

            self._signature_method_plaintext = oauth.SignatureMethod_PLAINTEXT()
            self._signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1()

        self._oauth_token = oauth.Token(key=access_token_key, secret=access_token_secret)
        self._oauth_consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret)
Example #3
0
 def __init__(self, api_key, shared_secret, httplib2_inst=None):
     """Override init to ensure required args"""
     super(TwoLegged, self).__init__(api_key, shared_secret, httplib2_inst)
     self.endpoint = PRIVATE_ENDPOINT
     self.scheme = HTTPS_SCHEME
     self.hmac_sha1_signature = oauth.SignatureMethod_HMAC_SHA1()
     self.plaintext_signature = oauth.SignatureMethod_PLAINTEXT()
Example #4
0
def verify_oauth_request(request, oauth_request, consumer, token=None):
    """ Helper function to verify requests. """
    from treeio.core.api.auth.store import store

    # Check nonce
    if not store.check_nonce(request, oauth_request,
                             oauth_request['oauth_nonce']):
        return False

    # Verify request
    try:
        oauth_server = oauth.Server()
        oauth_server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1())
        oauth_server.add_signature_method(oauth.SignatureMethod_PLAINTEXT())

        # Ensure the passed keys and secrets are ascii, or HMAC will complain.
        consumer = oauth.Consumer(consumer.key.encode('ascii', 'ignore'),
                                  consumer.secret.encode('ascii', 'ignore'))
        if token is not None:
            token = oauth.Token(token.key.encode('ascii', 'ignore'),
                                token.secret.encode('ascii', 'ignore'))

        oauth_server.verify_request(oauth_request, consumer, token)
    except oauth.Error:
        return False

    return True
Example #5
0
    def test_sign_request(self):
        url = "http://sp.example.com/"

        params = {
            'oauth_version': "1.0",
            'oauth_nonce': "4572616e48616d6d65724c61686176",
            'oauth_timestamp': "137131200"
        }

        tok = oauth.Token(key="tok-test-key", secret="tok-test-secret")
        con = oauth.Consumer(key="con-test-key", secret="con-test-secret")

        params['oauth_token'] = tok.key
        params['oauth_consumer_key'] = con.key
        req = oauth.Request(method="GET", url=url, parameters=params)

        methods = {
            'TQ6vGQ5A6IZn8dmeGB4+/Jl3EMI=': oauth.SignatureMethod_HMAC_SHA1(),
            'con-test-secret&tok-test-secret':
            oauth.SignatureMethod_PLAINTEXT()
        }

        for exp, method in methods.items():
            req.sign_request(method, con, tok)
            self.assertEquals(req['oauth_signature_method'], method.name)
            self.assertEquals(req['oauth_signature'], exp)
Example #6
0
def new_client(token=None):
    """Generate a new ningapi.Client instance"""

    consumer = oauth.Consumer(key=CONSUMER_KEY, secret=CONSUMER_SECRET)
    client = ningapi.Client(NING_API_URL, NETWORK_SUBDOMAIN, consumer, token)
    client.method = oauth.SignatureMethod_PLAINTEXT()
    return client
Example #7
0
def verify_oauth_request(request, oauth_request, consumer, token=None):
    """ Helper function to verify requests. """
    from store import store

    # Check nonce
    if not store.check_nonce(request, oauth_request,
                             oauth_request['oauth_nonce']):
        return False

    # Verify request
    try:
        oauth_server = oauth.Server()
        oauth_server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1())
        oauth_server.add_signature_method(oauth.SignatureMethod_PLAINTEXT())

        # Ensure the passed keys and secrets are ascii, or HMAC will complain.
        consumer = oauth.Consumer(consumer.key.encode('ascii', 'ignore'),
                                  consumer.secret.encode('ascii', 'ignore'))
        if token is not None:
            token = oauth.Token(token.key.encode('ascii', 'ignore'),
                                token.secret.encode('ascii', 'ignore'))

        oauth_server.verify_request(oauth_request, consumer, token)
    except oauth.Error, err:
        logger.error('OAuth-request verification error',
                     extra={'data': {
                         'error': err.message
                     }})
        return False
Example #8
0
def initialize_server_request(request):
    """Shortcut for initialization."""
    # Django converts Authorization header in HTTP_AUTHORIZATION
    # Warning: it doesn't happen in tests but it's useful, do not remove!
    auth_header = {}
    if 'Authorization' in request.META:
        auth_header = {'Authorization': request.META['Authorization']}
    elif 'HTTP_AUTHORIZATION' in request.META:
        auth_header =  {'Authorization': request.META['HTTP_AUTHORIZATION']}
   
    # Don't include extra parameters when request.method is POST and 
    # request.MIME['CONTENT_TYPE'] is "application/x-www-form-urlencoded" 
    # (See http://oauth.net/core/1.0a/#consumer_req_param).
    # But there is an issue with Django's test Client and custom content types
    # so an ugly test is made here, if you find a better solution...
    parameters = {}
    if request.method == "POST" and \
        (request.META.get('CONTENT_TYPE') == "application/x-www-form-urlencoded" \
            or request.META.get('SERVER_NAME') == 'testserver'):
        parameters = dict((k, v.encode('utf-8')) for (k, v) in request.REQUEST.iteritems())

    oauth_request = oauth.Request.from_request(request.method, 
                                              request.build_absolute_uri(request.path), 
                                              headers=auth_header,
                                              parameters=parameters,
                                              query_string=request.META.get('QUERY_STRING', ''))
    if oauth_request:
        oauth_server = oauth.Server()
        if 'plaintext' in OAUTH_SIGNATURE_METHODS:
            oauth_server.add_signature_method(oauth.SignatureMethod_PLAINTEXT())
        if 'hmac-sha1' in OAUTH_SIGNATURE_METHODS:
            oauth_server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1())
    else:
        oauth_server = None
    return oauth_server, oauth_request
Example #9
0
 def getInstance(cls):
     if cls._instance == None:
         cls._instance = oauth.Server()
         cls._instance.add_signature_method(
             oauth.SignatureMethod_PLAINTEXT())
         cls._instance.add_signature_method(
             oauth.SignatureMethod_HMAC_SHA1())
     return cls._instance
Example #10
0
 def oauth_signed_request(self, req):
     """Signs any request using OAuth. Mandatory before any request of access upon OAuth-protected data"""
     oauth_request = oauth2.Request.from_consumer_and_token(
         self.consumer, self.token, req.method, req.url)
     oauth_request.sign_request(oauth2.SignatureMethod_PLAINTEXT(),
                                self.consumer, self.token)
     for header, value in oauth_request.to_header().items():
         req.headers[header] = value
     rep = self.session.send(req.prepare())
     rep.raise_for_status()
     return rep
Example #11
0
 def __init__(self, num=0):
     if (TOKEN_KEY[num] and TOKEN_SECRET[num]):
         self._signature_method_plaintext = oauth.SignatureMethod_PLAINTEXT(
         )
         self._signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1(
         )
         self._oauth_token = oauth.Token(key=TOKEN_KEY[num],
                                         secret=TOKEN_SECRET[num])
         self._oauth_consumer = oauth.Consumer(key=CONSUMER_KEY,
                                               secret=CONSUMER_SECRET)
     else:
         exit()
Example #12
0
def initialize_server_request(request):
    """Shortcut for initialization."""
    oauth_request = get_oauth_request(request)

    if oauth_request:
        oauth_server = oauth.Server()
        if 'plaintext' in OAUTH_SIGNATURE_METHODS:
            oauth_server.add_signature_method(oauth.SignatureMethod_PLAINTEXT())
        if 'hmac-sha1' in OAUTH_SIGNATURE_METHODS:
            oauth_server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1())
    else:
        oauth_server = None
    return oauth_server, oauth_request
Example #13
0
 def _get_request(self, method='GET', parameters=None, use_token=True):
     consumer = oauth.Consumer(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET)
     if use_token:
         token = oauth.Token(OAUTH_TOKEN_KEY, OAUTH_TOKEN_SECRET)
     else:
         token = None
     request = oauth.Request.from_consumer_and_token(consumer,
                                                     token,
                                                     http_method=method,
                                                     parameters=parameters)
     request.sign_request(oauth.SignatureMethod_PLAINTEXT(), consumer,
                          token)
     return request
Example #14
0
    def test_add_signature_method(self):
        server = oauth.Server()
        res = server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1())
        self.assertTrue(len(res) == 1)
        self.assertTrue('HMAC-SHA1' in res)
        self.assertTrue(
            isinstance(res['HMAC-SHA1'], oauth.SignatureMethod_HMAC_SHA1))

        res = server.add_signature_method(oauth.SignatureMethod_PLAINTEXT())
        self.assertTrue(len(res) == 2)
        self.assertTrue('PLAINTEXT' in res)
        self.assertTrue(
            isinstance(res['PLAINTEXT'], oauth.SignatureMethod_PLAINTEXT))
    def __init__(self, subdomain):
        self.request_token_url = 'http://%s.%s%s' % (
            subdomain, config.LOGGLY_DOMAIN, config.OAUTH_REQUEST_TOKEN_PATH)
        self.access_token_url = 'http://%s.%s%s' % (
            subdomain, config.LOGGLY_DOMAIN, config.OAUTH_ACCESS_TOKEN_PATH)
        self.authorize_url = 'http://%s.%s%s' % (
            subdomain, config.LOGGLY_DOMAIN, config.OAUTH_AUTHORIZE_PATH)
        self.callback_url = config.OAUTH_CALLBACK_URL
        self.consumer = oauth.Consumer(config.OAUTH_CONSUMER_KEY,
                                       config.OAUTH_CONSUMER_SECRET)
        self.signature_method_plaintext = oauth.SignatureMethod_PLAINTEXT()
        self.signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1()

        self.connection = httplib.HTTPConnection(config.AB_DOMAIN)
Example #16
0
 def GetRequestToken(self):
     connection = httplib.HTTPSConnection(FitBit.config.SERVER)
     consumer = oauth.Consumer(FitBit.config.CONSUMER_KEY,
                               FitBit.config.CONSUMER_SECRET)
     signature_method = oauth.SignatureMethod_PLAINTEXT()
     oauth_request = oauth.Request.from_consumer_and_token(
         consumer, http_url=FitBit.config.REQUEST_TOKEN_URL)
     oauth_request.sign_request(signature_method, consumer, None)
     resp = self.FetchResponse(oauth_request, connection,
                               FitBit.config.REQUEST_TOKEN_URL)
     auth_token = oauth.Token.from_string(resp)
     auth_url = "%s?oauth_token=%s" % (FitBit.config.AUTHORIZATION_URL,
                                       auth_token.key)
     return auth_url, auth_token
Example #17
0
 def GetRequestToken(self):
     connection = httplib.HTTPSConnection(self.SERVER)
     consumer = oauth.Consumer(self.CONSUMER_KEY, self.CONSUMER_SECRET)
     signature_method = oauth.SignatureMethod_PLAINTEXT()
     oauth_request = oauth.Request.from_consumer_and_token(
         consumer, http_url=self.REQUEST_TOKEN_URL)
     oauth_request.sign_request(signature_method, consumer, None)
     resp = self.FetchResponse(
         oauth_request, connection,
         self.REQUEST_TOKEN_URL)  #passing in explicit url
     print resp
     auth_token = oauth.Token.from_string(resp)
     auth_url = "%s?oauth_token=%s" % (
         self.AUTHORIZATION_URL, auth_token.key)  #build the URL
     return auth_url, auth_token
Example #18
0
    def __init__(self,
                 consumer_key=None,
                 consumer_secret=None,
                 access_token_key=None,
                 access_token_secret=None):
        self._consumer_key        = consumer_key
        self._consumer_secret     = consumer_secret
        self._access_token_key    = access_token_key
        self._access_token_secret = access_token_secret

        self._signature_method_plaintext = oauth.SignatureMethod_PLAINTEXT()
        self._signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1()

        self._oauth_token    = oauth.Token(key=access_token_key, secret=access_token_secret)
        self._oauth_consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret)
Example #19
0
 def ApiCall(self, access_token, apiCall):
     signature_method = oauth.SignatureMethod_PLAINTEXT()
     connection = httplib.HTTPSConnection(FitBit.config.SERVER)
     #build the access token from a string
     access_token = oauth.Token.from_string(access_token)
     consumer = oauth.Consumer(FitBit.config.CONSUMER_KEY,
                               FitBit.config.CONSUMER_SECRET)
     final_url = 'https://' + FitBit.config.SERVER + apiCall
     oauth_request = oauth.Request.from_consumer_and_token(
         consumer, token=access_token, http_url=final_url)
     oauth_request.sign_request(signature_method, consumer, access_token)
     headers = oauth_request.to_header(realm='api.fitbit.com')
     connection.request('GET', apiCall, headers=headers)
     resp = connection.getresponse()
     response = resp.read()
     return response
Example #20
0
    def _create_authorization_url_parameters(self):
        params = {
            'oauth_version': "1.0",
            'oauth_nonce': oauth.generate_nonce(),
            'oauth_timestamp': int(time.time()),
            'oauth_token': self.token.key,
            'oauth_consumer_key': self.consumer.key
        }

        req = oauth.Request(method="GET",
                            url="http://example.com",
                            parameters=params)

        signature_method = oauth.SignatureMethod_PLAINTEXT()
        req.sign_request(signature_method, self.consumer, self.token)
        return dict(req)
Example #21
0
    def request(self, api_call, extra_params=None):
        self.parameters = {
            'oauth_signature_method': oauth2.SignatureMethod_PLAINTEXT.name,
            'oauth_timestamp': oauth2.generate_timestamp(),
            'oauth_nonce': oauth2.generate_nonce(),
            'oauth_version': '1.0',
        }
        if type(extra_params) is dict:
            self.parameters.update(extra_params)

        self.req = oauth2.Request(url=api_call, parameters=self.parameters)
        self.req.sign_request(
            signature_method=oauth2.SignatureMethod_PLAINTEXT(),
            token=self.user_token,
            consumer=self.cons_token)
        return self.req
    def create_headers(self) -> dict:
        (consumer_key, key, secret) = self.maas_api_key.split(':')

        resource_token_string = "oauth_token_secret={}&oauth_token={}".format(secret, key)
        resource_token = oauth.Token.from_string(resource_token_string)

        consumer_token = oauth.Consumer(consumer_key, "")

        oauth_request = oauth.Request.from_consumer_and_token(
            consumer_token, token=resource_token, http_url=self.maas_api_url,
            parameters={'auth_nonce': uuid.uuid4().hex})

        oauth_request.sign_request(oauth.SignatureMethod_PLAINTEXT(), consumer_token, resource_token)
        headers = oauth_request.to_header()
        headers['Accept'] = 'application/json'

        return headers
Example #23
0
def _logglyAuth(request):
    '''
    Perform an authorization request to Loggly.com for accessing a user's 
    account.
    
    Keyword arguments:
    request -- the request object.
    
    Return:
    Redirect the user to Loggly.com's for giving access to AfterGlow.
    '''

    # Construct a consumer object.
    consumer = oauth.Consumer(key=settings.LOGGLY_OAUTH_CONSUMER_KEY,
                              secret=settings.LOGGLY_OAUTH_CONSUMER_SECRET)

    request_token_url = "http://%s.loggly.com/api/oauth/request_token/" % (
        request.POST['logglySubdomain'])
    authorize_url = "http://%s.loggly.com/api/oauth/authorize/" % (
        request.POST['logglySubdomain'])

    client = oauth.Client(consumer)

    # Change the signature method to PLAINTEXT.
    method = oauth.SignatureMethod_PLAINTEXT()
    client.set_signature_method(method)

    # Request a token.
    resp, content = client.request(request_token_url,
                                   method="POST",
                                   body=urllib.urlencode({
                                       'oauth_callback':
                                       settings.LOGGLY_OAUTH_CALLBACK
                                   }))
    request_token = dict(urlparse.parse_qsl(content))

    # Store the subdomain and token secret in the session.
    request.session["logglyTokenSecret"] = request_token['oauth_token_secret']
    request.session["logglySubdomain"] = request.POST['logglySubdomain']

    # Redirect the user to Loggly's webpage for granting/denying access.
    return redirect("%s?oauth_token=%s" %
                    (authorize_url, request_token['oauth_token']))
Example #24
0
 def GetAccessToken(self, access_code, auth_token):
     oauth_verifier = access_code
     connection = httplib.HTTPSConnection(FitBit.config.SERVER)
     consumer = oauth.Consumer(FitBit.config.CONSUMER_KEY,
                               FitBit.config.CONSUMER_SECRET)
     signature_method = oauth.SignatureMethod_PLAINTEXT()
     oauth_request = oauth.Request.from_consumer_and_token(
         consumer,
         token=auth_token,
         http_url=FitBit.config.ACCESS_TOKEN_URL,
         parameters={'oauth_verifier': oauth_verifier})
     oauth_request.sign_request(signature_method, consumer, auth_token)
     # now the token we get back is an access token
     access_token = oauth.Token.from_string(
         self.FetchResponse(oauth_request, connection,
                            FitBit.config.ACCESS_TOKEN_URL))
     # store the access token when returning it
     access_token = access_token.to_string()
     return access_token
Example #25
0
 def GetAccessToken(self, access_code, auth_token, oauth_verifier):
     auth_token = oauth.Token.from_string(auth_token)
     oauth_verifier = oauth_verifier
     connection = httplib.HTTPSConnection(self.SERVER)
     consumer = oauth.Consumer(self.CONSUMER_KEY, self.CONSUMER_SECRET)
     signature_method = oauth.SignatureMethod_PLAINTEXT()
     oauth_request = oauth.Request.from_consumer_and_token(
         consumer,
         token=auth_token,
         http_url=self.ACCESS_TOKEN_URL,
         parameters={'oauth_verifier': oauth_verifier})
     oauth_request.sign_request(signature_method, consumer, auth_token)
     # now the token we get back is an access token
     resp = self.FetchResponse(oauth_request, connection,
                               self.ACCESS_TOKEN_URL)
     access_token = oauth.Token.from_string(
         resp
     )  # parse the response into an OAuthToken object / passingin explicit url
     # store the access token when returning it
     # access_token = access_token.to_string()
     return access_token
Example #26
0
    def ApiCall(self,
                access_token,
                apiCall='/1/user/-/activities/log/steps/date/today/1d.json'):
        #other API Calls possible, or read the FitBit documentation for the full list.
        #apiCall = '/1/user/-/devices.json'
        #apiCall = '/1/user/-/profile.json'
        #apiCall = '/1/user/-/activities/date/2011-06-17.json'

        signature_method = oauth.SignatureMethod_PLAINTEXT()
        connection = httplib.HTTPSConnection(self.SERVER)
        #build the access token from a string
        access_token = oauth.Token.from_string(access_token)
        consumer = oauth.Consumer(self.CONSUMER_KEY, self.CONSUMER_SECRET)
        final_url = 'http://' + self.SERVER + apiCall
        oauth_request = oauth.Request.from_consumer_and_token(
            consumer, token=access_token, http_url=final_url)
        oauth_request.sign_request(signature_method, consumer, access_token)
        headers = oauth_request.to_header(realm='api.fitbit.com')
        connection.request('GET', apiCall, headers=headers)
        resp = connection.getresponse()
        response = resp.read()
        return response
Example #27
0
def verify_oauth_request(request, oauth_request, consumer, token=None):
    """ Helper function to verify requests. """
    from store import store

    # Check nonce
    #print 'Nonce: %s' % store.check_nonce(request, oauth_request, oauth_request['oauth_nonce'], oauth_request['oauth_timestamp'])
    if not store.check_nonce(request, oauth_request,
                             oauth_request['oauth_nonce'],
                             oauth_request['oauth_timestamp']):
        #print 'nonce check fail'
        return False

    print 'Nonce: true'

    # Verify request
    try:
        oauth_server = oauth.Server()
        oauth_server.add_signature_method(oauth.SignatureMethod_HMAC_SHA1())
        oauth_server.add_signature_method(oauth.SignatureMethod_PLAINTEXT())
        oauth_server.add_signature_method(SignatureMethod_RSA_SHA1())

        # Ensure the passed keys and secrets are ascii, or HMAC will complain.
        consumer = oauth.Consumer(consumer.key.encode('ascii', 'ignore'),
                                  consumer.secret.encode('ascii', 'ignore'))
        if token is not None:
            token = oauth.Token(token.key.encode('ascii', 'ignore'),
                                token.secret.encode('ascii', 'ignore'))

        print 'normalized parameters: %s' % oauth_request.get_normalized_parameters(
        )

        oauth_server.verify_request(oauth_request, consumer, token)
    except oauth.Error as o:
        print o.message
        return False

    return True
Example #28
0
def index():

    # Basic processing of the LTI request starts here
    # this first block is about getting the user information provided by the LMS
    myrecord = None
    consumer = None
    masterapp = None
    userinfo = None

    user_id = request.vars.get("user_id", None)
    last_name = request.vars.get("lis_person_name_family", None)
    first_name = request.vars.get("lis_person_name_given", None)
    full_name = request.vars.get("lis_person_name_full", None)
    message_type = request.vars.get("lti_message_type")
    course_id = _param_converter(request.vars.get("custom_course_id", None))

    if course_id:
        # Allow the course_id to be either a number or the name of the course, as a string.
        try:
            course_id = int(course_id)
        except ValueError:
            course_id = (db(db.courses.course_name == course_id).select(
                **SELECT_CACHE).first())
            course_id = course_id.id

    if full_name and not last_name:
        names = full_name.strip().split()
        last_name = names[-1]
        first_name = " ".join(names[:-1])
    email = request.vars.get("lis_person_contact_email_primary", None)
    instructor = ("Instructor" in request.vars.get(
        "roles", [])) or ("TeachingAssistant" in request.vars.get("roles", []))
    result_source_did = request.vars.get("lis_result_sourcedid", None)
    outcome_url = request.vars.get("lis_outcome_service_url", None)
    # Deprecated: the use of the non-LTI-compliant name ``assignment_id``. The parameter should be ``custom_assignment_id``.
    assignment_id = _param_converter(
        request.vars.get("custom_assignment_id",
                         request.vars.get("assignment_id", None)))
    practice = request.vars.get("practice", None)

    if user_id is None:
        return dict(
            logged_in=False,
            lti_errors=[
                "user_id is required for this tool to function", request.vars
            ],
            masterapp=masterapp,
        )
    elif first_name is None:
        return dict(
            logged_in=False,
            lti_errors=[
                "First Name is required for this tool to function",
                request.vars,
            ],
            masterapp=masterapp,
        )
    elif last_name is None:
        return dict(
            logged_in=False,
            lti_errors=[
                "Last Name is required for this tool to function",
                request.vars,
            ],
            masterapp=masterapp,
        )
    elif email is None:
        return dict(
            logged_in=False,
            lti_errors=[
                "Email is required for this tool to function", request.vars
            ],
            masterapp=masterapp,
        )
    else:
        userinfo = dict()
        userinfo["first_name"] = first_name
        userinfo["last_name"] = last_name
        # In the `Canvas Student View <https://community.canvaslms.com/docs/DOC-13122-415261153>`_ as of 7-Jan-2019, the ``lis_person_contact_email_primary`` is an empty string. In this case, use the userid instead.
        email = email or (user_id + "@junk.com")
        userinfo["email"] = email

    # Now we need to get some security info
    # oauth_consumer_key

    key = request.vars.get("oauth_consumer_key", None)
    if key is not None:
        myrecord = db(db.lti_keys.consumer == key).select().first()
        if myrecord is None:
            return dict(
                logged_in=False,
                lti_errors=["Could not find oauth_consumer_key", request.vars],
                masterapp=masterapp,
            )
        else:
            session.oauth_consumer_key = key
    if myrecord is not None:
        masterapp = myrecord.application
        if len(masterapp) < 1:
            masterapp = "welcome"
        session.connect(request, response, masterapp=masterapp, db=db)

        oauth_server = oauth2.Server()
        oauth_server.add_signature_method(oauth2.SignatureMethod_PLAINTEXT())
        oauth_server.add_signature_method(oauth2.SignatureMethod_HMAC_SHA1())

        # Use ``setting.lti_uri`` if it's defined; otherwise, use the current URI (which must be built from its components). Don't include query parameters, which causes a failure in OAuth security validation.
        full_uri = settings.get(
            "lti_uri",
            "{}://{}{}".format(request.env.wsgi_url_scheme,
                               request.env.http_host, request.url),
        )
        oauth_request = oauth2.Request.from_request(
            "POST",
            full_uri,
            None,
            dict(request.vars),
            query_string=request.env.query_string,
        )
        # Fix encoding -- the signed keys are in bytes, but the oauth2 Request constructor translates everything to a string. Therefore, they never compare as equal. ???
        if isinstance(oauth_request.get("oauth_signature"), str):
            oauth_request["oauth_signature"] = oauth_request[
                "oauth_signature"].encode("utf-8")
        consumer = oauth2.Consumer(myrecord.consumer, myrecord.secret)

        try:
            oauth_server.verify_request(oauth_request, consumer, None)
        except oauth2.Error as err:
            return dict(
                logged_in=False,
                lti_errors=[
                    "OAuth Security Validation failed:" + err.message,
                    request.vars,
                ],
                masterapp=masterapp,
            )
            consumer = None
    ###############################################################################
    # I think everything from the beginning to here could/should be refactored into
    # a validate function.  Or make use of the lti package

    # Time to create / update / login the user
    if userinfo and (consumer is not None):
        userinfo["username"] = email
        # Only assign a password if we're creating the user. The
        # ``get_or_create_user`` method checks for an existing user using both
        # the username and the email.
        update_fields = ["email", "first_name", "last_name"]
        if (not db((db.auth_user.username == userinfo["username"])
                   | (db.auth_user.email == userinfo["email"])).select(
                       db.auth_user.id).first()):
            pw = db.auth_user.password.validate(str(uuid.uuid4()))[0]
            userinfo["password"] = pw
            update_fields.append("password")
        user = auth.get_or_create_user(userinfo, update_fields=update_fields)
        if user is None:
            return dict(
                logged_in=False,
                lti_errors=["Unable to create user record", request.vars],
                masterapp=masterapp,
            )
        # user exists; make sure course name and id are set based on custom parameters passed, if this is for runestone. As noted for ``assignment_id``, parameters are passed as a two-element list.
        # course_id = _param_converter(request.vars.get("custom_course_id", None))
        # if the instructor uses their course name instead of its id number then get the number.

        if course_id:
            user["course_id"] = course_id
            user["course_name"] = getCourseNameFromId(
                course_id
            )  # need to set course_name because calls to verifyInstructor use it
            user.update_record()

            # Update instructor status.
            # TODO: this block should be removed.  The only way to become an instructor
            # is through Runestone
            if instructor:
                # Give the instructor free access to the book.
                db.user_courses.update_or_insert(user_id=user.id,
                                                 course_id=course_id)
                db.course_instructor.update_or_insert(instructor=user.id,
                                                      course=course_id)
            else:
                # Make sure previous instructors are removed from the instructor list.
                db((db.course_instructor.instructor == user.id)
                   & (db.course_instructor.course == course_id)).delete()

            # Before creating a new user_courses record:
            if (not db((db.user_courses.user_id == user.id)
                       & (db.user_courses.course_id == course_id)).select().
                    first()):
                # In academy mode, present payment or donation options, per the discussion at https://github.com/RunestoneInteractive/RunestoneServer/pull/1322.
                if settings.academy_mode:
                    # To do so, store the current URL, so this request can be completed after creating the user.
                    # TODO: this doesn't work, since the ``course_id``` and ``assignment_id`` aren't saved in this redirect. Therefore, these should be stored (perhaps in ``session``) then used after a user pays / donates.
                    session.lti_url_next = full_uri
                    auth.login_user(user)
                    redirect(URL(c="default"))
                else:
                    # Otherwise, simply create the user.
                    db.user_courses.update_or_insert(user_id=user.id,
                                                     course_id=course_id)

        auth.login_user(user)

    if message_type == "ContentItemSelectionRequest":
        return _provide_assignment_list(course_id, consumer)

    elif assignment_id:
        # If the assignment is released, but this is the first time a student has visited the assignment, auto-upload the grade.
        _launch_assignment(assignment_id, user, result_source_did, outcome_url)
        # If we got here, the assignment wasn't launched.
        return dict(
            logged_in=False,
            lti_errors=[
                f"Invalid assignment id {assignment_id}; please contact your instructor.",
                request.vars,
            ],
            masterapp=masterapp,
        )

    elif practice:
        _launch_practice(outcome_url, result_source_did, user, course_id)

    # else just redirect to the book index
    redirect(get_course_url("index.html"))
Example #29
0
 def server(self):
     result = oauth.Server()
     result.add_signature_method(oauth.SignatureMethod_PLAINTEXT())
     result.add_signature_method(oauth.SignatureMethod_HMAC_SHA1())
     return result
Example #30
0
def index():
    myrecord = None
    consumer = None
    masterapp = None
    userinfo = None

    user_id = request.vars.get('user_id', None)
    last_name = request.vars.get('lis_person_name_family', None)
    first_name = request.vars.get('lis_person_name_given', None)
    full_name = request.vars.get('lis_person_name_full', None)
    if full_name and not last_name:
        names = full_name.strip().split()
        last_name = names[-1]
        first_name = ' '.join(names[:-1])
    email = request.vars.get('lis_person_contact_email_primary', None)
    instructor = ("Instructor" in request.vars.get('roles', [])) or \
                 ("TeachingAssistant" in request.vars.get('roles', []))
    result_source_did=request.vars.get('lis_result_sourcedid', None)
    outcome_url=request.vars.get('lis_outcome_service_url', None)
    assignment_id = _param_converter(request.vars.get('assignment_id', None))
    practice = request.vars.get('practice', None)

    if user_id is None :
        return dict(logged_in=False, lti_errors=["user_id is required for this tool to function", request.vars], masterapp=masterapp)
    elif first_name is None :
        return dict(logged_in=False, lti_errors=["First Name is required for this tool to function", request.vars], masterapp=masterapp)
    elif last_name is None :
        return dict(logged_in=False, lti_errors=["Last Name is required for this tool to function", request.vars], masterapp=masterapp)
    elif email is None :
        return dict(logged_in=False, lti_errors=["Email is required for this tool to function", request.vars], masterapp=masterapp)
    else :
        userinfo = dict()
        userinfo['first_name'] = first_name
        userinfo['last_name'] = last_name
        # In the `Canvas Student View <https://community.canvaslms.com/docs/DOC-13122-415261153>`_ as of 7-Jan-2019, the ``lis_person_contact_email_primary`` is an empty string. In this case, use the userid instead.
        email = email or (user_id + '@junk.com')
        userinfo['email'] = email

    key = request.vars.get('oauth_consumer_key', None)
    if key is not None:
        myrecord = db(db.lti_keys.consumer==key).select().first()
        if myrecord is None :
            return dict(logged_in=False, lti_errors=["Could not find oauth_consumer_key", request.vars],
                        masterapp=masterapp)
        else:
            session.oauth_consumer_key = key
    if myrecord is not None :
        masterapp = myrecord.application
        if len(masterapp) < 1 :
            masterapp = 'welcome'
        session.connect(request, response, masterapp=masterapp, db=db)

        oauth_server = oauth2.Server()
        oauth_server.add_signature_method(oauth2.SignatureMethod_PLAINTEXT())
        oauth_server.add_signature_method(oauth2.SignatureMethod_HMAC_SHA1())

        # Use ``setting.lti_uri`` if it's defined; otherwise, use the current URI (which must be built from its components). Don't include query parameters, which causes a failure in OAuth security validation.
        full_uri = settings.get('lti_uri', '{}://{}{}'.format(
            request.env.wsgi_url_scheme, request.env.http_host, request.url
        ))
        oauth_request = oauth2.Request.from_request(
            'POST', full_uri, None, dict(request.vars),
            query_string=request.env.query_string
        )
        # Fix encoding -- the signed keys are in bytes, but the oauth2 Request constructor translates everything to a string. Therefore, they never compare as equal. ???
        if isinstance(oauth_request.get('oauth_signature'), six.string_types):
            oauth_request['oauth_signature'] = oauth_request['oauth_signature'].encode('utf-8')
        consumer = oauth2.Consumer(myrecord.consumer, myrecord.secret)

        try:
            oauth_server.verify_request(oauth_request, consumer, None)
        except oauth2.Error as err:
            return dict(logged_in=False, lti_errors=["OAuth Security Validation failed:"+err.message, request.vars],
                        masterapp=masterapp)
            consumer = None

    # Time to create / update / login the user
    if userinfo and (consumer is not None):
        userinfo['username'] = email
        # Only assign a password if we're creating the user. The
        # ``get_or_create_user`` method checks for an existing user using both
        # the username and the email.
        update_fields = ['email', 'first_name', 'last_name']
        if not db(
            (db.auth_user.username == userinfo['username']) |
            (db.auth_user.email == userinfo['email'])
        ).select(db.auth_user.id).first():
            pw = db.auth_user.password.validate(str(uuid.uuid4()))[0]
            userinfo['password'] = pw
            update_fields.append('password')
        user = auth.get_or_create_user(userinfo, update_fields=update_fields)
        if user is None:
            return dict(logged_in=False, lti_errors=["Unable to create user record", request.vars],
                        masterapp=masterapp)
        # user exists; make sure course name and id are set based on custom parameters passed, if this is for runestone. As noted for ``assignment_id``, parameters are passed as a two-element list.
        course_id = _param_converter(request.vars.get('custom_course_id', None))
        section_id = _param_converter(request.vars.get('custom_section_id', None))
        if course_id:
            user['course_id'] = course_id
            user['course_name'] = getCourseNameFromId(course_id)    # need to set course_name because calls to verifyInstructor use it
            user['section'] = section_id
            user.update_record()

            # Update instructor status.
            if instructor:
                # Give the instructor free access to the book.
                db.user_courses.update_or_insert(user_id=user.id, course_id=course_id)
                db.course_instructor.update_or_insert(instructor=user.id, course=course_id)
            else:
                db((db.course_instructor.instructor == user.id) &
                   (db.course_instructor.course == course_id)).delete()

            # Before creating a new user_courses record, present payment or donation options.
            if not db((db.user_courses.user_id==user.id) &
                      (db.user_courses.course_id==course_id)).select().first():
                # Store the current URL, so this request can be completed after creating the user.
                session.lti_url_next = full_uri
                auth.login_user(user)
                redirect(URL(c='default'))

        if section_id:
            # set the section in the section_users table
            # test this
            db.section_users.update_or_insert(db.section_users.auth_user == user['id'], auth_user=user['id'], section = section_id)

        auth.login_user(user)

    if assignment_id:
        # If the assignment is released, but this is the first time a student has visited the assignment, auto-upload the grade.
        assignment = db(db.assignments.id == assignment_id).select(
            db.assignments.released).first()
        grade = db(
            (db.grades.auth_user == user.id) &
            (db.grades.assignment == assignment_id)
        ).select(db.grades.lis_result_sourcedid, db.grades.lis_outcome_url).first()
        send_grade = (assignment and assignment.released and grade and
                      not grade.lis_result_sourcedid and
                      not grade.lis_outcome_url)

        # save the guid and url for reporting back the grade
        db.grades.update_or_insert((db.grades.auth_user == user.id) & (db.grades.assignment == assignment_id),
                                   auth_user=user.id,
                                   assignment=assignment_id,
                                   lis_result_sourcedid=result_source_did,
                                   lis_outcome_url=outcome_url)
        if send_grade:
            _try_to_send_lti_grade(user.id, assignment_id)

        redirect(URL('assignments', 'doAssignment', vars={'assignment_id':assignment_id}))

    elif practice:
        if outcome_url and result_source_did:
            db.practice_grades.update_or_insert((db.practice_grades.auth_user == user.id),
                                                auth_user=user.id,
                                                lis_result_sourcedid=result_source_did,
                                                lis_outcome_url=outcome_url,
                                                course_name=getCourseNameFromId(course_id))
        else: # don't overwrite outcome_url and result_source_did
            db.practice_grades.update_or_insert((db.practice_grades.auth_user == user.id),
                                                auth_user=user.id,
                                                course_name=getCourseNameFromId(course_id))
        redirect(URL('assignments', 'settz_then_practice', vars={'course_name':user['course_name']}))

    redirect(get_course_url('index.html'))