/// <summary> /// Returns the LTI claims for an LtiDeepLinkingRequest. /// </summary> /// <param name="tool">The deep linking tool.</param> /// <param name="person">The person being authorized.</param> /// <param name="course">The course (can be null).</param> /// <param name="platform">The platform.</param> /// <returns></returns> private List <Claim> GetDeepLinkingRequestClaims( Tool tool, Person person, Course course, Platform platform) { var httpRequest = _httpContextAccessor.HttpContext.Request; var request = new LtiDeepLinkingRequest { DeploymentId = tool.DeploymentId, FamilyName = person.LastName, GivenName = person.FirstName, LaunchPresentation = new LaunchPresentationClaimValueType { DocumentTarget = DocumentTarget.Window, Locale = CultureInfo.CurrentUICulture.Name }, Lis = new LisClaimValueType { PersonSourcedId = person.SisId, CourseSectionSourcedId = course?.SisId }, Lti11LegacyUserId = person.Id.ToString(), Platform = new PlatformClaimValueType { ContactEmail = platform.ContactEmail, Description = platform.Description, Guid = platform.Id.ToString(), Name = platform.Name, ProductFamilyCode = platform.ProductFamilyCode, Url = platform.Url, Version = platform.Version }, Roles = PeopleModel.ParsePersonRoles(person.Roles), TargetLinkUri = tool.DeepLinkingLaunchUrl }; // Add the context if the launch is from a course. if (course == null) { // Remove context roles request.Roles = request.Roles.Where(r => !r.ToString().StartsWith("Context")).ToArray(); } else { request.Context = new ContextClaimValueType { Id = course.Id.ToString(), Title = course.Name, Type = new[] { ContextType.CourseSection } }; } // Add the deep linking settings request.DeepLinkingSettings = new DeepLinkingSettingsClaimValueType { AcceptPresentationDocumentTargets = new [] { DocumentTarget.Window }, AcceptMultiple = true, AcceptTypes = new [] { Constants.ContentItemTypes.LtiLink }, AutoCreate = true, DeepLinkReturnUrl = _linkGenerator.GetUriByPage( "/DeepLinks", handler: null, values: new { platformId = platform.Id, courseId = course?.Id }, scheme: httpRequest.Scheme, host: httpRequest.Host) }; // Collect custom properties if (tool.CustomProperties.TryConvertToDictionary(out var custom)) { // Prepare for custom property substitutions var substitutions = new CustomPropertySubstitutions { LtiUser = new LtiUser { Username = person.Username } }; request.Custom = substitutions.ReplaceCustomPropertyValues(custom); } return(new List <Claim>(request.Claims)); }
/// <summary> /// Returns the LTI claims for an LtiResourceLinkRequest. /// </summary> /// <param name="resourceLink">The resource link.</param> /// <param name="gradebookColumn">The gradebool column for this resource link.</param> /// <param name="person">The person being authorized.</param> /// <param name="course">The course (can be null).</param> /// <param name="platform">The platform.</param> /// <returns></returns> private List <Claim> GetResourceLinkRequestClaims( ResourceLink resourceLink, GradebookColumn gradebookColumn, Person person, Course course, Platform platform) { var httpRequest = _httpContextAccessor.HttpContext.Request; var request = new LtiResourceLinkRequest { DeploymentId = resourceLink.Tool.DeploymentId, FamilyName = person.LastName, GivenName = person.FirstName, LaunchPresentation = new LaunchPresentationClaimValueType { DocumentTarget = DocumentTarget.Window, Locale = CultureInfo.CurrentUICulture.Name, ReturnUrl = $"{httpRequest.Scheme}://{httpRequest.Host}" }, Lis = new LisClaimValueType { PersonSourcedId = person.SisId, CourseSectionSourcedId = course?.SisId }, Lti11LegacyUserId = person.Id.ToString(), Platform = new PlatformClaimValueType { ContactEmail = platform.ContactEmail, Description = platform.Description, Guid = platform.Id.ToString(), Name = platform.Name, ProductFamilyCode = platform.ProductFamilyCode, Url = platform.Url, Version = platform.Version }, ResourceLink = new ResourceLinkClaimValueType { Id = resourceLink.Id.ToString(), Title = resourceLink.Title, Description = resourceLink.Description }, Roles = PeopleModel.ParsePersonRoles(person.Roles), TargetLinkUri = resourceLink.Tool.LaunchUrl }; // Add the context if the launch is from a course. if (course == null) { // Remove context roles request.Roles = request.Roles.Where(r => !r.ToString().StartsWith("Context")).ToArray(); } else { request.Context = new ContextClaimValueType { Id = course.Id.ToString(), Title = course.Name, Type = new[] { ContextType.CourseSection } }; request.AssignmentGradeServices = new AssignmentGradeServicesClaimValueType { Scope = new List <string> { Constants.LtiScopes.Ags.LineItem }, LineItemUrl = gradebookColumn == null ? null : _linkGenerator.GetUriByRouteValues(Constants.ServiceEndpoints.Ags.LineItemService, new { contextId = course.Id, lineItemId = gradebookColumn.Id }, httpRequest.Scheme, httpRequest.Host), LineItemsUrl = _linkGenerator.GetUriByRouteValues(Constants.ServiceEndpoints.Ags.LineItemsService, new { contextId = course.Id }, httpRequest.Scheme, httpRequest.Host) }; request.NamesRoleService = new NamesRoleServiceClaimValueType { ContextMembershipUrl = _linkGenerator.GetUriByRouteValues(Constants.ServiceEndpoints.Nrps.MembershipService, new { contextId = course.Id }, httpRequest.Scheme, httpRequest.Host) }; } // Collect custom properties if (!resourceLink.Tool.CustomProperties.TryConvertToDictionary(out var custom)) { custom = new Dictionary <string, string>(); } if (resourceLink.CustomProperties.TryConvertToDictionary(out var linkDictionary)) { foreach (var property in linkDictionary) { if (custom.ContainsKey(property.Key)) { custom[property.Key] = property.Value; } else { custom.Add(property.Key, property.Value); } } } // Prepare for custom property substitutions var substitutions = new CustomPropertySubstitutions { LtiUser = new LtiUser { Username = person.Username } }; request.Custom = substitutions.ReplaceCustomPropertyValues(custom); return(new List <Claim>(request.Claims)); }
/// <inheritdoc /> /// <summary> /// Returns members of the course. /// </summary> /// <param name="request">The request.</param> /// <returns>The members of the sample course.</returns> protected override async Task <ActionResult <MembershipContainer> > OnGetMembershipAsync(GetMembershipRequest request) { // In this sample app, each registered app user has an associated platform, // course, and membership. So look up the user that owns the requested course. if (!int.TryParse(request.ContextId, out var contextId)) { var name = $"{nameof(request)}.{nameof(request.ContextId)}"; ModelState.AddModelError(name, $"The {name} field cannot be converted into a course id."); return(BadRequest(new ValidationProblemDetails(ModelState))); } if (!await _courseValidator.UserHasAccess(contextId)) { return(Unauthorized(new ProblemDetails { Title = "Not authorized", Detail = "User not authorized to access the requested course." })); } var course = await _context.GetCourseAsync(contextId); if (course == null) { return(NotFound(new ProblemDetails { Title = ReasonPhrases.GetReasonPhrase(StatusCodes.Status404NotFound), Detail = "Course not found" })); } var user = await _context.GetUserByCourseIdAsync(course.Id); var membership = new MembershipContainer { Id = Request.GetDisplayUrl(), Context = new Context { Id = user.Course.Id.ToString(), Title = user.Course.Name } }; if (user.People.Any()) { var people = user.People .Select(p => new Member { FamilyName = p.LastName, GivenName = p.FirstName, Roles = PeopleModel.ParsePersonRoles(p.Roles), Status = MemberStatus.Active, LisPersonSourcedId = p.SisId, UserId = p.Id.ToString(), Email = p.Email }); if (request.Rlid.IsPresent()) { if (!int.TryParse(request.Rlid, out var resourceLinkId)) { var name = $"{nameof(request)}.{nameof(request.ContextId)}"; ModelState.AddModelError(name, $"The {name} field cannot be converted into a resource linkid id."); return(BadRequest(new ValidationProblemDetails(ModelState))); } people = people.Where(p => user.Course.ResourceLinks.Any(l => l.Id == resourceLinkId)); } if (request.Role.HasValue) { people = people.Where(p => p.Roles.Any(r => r == request.Role.Value)); } membership.Members = people.ToList(); } return(membership); }