Hi @wojcika,
It's been some time since you posted this, so I'm not sure if this is still something you need. However, this is possible to do via the Canvas API. We've had to do changes like this with some vendors who migrated to LTI 1.3 and decided to break backwards compatibility. At a high level, the process involves:
- Listing all courses in your instance.
- Listing all assignments within each course.
- Identifying GoReact assignments (based on the
external_took_tag_attributes[url]
field).
- Updating the
external_tool_tag_attributes[url]
field for these assignments.
The Canvas API provides endpoints for listing courses and assignments, and for updating an assignment. Here is a Python script that demonstrates the general workflow for this and should get you pretty far down the right track. ALWAYS REVIEW AND TEST CODE BEFORE RUNNING AGAINST YOUR PRODUCTION INSTANCE!
import requests
API_BASE_URL = 'https://YOUR_CANVAS_URL/api/v1' # Replace YOUR_CANVAS_URL with the domain name for your canvas instance, such as yourschool.instructure.com.
ACCESS_TOKEN = 'YOUR_CANVAS_ACCESS_TOKEN' # Replace with a Canvas Access Token
NEW_GOREACT_URL = "https://new.goreact.url" # Replace with the new GoReact URL
def paginated_get(endpoint, params=None):
headers = {'Authorization': f'Bearer {ACCESS_TOKEN}'}
if params is None:
params = {}
while endpoint:
response = requests.get(f'{API_BASE_URL}{endpoint}', headers=headers, params=params)
response.raise_for_status() # Raises an error for non-200 responses
data = response.json()
yield from data
if getattr(response, 'links', None) is None:
break
links = response.links
endpoint = links['next']['url'].replace(API_BASE_URL, '') if 'next' in links else None
def update_assignment(course_id, assignment_id, new_url):
endpoint = f'/courses/{course_id}/assignments/{assignment_id}'
headers = {'Authorization': f'Bearer {ACCESS_TOKEN}'}
payload = {'assignment': {'external_tool_tag_attributes': {'url': new_url}}}
try:
response = requests.put(f'{API_BASE_URL}{endpoint}', headers=headers, json=payload)
response.raise_for_status()
return response.json()
except requests.RequestException as e:
print(f"Error updating assignment: {e}")
def main():
for course in paginated_get('/accounts/self/courses'):
for assignment in paginated_get(f'/courses/{course["id"]}/assignments'):
# Check if this is a GoReact assignment
if 'goreact' in assignment.get('external_tool_tag_attributes', {}).get('url', ''):
print(f"Updating GoReact URL for assignment {assignment['id']} in course {course['id']}")
update_assignment(course['id'], assignment['id'], NEW_GOREACT_URL)
if __name__ == "__main__":
main()
Replace the constants near the top of the script with your Canvas instance's details and the new GoReact URL they sent you. Again, you should test this on either your Canvas beta instance or test instance before running this script against your production instance to be sure it's working as expected.
Depending on how many courses are in your instance, this script could also take a long time (on the magnitude of hours to days) to run, so you might consider splitting the logic of finding courses with old GoReact assignments with the code that updates the assignments to allow you to properly review the scope of the change before doing anything. This would also give you a better back out strategy if something goes wrong.
I hope this helps!