public async Task <IActionResult> OnPostAsync() { if (ResourceLink.CustomProperties.IsPresent()) { if (!ResourceLink.CustomProperties.TryConvertToDictionary(out _)) { ModelState.AddModelError( $"{nameof(Tool)}.{nameof(Tool.CustomProperties)}", "Cannot parse the Custom Properties."); } } if (!ModelState.IsValid) { return(Page()); } var user = await _context.GetUserFullAsync(User); var tool = await _context.Tools.FindAsync(ResourceLink.ToolId); // Add the resource link to the course var resourceLink = ResourceLink.ToResourceLink(tool); user.Course.ResourceLinks.Add(resourceLink); // And add a gradebook column to the course var gradebookColumn = new GradebookColumn { EndDateTime = DateTime.UtcNow.AddMonths(3), Label = ResourceLink.Title, ResourceLink = resourceLink, ScoreMaximum = 100, StartDateTime = DateTime.UtcNow, Tag = tool.Name }; user.Course.GradebookColumns.Add(gradebookColumn); await _context.SaveChangesAsync(); return(RedirectToPage("./Index")); }
/// <inheritdoc /> /// <summary> /// Adds a gradebook column to a course. /// </summary> /// <returns>The line item corresponding to the new gradebook column.</returns> protected override async Task <ActionResult <LineItem> > OnAddLineItemAsync(AddLineItemRequest request) { 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" })); } // Add a gradebook column to the course var gradebookColumn = new GradebookColumn { EndDateTime = request.LineItem.EndDateTime, Label = request.LineItem.Label, ScoreMaximum = request.LineItem.ScoreMaximum, StartDateTime = request.LineItem.StartDateTime, Tag = request.LineItem.Tag }; if (request.LineItem.ResourceLinkId.IsPresent()) { if (!int.TryParse(request.LineItem.ResourceLinkId, out var resourceLinkId)) { var name = $"{nameof(request)}.{nameof(request.LineItem.ResourceLinkId)}"; ModelState.AddModelError(name, $"The {name} field cannot be converted into a resource link id."); return(BadRequest(new ValidationProblemDetails(ModelState))); } var resourceLink = await _context.GetResourceLinkAsync(resourceLinkId); if (resourceLink == null) { var name = $"{nameof(request)}.{nameof(request.LineItem)}.{request.LineItem.ResourceLinkId}"; ModelState.AddModelError(name, $"The {name} field is not a valid resource link id."); return(BadRequest(new ValidationProblemDetails(ModelState))); } gradebookColumn.ResourceLink = resourceLink; } course.GradebookColumns.Add(gradebookColumn); await _context.SaveChangesAsync(); request.LineItem.Id = Url.Link(LtiAdvantage.Constants.ServiceEndpoints.Ags.LineItemService, new { contextId = request.ContextId, lineItemId = gradebookColumn.Id }); return(Created(request.LineItem.Id, request.LineItem)); }
/// <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)); }