
edu.iu.uits.lms.canvas.services.AccountService Maven / Gradle / Ivy
package edu.iu.uits.lms.canvas.services;
/*-
* #%L
* LMS Canvas Services
* %%
* Copyright (C) 2015 - 2021 Indiana University
* %%
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the Indiana University nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
import edu.iu.uits.lms.canvas.model.Account;
import edu.iu.uits.lms.canvas.model.AccountAdmin;
import edu.iu.uits.lms.canvas.model.AccountAdminCreate;
import edu.iu.uits.lms.canvas.model.CanvasRole;
import edu.iu.uits.lms.canvas.model.Saml;
import edu.iu.uits.lms.canvas.model.SsoSettings;
import edu.iu.uits.lms.canvas.model.SsoSettingsWrapper;
import edu.iu.uits.lms.canvas.utils.CacheConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriTemplate;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
/**
* Service to get various account related things
*/
@Service
@Slf4j
public class AccountService extends SpringBaseService {
private static final String CANVAS_BASE_URI = "{url}";
private static final String ACCOUNTS_BASE_URI = CANVAS_BASE_URI + "/accounts";
private static final String ACCOUNT_URI = ACCOUNTS_BASE_URI + "/{id}";
private static final String COURSE_ACCOUNTS_URI = CANVAS_BASE_URI + "/course_accounts";
private static final String ROLES_URI = ACCOUNT_URI + "/roles";
private static final String ACCOUNT_ADMINS_URI = ACCOUNT_URI + "/admins";
private static final String ACCOUNT_ADMINS_SPECIFIC_URI = ACCOUNT_ADMINS_URI + "/{userid}";
private static final String SUBACCOUNTS_URI = ACCOUNT_URI + "/sub_accounts";
private static final String SSO_SETTINGS_URI = ACCOUNT_URI + "/sso_settings";
private static final String SAML_URI = ACCOUNT_URI + "/authentication_providers/{samlId}";
private static final UriTemplate ACCOUNT_TEMPLATE = new UriTemplate(ACCOUNT_URI);
private static final UriTemplate COURSE_ACCOUNTS_TEMPLATE = new UriTemplate(COURSE_ACCOUNTS_URI);
private static final UriTemplate ROLES_TEMPLATE = new UriTemplate(ROLES_URI);
private static final UriTemplate ACCOUNT_ADMINS_TEMPLATE = new UriTemplate(ACCOUNT_ADMINS_URI);
private static final UriTemplate ACCOUNT_ADMINS_SPECIFIC_TEMPLATE = new UriTemplate(ACCOUNT_ADMINS_SPECIFIC_URI);
private static final UriTemplate SUBACCOUNTS_TEMPLATE = new UriTemplate(SUBACCOUNTS_URI);
private static final UriTemplate SSO_SETTINGS_TEMPLATE = new UriTemplate(SSO_SETTINGS_URI);
private static final UriTemplate SAML_TEMPLATE = new UriTemplate(SAML_URI);
/**
* Get all roles that are defined in the system
* @return List of CanvasRole objects
*/
public List getAllRoles() {
URI uri = ROLES_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl(), canvasConfiguration.getAccountId());
log.debug("{}", uri);
return doGet(uri, CanvasRole[].class);
}
/**
* Get all the roles for the given accountId
* @param accountId Account id
* @param showInherited Flag indicating if all inherited roles should be returned as well
* @return List of canvas roles available to this account
*/
public List getRolesForAccount(String accountId, boolean showInherited) {
URI uri = ROLES_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl(), accountId);
log.debug("{}", uri);
UriComponentsBuilder builder = UriComponentsBuilder.fromUri(uri);
builder.queryParam("show_inherited", showInherited);
return doGet(builder.build().toUri(), CanvasRole[].class);
}
/**
*
* @param accountId Account id
* @return a list of the parent {@link Account}s for the given accountId
*/
@Cacheable(value = CacheConstants.PARENT_ACCOUNTS_CACHE_NAME, cacheManager = "CanvasServicesCacheManager")
public List getParentAccounts(String accountId) {
List parentAccounts = new ArrayList<>();
Account account = getAccount(accountId);
// if there is no parent account (ie this is the root), parent_account_id should be null
while (account != null && account.getParentAccountId() != null) {
account = getAccount(account.getParentAccountId());
parentAccounts.add(account);
}
return parentAccounts;
}
/**
* Get a specific account object from Canvas
* GET /api/v1/accounts/account_id
* @param accountId Canvas account id. Could also have the form of sis_account_id:account_id
* @return Account
*/
public Account getAccount(String accountId) {
URI uri = ACCOUNT_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl(), accountId);
log.debug("uri: {}", uri);
try {
HttpEntity accountResponseEntity = this.restTemplate.getForEntity(uri, Account.class);
log.debug("accountResponseEntity: {}", accountResponseEntity);
if (accountResponseEntity != null) {
return accountResponseEntity.getBody();
}
} catch (HttpClientErrorException hcee) {
log.error("Error: ", hcee);
}
return null;
}
/**
* Get all accounts a given user can access
* @param userLoginId User's login id
* @return List of accessible accounts
*/
public List getAccountsForUser(String userLoginId) {
URI uri = COURSE_ACCOUNTS_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl());
log.debug("uri: {}", uri);
UriComponentsBuilder builder = UriComponentsBuilder.fromUri(uri);
builder.queryParam("as_user_id", "sis_login_id:" + userLoginId);
builder.queryParam("per_page", "100");
return doGet(builder.build().toUri(), Account[].class);
}
/**
* Is the given user an admin in the given account
* @param accountId
* @param userId
* @return
*/
public boolean isAccountAdmin(String accountId, String userId) {
URI uri = ACCOUNT_ADMINS_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl(), accountId);
log.debug("uri: {}", uri);
UriComponentsBuilder builder = UriComponentsBuilder.fromUri(uri);
builder.queryParam("user_id[]", userId);
List accountAdmins = doGet(builder.build().toUri(), AccountAdmin[].class);
for (AccountAdmin accountAdmin : accountAdmins) {
if ("active".equals(accountAdmin.getWorkflow_state())) {
return true;
}
}
return false;
}
/**
* Elevate the given user to an account admin
* @param accountId
* @param userId
* @return
*/
public boolean elevateToAccountAdmin(String accountId, String userId) {
if (isAccountAdmin(accountId, userId)) {
return true;
}
URI uri = ACCOUNT_ADMINS_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl(), accountId);
log.debug("uri: {}", uri);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
AccountAdminCreate accountAdminCreate = new AccountAdminCreate(userId, false);
HttpEntity accountAdminCreateRequestEntity = new HttpEntity<>(accountAdminCreate, headers);
HttpEntity accountAdminCreateResponseEntity = this.restTemplate.exchange(uri, HttpMethod.POST, accountAdminCreateRequestEntity, AccountAdmin.class);
log.debug("accountAdminCreateResponseEntity: {}", accountAdminCreateResponseEntity);
if (((ResponseEntity) accountAdminCreateResponseEntity).getStatusCode() == HttpStatus.OK) {
return true;
}
} catch (HttpClientErrorException hcee) {
log.error("uh oh", hcee);
}
return false;
}
/**
* Demote the given user back to a "regular" user as they no longer need to ba an account admin
* @param accountId
* @param userId
* @return
*/
public boolean revokeAsAccountAdmin(String accountId, String userId) {
if (! isAccountAdmin(accountId, userId)) {
return true;
}
try {
URI uri = ACCOUNT_ADMINS_SPECIFIC_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl(), accountId, userId);
log.debug("uri: {}", uri);
HttpEntity accountAdminDeleteResponseEntity = this.restTemplate.exchange(uri, HttpMethod.DELETE, null, AccountAdmin.class);
log.debug("accountAdminDeleteResponseEntity: {}", accountAdminDeleteResponseEntity);
if (((ResponseEntity) accountAdminDeleteResponseEntity).getStatusCode() == HttpStatus.OK) {
return true;
}
} catch (HttpClientErrorException hcee) {
log.error("uh oh", hcee);
}
return false;
}
/**
* Get all subaccounts that are defined in the system
* @return List of Account objects
*/
public List getSubAccounts() {
URI uri = SUBACCOUNTS_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl(), canvasConfiguration.getAccountId());
log.debug("uri: {}", uri);
UriComponentsBuilder builder = UriComponentsBuilder.fromUri(uri);
builder.queryParam("recursive","true");
builder.queryParam("per_page", "50");
return doGet(builder.build().toUri(), Account[].class);
}
/**
* Account with this accountId to use to set the sisAccountId value
* @param accountId - the accountId to use to set
* @param sisAccountId - the sisAccountId value to set for account with accountId
* @return - the account changed
*/
public Account setSisAccountId(String accountId, String sisAccountId) {
if (accountId == null || accountId.isEmpty() || sisAccountId == null || sisAccountId.isEmpty()) {
throw new RuntimeException("Null parameters");
}
URI uri = ACCOUNT_TEMPLATE.expand(canvasConfiguration.getBaseApiUrl(), accountId);
log.debug("uri: {}", uri);
UriComponentsBuilder builder = UriComponentsBuilder.fromUri(uri);
builder.queryParam("account[sis_account_id]", sisAccountId);
try {
ResponseEntity response = this.restTemplate.exchange(builder.build().toUri(), HttpMethod.PUT, null, Account.class);
log.debug("{}", response);
if (response.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException("Request to Canvas was not successful. Response code: "
+ response.getStatusCode() + ", reason: " + ((HttpStatus)response.getStatusCode()).getReasonPhrase()
+ ", body: " + response.getBody());
}
return response.getBody();
} catch (HttpClientErrorException hcee) {
log.error("cannot set sisAccountId", hcee);
throw new RuntimeException("cannot set sisAccountId", hcee);
}
}
/**
* GET /api/v1/accounts/:account_id/sso_settings
* @param canvasServer
* @return
*/
public SsoSettings getSsoSettings(String canvasServer) {
URI uri = SSO_SETTINGS_TEMPLATE.expand(canvasServer, canvasConfiguration.getAccountId());
log.debug("{}", uri);
try {
HttpEntity ssoSettingsResponseEntity = this.restTemplate.getForEntity(uri, SsoSettingsWrapper.class);
log.debug("{}", ssoSettingsResponseEntity);
if (ssoSettingsResponseEntity != null) {
SsoSettingsWrapper ssoSettingsWrapperResponse = ssoSettingsResponseEntity.getBody();
if (ssoSettingsWrapperResponse != null) {
return ssoSettingsWrapperResponse.getSsoSettings();
}
}
} catch (HttpClientErrorException hcee) {
log.error("Error getting SsoSettings", hcee);
}
return null;
}
/**
* PUT /api/v1/accounts/:account_id/sso_settings
* @param canvasServer
* @param ssoSettingsWrapper
* @return
*/
public SsoSettings setSsoSettings(String canvasServer, SsoSettingsWrapper ssoSettingsWrapper) {
URI uri = SSO_SETTINGS_TEMPLATE.expand(canvasServer, canvasConfiguration.getAccountId());
log.debug("{}", uri);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity ssoSettingsWrapperRequestEntity = new HttpEntity<>(ssoSettingsWrapper, headers);
HttpEntity ssoSettingsResponseEntity = this.restTemplate.exchange(uri, HttpMethod.PUT, ssoSettingsWrapperRequestEntity, SsoSettingsWrapper.class);
log.debug("{}", ssoSettingsResponseEntity);
if (ssoSettingsResponseEntity != null) {
SsoSettingsWrapper ssoSettingsWrapperResponse = ssoSettingsResponseEntity.getBody();
if (ssoSettingsWrapperResponse != null) {
return ssoSettingsWrapperResponse.getSsoSettings();
}
}
} catch (HttpClientErrorException hcee) {
log.error("Error setting SsoSettings", hcee);
}
return null;
}
/**
* GET /api/v1/accounts/:account_id/authentication_providers/:id
* @param canvasServer
* @param samlId
* @return
*/
public Saml getSaml(String canvasServer, String samlId) {
URI uri = SAML_TEMPLATE.expand(canvasServer, canvasConfiguration.getAccountId(), samlId);
log.debug("{}", uri);
try {
HttpEntity samlResponseEntity = this.restTemplate.getForEntity(uri, Saml.class);
log.debug("{}", samlResponseEntity);
if (samlResponseEntity != null) {
return samlResponseEntity.getBody();
}
} catch (HttpClientErrorException hcee) {
log.error("Error getting Saml", hcee);
}
return null;
}
/**
* PUT /api/v1/accounts/:account_id/authentication_providers/:id
* @param canvasServer
* @param samlId
* @param newSamlObject
*/
public void setSaml(String canvasServer, String samlId, Saml newSamlObject) {
URI uri = SAML_TEMPLATE.expand(canvasServer, canvasConfiguration.getAccountId(), samlId);
log.debug("{}", uri);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
try {
HttpEntity requestEntity = new HttpEntity<>(newSamlObject, headers);
HttpEntity samlResponseEntity = this.restTemplate.exchange(uri, HttpMethod.PUT, requestEntity, Saml.class);
log.debug("{}", samlResponseEntity);
ResponseEntity responseEntity = (ResponseEntity) samlResponseEntity;
if (responseEntity.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException("Request to Canvas was not successful. Response code: "
+ responseEntity.getStatusCode() + ", reason: " + ((HttpStatus)responseEntity.getStatusCode()).getReasonPhrase()
+ ", body: " + responseEntity.getBody());
}
} catch (RuntimeException re) {
log.error("Error setting Saml", re);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy