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
-
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
-
Thanks David. Looks like I'll have to learn the API. We are using IPSIS as the only communication with Brightspace at the moment.
-
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.