Pass user photo to Brightspace
 
            We would like to set the Brightspace profile photos for our users using our photos from their ID cards. Is there a way using file transfer or the API to pass the photos? Has someone else done this before? We'd like to then prevent them from changing it (we have an approval process in place for the photos already in our SIS).
Answers
- 
            Hey James, Using the Profile Image API you can update the profile image for a specified user. The API uses our simple file upload process to upload the image. Here is a link to the details for the API: Here is a link describing the simple file upload process: http://docs.valence.desire2learn.com/basic/fileupload.html#simple-uploads Hope that helps, Dave 
- 
            Thanks David. Looks like I'll have to learn the API. We are using IPSIS as the only communication with Brightspace at the moment. 
- 
            No problem, feel free to ask questions as you start working your way through getting an API call up and running. A great starting point for your use case might be the following article: It does a walk through creating a back-end service to make API calls using the id-key authentication system (http://docs.valence.desire2learn.com/basic/auth.html). In addition to that an example was created for retrieving the Brightspace Data Sets using a background service with OAuth 2.0(http://docs.valence.desire2learn.com/basic/oauth2.html) authentication model: Hope that helps, Dave 
- 
            I admit I've been mostly liker a fish out of water on this. The help stuff expects a level of knowledge I don't have. I have fumbled my way further, but I'm unable to get a user other than the API user. What I don't understand (and couldn't find in the documentation) was how to pass parameters to the commands For example, I want to get the UserID for a user based off of their OrgDefinedID. I see that's a parameter for the get: GET /d2l/api/lp/(version)/users/ I'm using the API Test tool as a bases and can't get this to work (because I'm missing something) app_creds = { 'app_id': my_app_id, 'app_key': my_app_key } ac = d2lauth.fashion_app_context(app_id=app_creds['app_id'], app_key=app_creds['app_key']) auth_url = ac.create_url_for_authentication(my_lms, 'http://localhost:8080') redirect_url = 'http://localhost:8080' + my_returned_url uc = ac.create_user_context(result_uri=redirect_url, host=my_lms, encrypt_requests=True) api_command = '/d2l/api/lp/1.0/users/?orgDefinedId=1' url = uc.create_authenticated_url(api_command) I get File "<stdin>", line 1, in <module> File "C:\Program Files\Python36\lib\site-packages\d2lvalence\auth.py", line 486, in create_authenticated_url method=method), File "C:\Program Files\Python36\lib\site-packages\d2lvalence\auth.py", line 414, in _build_tokens_for_path raise ValueError("path contains invalid characters for URL path") ValueError: path contains invalid characters for URL path I've tried ampersands and questions. The help document isn't specifying how to 
- 
            Hey @James Mueller, I'm not an expert in python, but I wonder if the query parameter should be added after you've created the authenticated URL instead of before. Here is some example python calling the same route, that adds the query parameter after it's authenticated the URL. http://docs.valence.desire2learn.com/samples/permissionCheck.html#id3 Hope that helps, Dave 
- 
            David, that's exactly what I needed! 
- 
            Here's out python script (with our info stripped out someone would need to plug in their options. This is designed to be called one by one as new photos come in. import sys import requests import d2lvalence.auth as d2lauth import json def main(): if len(sys.argv) - 1 == 0: sys.exit('You must provide a Student ID') else: # Set the ID into a variable sis_id = sys.argv[1] # Create the link to the image file stu_img= '//server/directory/' + sis_id + '.jpg' # Set the basic variables that we need # The LMS url address (minues the access method) my_lms = 'yourschool.brightspace.com' my_return_server = 'http:///localhost:8080' # These come from using the interactive API Test Tool https://apitesttool.desire2learnvalence.com/ # need app_id, app_key my_app_id = '' my_app_key = '' # After authenticating using the Application user you'll get the resulting URL tail which is our user verification data my_returned_url = '' # Create the Credentials we need to connect and the Application's context we are authorizing with my_app_creds = { 'app_id': my_app_id, 'app_key': my_app_key } my_app_context = d2lauth.fashion_app_context(app_id=my_app_creds['app_id'], app_key=my_app_creds['app_key']) # Get the URLS we need for the commands my_auth_url = my_app_context.create_url_for_authentication( my_lms, my_return_server ) my_redirect_url = my_return_server + my_returned_url # Create our User Context to handle the requests my_user_context = my_app_context.create_user_context(result_uri=my_redirect_url, host=my_lms, encrypt_requests=True) # Run our commands # ##################### # We need to get the D2L User ID (UserId) from their SIS id number api_command = '/d2l/api/lp/1.9/users/' query_params = {'orgDefinedID':sis_id} api_url = my_user_context.create_authenticated_url(api_command) # Request the data query_result = requests.get(api_url, params=query_params) if query_result.status_code != 200: sys.exit( 'Info: ' + sis_id + ' does not exist in Brightspace' ) # We get back a JSON object, get the UserId from it and convert it to a string datatype d2l_user_id = str(query_result.json()[0]['UserId']) # Set the command to pass the photo upload_command = '/d2l/api/lp/1.9/profile/user/' + d2l_user_id + '/image' # Create the payload for our image to upload upload_content = { 'profileImage': ('profileImage.jpg', open( stu_img, 'rb' ) ) } # Get it properly configured to be a post to Brightspace upload_url = my_user_context.create_authenticated_url( upload_command , "POST" ) # Post it upload_response = requests.post( upload_url, files=upload_content ) if upload_response.status_code != 200: sys.exit( 'Error: ' + sis_id + ' ' + upload_response.text ) sys.exit ( ' ' + sis_id + ' uploaded' ) if __name__ == "__main__": main() 
- 
            I thought I'd also share a version that's self contained that searches a certain folder for files changed in the last few days and passes them up. Works faster for small directories or cases where multiple images are passed at once. import os import os.path import datetime import re import requests import d2lvalence.auth as d2lauth import json def main(): # Get list of IDs print('Getting Recent Files') my_path = '///server//folder' filter_date = datetime.datetime.now() - datetime.timedelta(days=2) #2 days ago pattern = re.compile("^i\d{5,6}.jpg") #starts with i, has 5-6 digits, ends with .jpg change as needed # Create our empty list id_list = [] # Search for those recent files for root, dirs, files in os.walk(my_path): for file_name in files: if pattern.match(file_name): # The file matched our regex, now find out if it was a recent file path = os.path.join(root, file_name) st = os.stat(path) mtime = datetime.datetime.fromtimestamp(st.st_mtime) if mtime > filter_date: # Recent file, put it in our array, stripping the 'i' and '.jpg' off (leaving just the id) id_list.append(file_name[1:-4]) if len(id_list) > 0: # We had at least one id in our array print('Passing images for') print(id_list) pass_images( id_list ) else: print('No files to pass') def pass_images( in_list ): # Set the basic variables that we need # The LMS url address (minues the access method) my_lms = 'yourschool.brightspace.com' my_return_server = 'http:///localhost:8080' # These come from using the interactive API Test Tool https://apitesttool.desire2learnvalence.com/ # need app_id, app_key my_app_id = '' my_app_key = '' # After authenticating using the InfoCentral user you'll get the resulting URL tail which is our user verification data my_returned_url = '' # Create the Credentials we need to connect and the Application's context we are authorizing with my_app_creds = { 'app_id': my_app_id, 'app_key': my_app_key } my_app_context = d2lauth.fashion_app_context(app_id=my_app_creds['app_id'], app_key=my_app_creds['app_key']) # Get the URLS we need for the commands my_auth_url = my_app_context.create_url_for_authentication( my_lms, my_return_server ) my_redirect_url = my_return_server + my_returned_url # Create our User Context to handle the requests my_user_context = my_app_context.create_user_context(result_uri=my_redirect_url, host=my_lms, encrypt_requests=True) # Pass the photos for sis_id in in_list: # We need to get the D2L User ID (UserId) from their CX id number api_command = '/d2l/api/lp/1.9/users/' query_params = {'orgDefinedID':sis_id} api_url = my_user_context.create_authenticated_url(api_command) # Request the data query_result = requests.get(api_url, params=query_params) if query_result.status_code != 200: print( 'Info: ' + sis_id + ' does not exist in Brightspace' ) continue # We get back a JSON object, get the UserId from it and convert it to a string datatype d2l_user_id = str(query_result.json()[0]['UserId']) # Set the command to pass the photo upload_command = '/d2l/api/lp/1.9/profile/user/' + d2l_user_id + '/image' # Create the payload with our image to upload gu_img = '//server/folder/i' + sis_id + '.jpg' upload_content = { 'profileImage': ('profileImage.jpg', open( gu_img , 'rb' ) ) } # Get it properly configured to be a post to Brightspace upload_url = my_user_context.create_authenticated_url( upload_command , "POST" ) # Post it upload_response = requests.post( upload_url, files=upload_content ) if upload_response.status_code != 200: print( 'Error: ' + sis_id + ' ' + upload_response.text ) continue print( ' ' + sis_id + ' uploaded' ) print( 'Done uploading' ) if __name__ == "__main__": main() 
- 
            Hey @James Mueller, Thanks you for sharing your solution. I'm sure it will be helpful for people attempting to do the same thing in the future! Appreciated, Dave 
- 
            @_David _Wagler and @James Mueller , we are trying to set up a profile pic upload as well. We do not want to replace any existing profile the user may have uploaded, we just want to add an image if there isn't one. All I can see to do would be to get the profile image and use the status code to know which students need to receive a profile image because they don't have one. Do you have a better way to handle the already-exists-don't-replace situation? 
- 
            I can't think of a better way to do it. 
- 
            Ok, some help please. I'm not close to being a developer, more of just a hack. I'm trying to create a script to upload student photos to our brightspace tenant. I have a folder with photos of each student named (#######.jpg) where the ####### is the OrgDefinedID. I am trying to get the script above that searches a folder and uploads the pics functioning, but I can't get past authentication (surprise). What I've done: - Created an 'administrative' service account in my tenant.
- Created an appId/Key using manage Extensibility in my tenant
- Used the https://apitesttool.desire2learnvalence.com to log in using the above two items. I am able to perform the /d2l/api/lp/1.0/users/whoami successfully and it returns the administrative service account.
- I then adjusted the appId/Key page to trust https://localhost:8080 (added the s to http in the script as well)
- I've pulled down the script to my utility server and pip installed the modules needed.  - I've customized the script (slightly) to point at the correct folder for photos (currently contains one image for testing) and adjusted the regex.
- I've added my_app_id and my_app_key
 
- I don't know what to put in the script for my_returned_url.- Tried blank - fail
- Tried '/' - fail
- Tried /?x_aXXXX&x_bXXXX&x_cXXXX - fail (but got further)
- Tried /?x_aXXXX&x_bXXXX - fail
- Tried /index.php (Hail Mary) - fail
 
 Thoughts? Next tries? Thanks in advance! 
- 
            Rich, You get that return string from the API Test tool. Make sure that the API Test Tool address below is the trusted URL in your apps properties in Brightspace. Go to https://apitesttool.desire2learnvalence.com put in your Brighstpace instance put in your app ID and app key Then click "Authenticate" and login with the user who is going to be doing the work on the Brightspace side (I created a new user in Brightspace just to do ours) After you log in successfully you should be asked to grant it permission, test to make sure you can do a WhoAmI Now for the thing you are needing the "my_return_url". Look up at the URL in the web browser. You'll see https://apitesttool.desire2learnvalence.com/ and then the "?" followed by a really long code. That is your returned URL. You'll need the whole thing starting with the "?" 
- 
            James - Thank you. I had an extra / in the URL that was creating all sorts of havoc. You're note to start with the '?' pointed me in the right direction. 
- 
            @Rich McCourt Hi Rich, im looking at doing the exact same, your steps above are really useful . Would you be free for a quick chat by any chance? I'd like some advice with the setup. 


