Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

Commit

Permalink
Create a lookup table for LTI placement types (#193) (#195)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonespm authored Jun 18, 2020
1 parent 2be25d3 commit 0969b05
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 31 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ a more lenient and customizable variant of JSON. Complete the following items in
`CANVAS` | `API_CLIENT_SECRET` | The client secret for authenticating to the API Directory.
`CANVAS` | `CANVAS_URL` | The Canvas instance URL to be used as the base URL for API requests that use the `CANVAS TOKEN`.
`CANVAS` | `CANVAS_TOKEN` | The Canvas token used for authenticating to the API when not using the U-M API Directory.
`CANVAS` | `SUPPORTED_LTI_TOOLS` | The tool definitions supported by the CANVAS_LTI job. See the env_blank for a sample of a configuration.
`MIVIDEO` | `udp_service_account_json_filename` | The name of the JSON credential file for accessing UDP's Google BigQuery service account. It should be the `umich-its-tl-reports-prod.json` credential file for UMich ITS TL. This file name is appended to the value of `ENV_DIR` (which is `/config/secrets`, by default) to determine the full path to the file.<br/><br/>If this key's value is set to `umich-its-tl-reports-prod.json` and `ENV_DIR` has its default value, the full path to the file will be `/config/secrets/umich-its-tl-reports-prod.json`.
`MIVIDEO` | `default_last_timestamp` | The MiVideo procedures use the last timestamp found in its tables in this application's DB to query for data newer than that time. If that timestamp isn't found (e.g., the first time the application runs) the value of this property will be used. This must be a valid ISO 8601 timestamp in the UTC time zone. The recommended value is `2020-03-01T00:00:00+00:00`.
`MIVIDEO` | `kaltura_partner_id` | This is an integer that represents the Kaltura account number. UMich ITS TL users can find this value in the usual security files folder.
Expand Down
7 changes: 1 addition & 6 deletions config/env_blank.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@
"API_CLIENT_SECRET": "",
# Canvas API
"CANVAS_URL": "",
"CANVAS_TOKEN": "",
# For processing canvas_placements
# ID in each object can be duplicated if the same tool is duplicated
"SUPPORTED_LTI_TOOLS": {
12345: {"name": "Zoom", "id": 0},
}
"CANVAS_TOKEN": ""
},

"MIVIDEO": {
Expand Down
9 changes: 1 addition & 8 deletions config/env_schema.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,7 @@
"API_CLIENT_SECRET": {"type": "string"},
# Canvas API
"CANVAS_URL": {"type": "string"},
"CANVAS_TOKEN": {"type": "string"},
"SUPPORTED_LTI_TOOLS" : {
type: "object"
"properties": {
"name": {"type": "string"}
"id": {"type": "integer"}
}
}
"CANVAS_TOKEN": {"type": "string"}
},
"required": [
"CANVAS_ACCOUNT_ID",
Expand Down
11 changes: 11 additions & 0 deletions db/db_creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,14 @@ def reset_database(self) -> DBCreator:
'''
self.drop_records().migrate()
return self

def get_pk_values(self, table_name: str, primary_key: str) -> List[Union[int, None]]:
'''
Retrieves primary key values from the table. Only works with one primary key.
'''
pk_values = []
conn = self.engine.connect()
rs = conn.execute(f"SELECT {primary_key} FROM {table_name}")
for row in rs:
pk_values.append(row[0])
return pk_values
28 changes: 28 additions & 0 deletions db/migrations/0022.add_lti_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'''
Add in the initial LTI Type Table
'''

from yoyo import step

__depends__ = {'0020.add_lti_usage'}

steps = [
step('''
CREATE TABLE IF NOT EXISTS lti_type (
canvas_id INTEGER NOT NULL,
des VARCHAR(200),
rpt_group_nm VARCHAR(200),
PRIMARY KEY (canvas_id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
'''),
step('''
ALTER TABLE lti_placement
ADD FOREIGN KEY (placement_type_id) REFERENCES lti_type(canvas_id)
ON DELETE RESTRICT ON UPDATE CASCADE
'''),
step('''
INSERT INTO lti_type (canvas_id, des, rpt_group_nm)
VALUES (25194, 'Zoom', 'Zoom'),
(4352, 'Bluejeans', 'Bluejeans');
'''),
]
37 changes: 21 additions & 16 deletions lti_placements/canvas_placements.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@ class CanvasLtiPlacementProcessor:

def __init__(self,
canvas_url: str,
canvas_token: str,
supported_lti_tools: Union[Dict[str, Dict[str, Union[str, int]]], None]):
canvas_token: str):
self.canvas = canvasapi.Canvas(canvas_url, canvas_token)
self.zoom_placements = ZoomPlacements(self.canvas)
if not supported_lti_tools:
supported_lti_tools = {}
self.supported_lti_tools = supported_lti_tools
self.db_creator: DBCreator = DBCreator(ENV['INVENTORY_DB'])
self.supported_tools = self.get_supported_lti_tools()

def generate_lti_course_report(self,
canvas_account_id: int,
Expand Down Expand Up @@ -76,6 +74,9 @@ def generate_lti_course_report(self,
self.get_lti_tabs(self.canvas.get_course(course_id))
return None

def get_supported_lti_tools(self) -> List[Union[int, None]]:
return self.db_creator.get_pk_values('lti_type', 'canvas_id')

def get_lti_tabs(self, course: canvasapi.course.Course) -> None:
# This is a new course we're looking through
self.course_count += 1
Expand All @@ -86,15 +87,20 @@ def get_lti_tabs(self, course: canvasapi.course.Course) -> None:
# The format in canvas of ids is like
# context_external_tool_12345. But we need the numeric part
tab_id = tab.id.split('_')[-1]
supported_tool = self.supported_lti_tools.get(tab_id, None)
# We want the integer value if it exists, otherwise just skip
if tab_id.isdigit():
tab_id = int(tab_id)
else:
continue

# Hidden only included if true
if (supported_tool and not hasattr(tab, "hidden")):
if (tab_id in self.supported_tools and not hasattr(tab, "hidden")):
self.placement_count += 1
self.lti_placements.append({'id': self.placement_count,
'course_id': course.id,
'account_id': course.account_id,
'course_name': course.name,
'placement_type_id': supported_tool.get("id", -1)
'placement_type_id': tab_id
})

# TODO: Find a better way of running this just for zoom
Expand All @@ -104,7 +110,6 @@ def get_lti_tabs(self, course: canvasapi.course.Course) -> None:
return None

def output_report(self) -> None:
db_creator: DBCreator = DBCreator(ENV['INVENTORY_DB'])

lti_placement_df = pd.DataFrame(self.lti_placements)
lti_placement_df = lti_placement_df.set_index("id")
Expand All @@ -120,17 +125,17 @@ def output_report(self) -> None:

# For now until this process is improved just remove all the previous records
logger.info('Emptying Canvas LTI data tables in DB')
db_creator.drop_records(
self.db_creator.drop_records(
['lti_placement', 'lti_zoom_meeting']
)

logger.info(f'Inserting {len(lti_placement_df)} lti_placement records to DB')
lti_placement_df.to_sql("lti_placement", db_creator.engine, if_exists="append", index=True)
logger.info(f'Inserted data into lti_placement table in {db_creator.db_name}')
lti_placement_df.to_sql("lti_placement", self.db_creator.engine, if_exists="append", index=True)
logger.info(f'Inserted data into lti_placement table in {self.db_creator.db_name}')

logger.info(f'Inserting {len(lti_zoom_meeting_df)} lti_zoom_meeting records to DB')
lti_zoom_meeting_df.to_sql("lti_zoom_meeting", db_creator.engine, if_exists="append", index=True)
logger.info(f'Inserted data into lti_zoom_meeting table in {db_creator.db_name}')
lti_zoom_meeting_df.to_sql("lti_zoom_meeting", self.db_creator.engine, if_exists="append", index=True)
logger.info(f'Inserted data into lti_zoom_meeting table in {self.db_creator.db_name}')


class ZoomPlacements():
Expand Down Expand Up @@ -248,11 +253,11 @@ def main() -> Sequence[DataSourceStatus]:
This method is invoked when its module is executed as a standalone program.
'''

# Get ids for tools in lti_type table as supported tools
canvas_env = ENV.get('CANVAS', {})
lti_processor = CanvasLtiPlacementProcessor(
canvas_env.get("CANVAS_URL"),
canvas_env.get("CANVAS_TOKEN"),
canvas_env.get("SUPPORTED_LTI_TOOLS", {}))
canvas_env.get("CANVAS_TOKEN"))

lti_processor.generate_lti_course_report(
canvas_env.get("CANVAS_ACCOUNT_ID", 1),
Expand Down

0 comments on commit 0969b05

Please sign in to comment.