Example #1
0
        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"));
        }
Example #2
0
        /// <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));
        }
Example #3
0
        /// <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));
        }