3.4. IMS Basic Learning Tools Interoperability (version 1.0)¶
The IMS Basic Learning Tools Interoperability (BLTI) specification was released in 2010. The purpose of the specification is to provide a link between tool consumers (such as Learning Management Systems and portals) and Tools (such as specialist assessment management systems). Official information about the specification is available from the IMS GLC under the general name LTI:
This module implements the Basic LTI specification documented in the Best Practice Guide
This module requires the oauthlib module to be installed. The oauthlib module is available from PyPi.
This module is written from the point of view of the Tool Provider. There are a number of pre-defined classes to help you implement LTI in your own Python applications.
3.4.1. Classes¶
The ToolProviderApp
class is a mini-web framework in itself
which makes writing LTI tools much easier. The framework does not
include a page templating language but it should be easy to integrate
with your templating system of choice.
Instances of ToolProviderApp are callable objects that support the WSGI protocol for ease of integration into a wide variety of deployment scenarios.
The base class implementation takes care of many aspects of your LTI tool:
- Application settings are read from a JSON-encoded settings file.
- Data storage is configured using one of the concrete implementations of Pyslet’s own data access layer API. No SQL necessary in your code, minimising the risk of SQL injection vulnerabilities!
- Session handling: the base class handles the setting of a session cookie and an initial set of redirects to ensure that cookies are being supported properly by the browser. If session handling is broken a fail page method is called. The session logic contains special measures to prevent common session-related attacks (such as session fixation, hijacking and cross-site request forgery) and the redirection sequence is designed to overcome limitaions imposed by broswer restrictions on third party cookies or P3P-related policy issues by providing a user-actionable flow, opening your tool in a new window if necessary. End user messages are customisable.
- Launch authorisation is handled automatically, launch requests are checked using OAuth for validity and rejected automatically if invalid. Successful requests are automatically redirected to a resource-specific page.
- Each resource is given its own path in your application of the form
/<script.wsgi>/resource/<id>/ allowing you to spread your tool
application across multiple pages if necessary. A special method,
ToolProviderApp.load_visit()
, is provided to extract the resource ID from the URL path and load the corresponding entity from the data store. This method also loads the related entities for the the context, user and visit entities from the session according to the parameters passed in the original launch. - An overridable tool permission model is provided with a default implementation that provides read/write/configure permissions to Instructors (and sub-roles) and read permissions to Learners (and sub-roles). This enables your tool to simply test a permission bit at runtime to determine whether or not to display certain page elements.
- Tools can be launched multiple times in the same browser session. Authorisations remain active allowing the user to interact with your tool in separate tabs or even in multiple iframes on the same page. Authorisations are automatically expired if a conflicting launch request is received. In other words, if a browser session receives a new launch from the same consumer but for a different user then all the previous user’s activity is automatically logged out.
- Consumer secrets can be encrypted when persisted in the data store using an application key. By default the application key is configured in the settings file. (The PyCrypto module is required for encryption.)
The ToolConsumer
and ToolProvider
classes are largely
for internal use. You may want to use them if you are integrating the
basic LTI functionality into a different web framework, they contain
utility methods for reading information from the data store. You would
use the ToolProvider.launch()
method in your application when the
user POSTs to your launch endpoint to check that the LTI launch has been
authorised.
3.4.2. The Data Model¶
Implementing LTI requires some data storage to persist information between HTTP requests. This module is written using Pyslet’s own data access layer, based on the concepts of OData. For more information see The Open Data Protocol (OData).
A sample metadata file describing the required elements of the model is available as part of Pyslet itself. The entity sets (cf SQL Tables) it describes are as follows:
- AppKeys
- This entity set is used to store information about encryption keys
used to encrypt the consumer secrets in the data store. For more
information see
pyslet.wsgi.WSGIDataApp
- Silos
- This entity set is the root of the information space for each tool. LTI tools tend to be multi-tenanted, that is, the same tool application can be used by multiple consumers with complete isolation between each consumer’s data. The Silo provides this level of protection. Normally, each Silo will link to a single consumer but there may be cases where two or more consumers should share some data, in these cases a single Silo may link to multiple consumers.
- Consumers
- This entity set contains information about the tool consumers. Each consumer is identified by a consumer key and access is protected using a consumer secret (which can be stored in an encrypted form in the data store).
- Nonces
- LTI tools are launched from the consumer using OAuth. The protocol requires the use of a nonce (number used once only) to prevent the launch request being ‘replayed’ by an unauthorised person. This entity set is used to record which nonces have been used and when.
- Resources
- The primary launch concept in LTI is the resource. Every launch must have a resource_link_id which identifies the specific ‘place’ or ‘page’ in which the tool has been placed.
- Contexts
- LTI defines a context as an optional course or group-like organisation that provides context for a launch request. The context provides another potential scope for sharing data across launches.
- Users
- An LTI launch is typically identifed with a specific user of the Tool Consumer (though this isn’t required). Information about the users is recorded in the data store so that they can be associated with any data generated by the tool using simple extensions to the data model.
- Visits
- Each time someone launches your tool a visit entity is created with information about the resource, the context and the user.
- Sessions
- Used to store information about the browser session, see
pyslet.wsgi.SessionApp
for details. The basic session entity is extended to link to the visits that are active (i.e., currently authorised) for this session.
These entities are related using navigation properties enabling you to determine, for example, which Consumer a Resource belongs to, which Visits are active in a Session, and so on.
You can extend the core model by adding additional data properties (which should be nullable) or by adding optional navigation properties. For example, you might create an entity set to store information created by users of the tool and add a navigation property from the User entity to your new entity to indicate ownership. The sample Noticeboard application uses this technique and can be used as a guide.
3.4.2.1. Hello LTI¶
Writing your first LTI tool is easy:
from optparse import OptionParser
import pyslet.imsbltiv1p0 as lti
if __name__ == '__main__':
parser = OptionParser()
lti.ToolProviderApp.add_options(parser)
(options, args) = parser.parse_args()
lti.ToolProviderApp.setup(options, args)
app = lti.ToolProviderApp()
app.run_server()
Save this script as mytool.py and run it from the command line like this:
$ python mytool.py --help
Built-in to the WSGI base classes is support for running your tool from the command line during development. The script above just uses Python’s builtin options parsing feature to set up the tool class before creating an instance (the WSGI callable object) and running a basic WSGI server using Python’s builtin wsgiref module.
Try running your application with the -m and –create_silo options to use an in-memory SQLite data store and a default consumer.
$ python mytool.py -m
The script may print a warning message to the console warning you that the in-memory database does not support multiple connections, it then just sits waiting for connections on the default port, 8080. The default consumer has key ‘12345’ and secret ‘secret’ (these can be changed using a configuration file!). The launch URL for your running tool is:
http://localhost:8080/launch
If you try it in the IMS test consumer at: http://www.imsglobal.org/developers/LTI/test/v1p1/lms.php you should get something that looks a bit like this:
For a more complete example see the NoticeBoard Sample LTI Tool.
3.4.3. Reference¶
-
class
pyslet.imsbltiv1p0.
ToolProviderApp
(**kwargs)¶ Bases:
pyslet.wsgi.SessionApp
Represents WSGI applications that provide LTI Tools
The key ‘ToolProviderApp’ is reserved for settings defined by this class in the settings file. The defined settings are:
- silo (‘testing’)
- The name of a default silo to create when the –create_silo option is used.
- key (‘12345’)
- The default consumer key created when –create_silo is used.
- secret (‘secret’)
- The consumer secret of the default consumer created when –create_silo is used.
-
ContextClass
¶ We have our own context class
alias of
ToolProviderContext
-
classmethod
add_options
(parser)¶ Adds the following options:
--create_silo create default silo and consumer
-
init_dispatcher
()¶ Provides ToolProviderApp specific bindings.
This method adds bindings for /launch as the launch URL for the tool and all paths within /resource as the resource pages themselves.
-
set_launch_group
(context)¶ Sets the group in the context from the launch parameters
-
set_launch_resource
(context)¶ Sets the resource in the context from the launch parameters
-
set_launch_user
(context)¶ Sets the user in the context from the launch parameters
-
set_launch_permissions
(context)¶ Sets the permissions in the context from the launch params
-
READ_PERMISSION
= 1¶ Permission bit mask representing ‘read’ permission
-
WRITE_PERMISSION
= 2¶ Permission bit mask representing ‘write’ permission
-
CONFIGURE_PERMISSION
= 4¶ Permission bit mask representing ‘configure’ permission
-
classmethod
get_permissions
(role)¶ Returns the permissions that apply to a single role
- role
- A single
URN
instance
Specific LTI tools can override this method to provide more complex permission models. Each permission type is represented by an integer bit mask, permissions can be combined with binary or ‘|’ to make an overal permissions integer. The default implementation uses the
READ_PERMISSION
,WRITE_PERMISSION
andCONFIGURE_PERMISSION
bit masks but you are free to use any values you wish.In this implementation, Instructors (and all sub-roles) are granted read, write and configure whereas Learners (and all subroles) are granted read only. Any other role returns 0 (no permissions).
An LTI consumer can specify multiple roles on launch, this method is called for each role and the resulting permissions integers are combined to provide an overall permissions integer.
-
get_user_display_name
(context, user=None)¶ Given a user entity, returns a display name
If user is None then the user from the context is used instead.
-
get_resource_title
(context)¶ Given a resource entity, returns a display title
-
new_visit
(context)¶ Called during launch to create a new visit entity
A new visit entity is created and bound to the resource entity referred to in the launch. The visit entity stores the permissions and a link to the (optional) user entity.
If a visit to the same resource is already associated with the session it is replaced. This ensures that information about the resource, the user, roles and permissions always corresponds to the most recent launch.
Any visits from the same consumer but with a different user are also removed. This handles the case where a previous user of the browser session needs to be logged out of the tool.
-
find_visit
(context, resource_id)¶ Finds a visit that matches this resource_id
-
establish_session
(context)¶ Overridden to update the Session ID in the visit
-
merge_session
(context, merge_session)¶ Overridden to update the Session ID in any associated visits
-
load_visit
(context)¶ Loads an existing LTI visit into the context
You’ll normally call this method from each session decorated method of your tool provider that applies to a protected resource.
This method sets the following attributes of the context…
ToolProviderContext.resource
- The resource record is identified from the resource id given in the URL path.
ToolProviderContext.visit
- The session is searched for a visit record matching the resource.
ToolProviderContext.permissions
- Set from the visit record
ToolProviderContext.user
- The optional user is loaded from the visit.
ToolProviderContext.group
- The context record identified from the resource id given in the URL path. This may be None if the resource link was not created in any context.
ToolProviderContext.consumer
- The consumer object is looked up from the visit entity.
If the visit can’t be set then an exception is raised, an unknown resource raises
pyslet.wsgi.PageNotFound
whereas the absence of a valid visit for a known resource raisespyslet.wsgi.PageNotAuthorized
. These are caught automatically by the WSGI handlers and return 404 and 403 errors respectively.
-
launch_redirect
(context)¶ Redirects to the resource identified on launch
A POST request should pretty much always redirect to a GET page and our tool launches are no different. This allows you to reload a tool page straight away if desired without the risk of double-POST issues.
-
class
pyslet.imsbltiv1p0.
ToolProviderContext
(environ, start_response, canonical_root=None)¶ Bases:
pyslet.wsgi.SessionContext
-
consumer
= None¶ a
ToolConsumer
instance identified from the launch
-
parameters
= None¶ a dictionary of non-oauth parameters from the launch
-
visit
= None¶ the effective visit entity
-
resource
= None¶ the effective resource entity
-
user
= None¶ the effective user entity
-
group
= None¶ the effective group (context) entity
-
permissions
= None¶ the effective permissions (an integer for bitwise testing)
-
-
class
pyslet.imsbltiv1p0.
ToolConsumer
(entity, cipher)¶ Bases:
object
An LTI consumer object
This class is a light wrapper for the entity object that is used to persist information on the server about the consumer. The consumer is persisted in a data store using a single entity passed on construction which must have the following required properties:
- ID: Int64
- A database key for the consumer.
- Handle: String
- A convenient handle for referring to this consumer in the user interface of the silo’s owner. This handle is never exposed to users launching the tool through the LTI protocol. For example, you might use handles like “LMS Prod” and “LMS Staging” as handles to help distinguish different consumers.
- Key: String
- The consumer key
- Secret: String
- The consumer secret (encrypted using cipher).
- Silo: Entity
- Required navigation property to the Silo this consumer is associated with.
- Contexts: Entity Collection
- Navigation property to the associated contexts from which this tool has been launched.
- Resources: Entity Collection
- Navigation property to the associated resources from which this tool has been launched.
- Users: Entity Collection
- Navigation property to the associated users that have launched the tool.
-
entity
= None¶ the entity that persists this consumer
-
cipher
= None¶ the cipher used to
-
key
= None¶ the consumer key
-
secret
= None¶ the consumer secret
-
classmethod
new_from_values
(entity, cipher, handle, key=None, secret=None)¶ Create an instance from an new entity
- entity
- An
Entity
instance from a suitable entity set. - cipher
- An
AppCipher
instance, used to encrypt the secret before storing it. - handle
- A string
- key (optional)
- A text string, defaults to a string generated with
generate_key()
- secret (optional)
- A text string, defaults to a string generated with
generate_key()
The fields of the entity are set from the passed in parameters (or the defaults) and then a new instance of cls is constructed from the entity and cipher and returned as a the result.
-
update_from_values
(handle, secret)¶ Updates an instance from new values
- handle
- A string used to update the consumer’s handle
- secret
- A string used to update the consumer’s secret
It is not possible to update the consumer key as this is used to set the ID of the consumer itself.
-
nonce_key
(nonce)¶ Returns a key into the nonce table
- nonce
- A string received as a nonce during an LTI launch.
This method hashes the nonce, along with the consumer entity’s Key, to return a hex digest string that can be used as a key for comparing against the nonces used in previous launches.
Mixing the consumer entity’s Key into the hash reduces the chance of a collision between two nonces from separate consumers.
-
get_context
(context_id, title=None, label=None, ctypes=None)¶ Returns a context entity
- context_id
- The context_id string passed on launch
- title (optional)
- The title string passed on launch
- label (optional)
- The label string passed on launch
- ctypes (optional)
- An array of
URI
instances representing the context types of this context. SeeCONTEXT_TYPE_HANDLES
for more information.
Returns the context entity.
If this context has never been seen before then a new entity is created and bound to the consumer. Otherwise, the additional information (if supplied) is compared and updated as necessary.
-
get_resource
(resource_link_id, title=None, description=None, context=None)¶ Returns a resource entity
- resource_link_id
- The resource_link_id string passed on launch (required).
- title (optional)
- The title string passed on launch, or None.
- description (optional)
- The description string passed on launch, or None.
- context (optional)
- The context entity referred to in the launch, or None.
If this resource has never been seen before then a new entity is created and bound to the consumer and (if specified) the context. Otherwise, the additional information (if supplied) is compared and updated as necessary, with the proviso that a resource can never change context, as per the following quote from the specification:
[resource_link_id] will also change if the item is exported from one system or context and imported into another system or context.
-
get_user
(user_id, name_given=None, name_family=None, name_full=None, email=None)¶ Returns a user entity
- user_id
- The user_id string passed on launch
- name_given
- The user’s given name (or None)
- name_family
- The user’s family name (or None)
- name_full
- The user’s full name (or None)
- The user’s email (or None)
If this user has never been seen before then a new entity is created and bound to the consumer, otherwise the
-
class
pyslet.imsbltiv1p0.
ToolProvider
(consumers, nonces, cipher)¶ Bases:
pyslet.imsbltiv1p0.OAuthMissing
,pyslet.pep8.MigratedClass
An LTI tool provider object
- consumers
- The
EntitySet
containing the tool Consumers. - nonces
- The
EntitySet
containing the used Nonces. - cipher
- An
AppCipher
instance. Used to decrypt the consumer secret from the database.
Implements the RequestValidator object required by the oauthlib package. Internally creates an instance of SignatureOnlyEndpoint
-
consumers
= None¶ The entity set containing Silos
-
nonces
= None¶ The entity set containing Nonces
-
cipher
= None¶ The cipher object used for encrypting consumer secrets
-
lookup_consumer
(key)¶ Implements the required method for consumer lookup
Returns a
ToolConsumer
instance or raises a KeyError if key is not the key of any known consumer.
-
launch
(command, url, headers, body_string)¶ Checks a launch request for authorization
- command
- The HTTP method, as an upper-case string. Should be POST for LTI.
- url
- The full URL of the page requested as part of the launch. This will be the launch URL specified in the LTI protocol and configured in the consumer.
- headers
- A dictionary of headers, must include the Authorization header but other values are ignored.
- body_string
- The query string (in the LTI case, this is the content of the POST request).
Returns a
ToolConsumer
instance and a dictionary of parameters on success. If the incoming request is not authorized thenLTIAuthenticationError
is raised.This method also checks the LTI message type and protocol version and will raise
LTIProtcolError
if this is not a recognized launch request.
3.4.3.1. Metadata¶
-
pyslet.imsbltiv1p0.
load_metadata
()¶ Loads the default metadata document
Returns a
pyslet.odata2.metadata.Document
instance. The schema is loaded from a bundled metadata document which contains the minimum schema required for an LTI tool provider.
3.4.3.2. Constants and Data¶
-
pyslet.imsbltiv1p0.
LTI_VERSION
= 'LTI-1p0'¶ The version of LTI we support
-
pyslet.imsbltiv1p0.
LTI_MESSAGE_TYPE
= 'basic-lti-launch-request'¶ The message type we support
-
pyslet.imsbltiv1p0.
SYSROLE_HANDLES
= {'Administrator': <pyslet.urn.URN object>, 'Creator': <pyslet.urn.URN object>, 'None': <pyslet.urn.URN object>, 'SysAdmin': <pyslet.urn.URN object>, 'User': <pyslet.urn.URN object>, 'AccountAdmin': <pyslet.urn.URN object>, 'SysSupport': <pyslet.urn.URN object>}¶ A mapping from a system role handle to the full URN for the role as a
URI
instance.
-
pyslet.imsbltiv1p0.
INSTROLE_HANDLES
= {'None': <pyslet.urn.URN object>, 'Guest': <pyslet.urn.URN object>, 'Learner': <pyslet.urn.URN object>, 'Alumni': <pyslet.urn.URN object>, 'Member': <pyslet.urn.URN object>, 'Other': <pyslet.urn.URN object>, 'Mentor': <pyslet.urn.URN object>, 'ProspectiveStudent': <pyslet.urn.URN object>, 'Administrator': <pyslet.urn.URN object>, 'Observer': <pyslet.urn.URN object>, 'Student': <pyslet.urn.URN object>, 'Faculty': <pyslet.urn.URN object>, 'Instructor': <pyslet.urn.URN object>, 'Staff': <pyslet.urn.URN object>}¶ A mapping from a institution role handle to the full URN for the role as a
URI
instance.
-
pyslet.imsbltiv1p0.
ROLE_HANDLES
= {'Manager/CourseCoordinator': <pyslet.urn.URN object>, 'Mentor/Auditor': <pyslet.urn.URN object>, 'Instructor/PrimaryInstructor': <pyslet.urn.URN object>, 'TeachingAssistant/TeachingAssistant': <pyslet.urn.URN object>, 'Administrator/Developer': <pyslet.urn.URN object>, 'Member': <pyslet.urn.URN object>, 'ContentDeveloper/ContentExpert': <pyslet.urn.URN object>, 'Mentor/ExternalReviewer': <pyslet.urn.URN object>, 'TeachingAssistant/Grader': <pyslet.urn.URN object>, 'Mentor/Mentor': <pyslet.urn.URN object>, 'ContentDeveloper/Librarian': <pyslet.urn.URN object>, 'Mentor/ExternalTutor': <pyslet.urn.URN object>, 'Instructor/Lecturer': <pyslet.urn.URN object>, 'TeachingAssistant/TeachingAssistantTemplate': <pyslet.urn.URN object>, 'Administrator/Administrator': <pyslet.urn.URN object>, 'Instructor/ExternalInstructor': <pyslet.urn.URN object>, 'TeachingAssistant/TeachingAssistantSection': <pyslet.urn.URN object>, 'Administrator/Support': <pyslet.urn.URN object>, 'Mentor/Advisor': <pyslet.urn.URN object>, 'Mentor': <pyslet.urn.URN object>, 'TeachingAssistant/TeachingAssistantGroup': <pyslet.urn.URN object>, 'Manager/AreaManager': <pyslet.urn.URN object>, 'TeachingAssistant/TeachingAssistantOffering': <pyslet.urn.URN object>, 'Mentor/LearningFacilitator': <pyslet.urn.URN object>, 'Learner/GuestLearner': <pyslet.urn.URN object>, 'Learner': <pyslet.urn.URN object>, 'Learner/Instructor': <pyslet.urn.URN object>, 'Manager/Observer': <pyslet.urn.URN object>, 'Administrator/ExternalDeveloper': <pyslet.urn.URN object>, 'Learner/Learner': <pyslet.urn.URN object>, 'Administrator': <pyslet.urn.URN object>, 'Administrator/ExternalSupport': <pyslet.urn.URN object>, 'Mentor/Tutor': <pyslet.urn.URN object>, 'Mentor/ExternalAuditor': <pyslet.urn.URN object>, 'TeachingAssistant': <pyslet.urn.URN object>, 'Instructor': <pyslet.urn.URN object>, 'Mentor/ExternalMentor': <pyslet.urn.URN object>, 'Administrator/ExternalSystemAdministrator': <pyslet.urn.URN object>, 'Manager/ExternalObserver': <pyslet.urn.URN object>, 'Learner/ExternalLearner': <pyslet.urn.URN object>, 'Mentor/ExternalAdvisor': <pyslet.urn.URN object>, 'ContentDeveloper/ContentDeveloper': <pyslet.urn.URN object>, 'TeachingAssistant/TeachingAssistantSectionAssociation': <pyslet.urn.URN object>, 'ContentDeveloper/ExternalContentExpert': <pyslet.urn.URN object>, 'Mentor/ExternalLearningFacilitator': <pyslet.urn.URN object>, 'ContentDeveloper': <pyslet.urn.URN object>, 'Learner/NonCreditLearner': <pyslet.urn.URN object>, 'Member/Member': <pyslet.urn.URN object>, 'Mentor/Reviewer': <pyslet.urn.URN object>, 'Manager': <pyslet.urn.URN object>, 'Administrator/SystemAdministrator': <pyslet.urn.URN object>, 'Instructor/GuestInstructor': <pyslet.urn.URN object>}¶ A mapping from LTI role handles to the full URN for the role as a
URI
instance.
-
pyslet.imsbltiv1p0.
split_role
(role)¶ Splits an LTI role into vocab, type and sub-type
- role
- A
URN
instance containing the full definition of the role.
Returns a triple of:
- vocab
- One of ‘role’, ‘sysrole’, ‘instrole’ or some future vocab extension.
- rtype
- The role type, e.g., ‘Learner’, ‘Instructor’
- rsubtype
- The role sub-type , e.g., ‘NonCreditLearner’, ‘Lecturer’. Will be None if there is no sub-type.
If this is not an LTI defined role, or the role descriptor does not start with the path ims/lis then ValueError is raised.
-
pyslet.imsbltiv1p0.
is_subrole
(role, parent_role)¶ True if role is a sub-role of parent_role
- role
- A
URN
instance containing the full definition of the role to be tested. - parent_role
- A
URN
instance containing the full definition of the parent role. It must not define a subrole of ValueError is raised.
In the special case that role does not have subrole then it is simply matched against parent_role. This ensures that:
is_subrole(role, ROLE_HANDLES['Learner'])
will return True in all cases where role is a Learner role.
-
pyslet.imsbltiv1p0.
CONTEXT_TYPE_HANDLES
= {'CourseSection': <pyslet.urn.URN object>, 'CourseOffering': <pyslet.urn.URN object>, 'Group': <pyslet.urn.URN object>, 'CourseTemplate': <pyslet.urn.URN object>}¶ A mapping from LTI context type handles to the full URN for the context type as a
URI
instance.
3.4.3.3. Exceptions¶
-
class
pyslet.imsbltiv1p0.
LTIError
¶ Bases:
exceptions.Exception
Base class for all LTI errors
-
class
pyslet.imsbltiv1p0.
LTIAuthenticationError
¶ Bases:
pyslet.imsbltiv1p0.LTIError
Indicates an authentication error (on launch)
-
class
pyslet.imsbltiv1p0.
LTIProtocolError
¶ Bases:
pyslet.imsbltiv1p0.LTIError
Indicates a protocol violoation
This may be raised if the message type or protocol version in a launch request do not match the expected values or if a required parameter is missing.
3.4.3.4. Legacy Classes¶
Earlier Pyslet versions contained a very rudimentary memory based LTI
tool provider implementation based on the older oauth module. These
classes have been superceded but the main BLTIToolProvider class has
been refactored as a derived class of ToolProvider
using a
SQLite ‘:memory:’ database (instead of a Python dictionary) and the
existing method signatures should continue to work as before.
The only change you’ll need to make is to install the newer oauthlib.
Bear in mind that these classes are now deprecated and you should
refactor to use the base ToolProvider
class directly for future
compatibility. Please raise an issue on GitHub if you anticipate
problems.
-
class
pyslet.imsbltiv1p0.
BLTIToolProvider
¶ Bases:
pyslet.imsbltiv1p0.ToolProvider
Legacy class for tool provider.
Refactored to build directly on the newer
ToolProvider
. A single Silo entity is created containing all defined consumers. An in-memory SQLite database is used as the data store. Consumer keys are not encrypted (a plaintext cipher is used) as they will not be persisted.-
generate_key
(key_length=128)¶ Generates a new key
Also available as GenerateKey. This method is deprecated, it has been replaced by the similarly named function
pyslet.wsgi.generate_key()
.- key_length
- The minimum key length in bits. Defaults to 128.
The key is returned as a sequence of 16 bit hexadecimal strings separated by ‘.’ to make them easier to read and transcribe into other systems.
-
new_consumer
(key=None, secret=None)¶ Creates a new BLTIConsumer instance
Also available as NewConsumer
The new instance is added to the database of consumers authorized to use this tool. The consumer key and secret are automatically generated using
generate_key()
but key and secret can be passed as optional arguments instead.
-
load_from_file
(f)¶ Loads the list of trusted consumers
Also available as LoadFromFile
The consumers are loaded from a simple file of key, secret pairs formatted as:
<consumer key> [SPACE]+ <consumer secret>
Lines starting with a ‘#’ are ignored as comments.
-
GenerateKey
(*args, **kwargs)¶ Deprecated equivalent to
generate_key()
-
LoadFromFile
(*args, **kwargs)¶ Deprecated equivalent to
load_from_file()
-
NewConsumer
(*args, **kwargs)¶ Deprecated equivalent to
new_consumer()
-
SaveToFile
(*args, **kwargs)¶ Deprecated equivalent to
save_to_file()
-
save_to_file
(f)¶ Saves the list of trusted consumers
Also available as SaveToFile
The consumers are saved in a simple file suitable for reading with
load_from_file()
.
-