private static bool VerifyModifyPermissions(HttpContext context, Models.Users.UserProfile up, int courseID) { OSBLEContext _db = new OSBLEContext(); CourseUser courseUser = ( from cu in _db.CourseUsers where cu.UserProfileID == up.ID && cu.AbstractCourse is AbstractCourse && cu.AbstractCourseID == courseID select cu ).FirstOrDefault(); if (null == courseUser || !courseUser.AbstractRole.CanModify) { // User cannot modify this course WriteErrorResponse(context, "The specified user does not have permission to modify course with ID=" + courseID.ToString() + "."); return(false); } return(true); }
public override DynamicDictionary BuildTableForTeam(IAssignmentTeam assignmentTeam) { dynamic data = Builder.BuildTableForTeam(assignmentTeam); data.studentRubricsReceived = new DynamicDictionary(); List <bool> hasRubricList = new List <bool>(); List <int> authorTeamIds = new List <int>(); foreach (TeamMember tm in assignmentTeam.Team.TeamMembers) { AssignmentTeam previousTeam = OSBLEController.GetAssignmentTeam(assignmentTeam.Assignment.PreceedingAssignment, tm.CourseUser); authorTeamIds.Add(previousTeam.TeamID); using (OSBLEContext db = new OSBLEContext()) { hasRubricList.Add((from e in db.RubricEvaluations where e.AssignmentID == assignmentTeam.AssignmentID && e.RecipientID == previousTeam.TeamID && e.Evaluator.AbstractRoleID == (int)CourseRole.CourseRoles.Student && e.IsPublished select e.ID).Count() > 0); } } data.studentRubricsReceived.assignmentID = assignmentTeam.AssignmentID; data.studentRubricsReceived.hasRubricList = hasRubricList; data.studentRubricsReceived.authorTeamIDs = authorTeamIds; return(data); }
public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext.Controller is OSBLEController) { OSBLEController controller = filterContext.Controller as OSBLEController; //AC: Will fail when session clears try { if (controller.ActiveCourseUser.AbstractCourse is Community) { filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Home", action = "Index", area = "" })); } } catch (Exception ex) { OSBLEContext db = new OSBLEContext(); ActivityLog log = new ActivityLog() { Sender = typeof(NotForCommunity).ToString(), Message = "IP " + filterContext.HttpContext.Request.UserHostAddress + " encountered exception: " + ex.ToString() }; //AC: turned off to save space / improve performance /* * db.ActivityLogs.Add(log); * db.SaveChanges(); * */ } } }
/// <summary> /// This function prepares DiscussionPostViewModels for a Discussion Assignment. /// </summary> private void InitializeViewModelForDiscussionAssignment() { List <DiscussionPost> AllPosts; using (OSBLEContext db = new OSBLEContext()) { //If the assignment has discussion teams, we want to grab only DiscussionPosts made by a specific DiscussionTeam.ID. //Otherwise, we want to grab all the posts for the entire class. if (discussionTeam.Assignment.HasDiscussionTeams) { AllPosts = (from post in db.DiscussionPosts .Include("CourseUser") .Include("CourseUser.AbstractRole") where post.DiscussionTeamID == discussionTeam.ID select post).ToList(); } else { AllPosts = (from post in db.DiscussionPosts .Include("CourseUser") .Include("CourseUser.AbstractRole") where post.AssignmentID == discussionTeam.AssignmentID select post).ToList(); } ConvertPostsToViewmodel(AllPosts); OrganizeReplies(); } }
/// <summary> /// Returns an int with the amount of instructor evaluated rubrics that are currently saved as draft /// </summary> public int GetSavedAsDraftCount() { int draftRubricEvals = 0; using (OSBLEContext db = new OSBLEContext()) { draftRubricEvals = (from a in db.RubricEvaluations where a.AssignmentID == this.ID && !a.IsPublished && a.Evaluator.AbstractRole.CanGrade select a).Count(); } return(draftRubricEvals); }
private static double GetGradeHelper(int rubricEvaluationId, bool isStudent) { double gradeOnRubric = 0.0; using (OSBLEContext db = new OSBLEContext()) { RubricEvaluation re = db.RubricEvaluations.Find(rubricEvaluationId); //Calculate the rubric grade as a percent to display if (re.CriterionEvaluations.Count > 0) { int sumOfPointSpreads; //Below we are calculating the percent received on the rubric. if (isStudent) { sumOfPointSpreads = (from level in re.Assignment.StudentRubric.Levels select level.PointSpread).Sum(); } else { sumOfPointSpreads = (from level in re.Assignment.Rubric.Levels select level.PointSpread).Sum(); } double sumOfWeights = 0; double sumOfWeightedScores = 0; foreach (CriterionEvaluation critEval in re.CriterionEvaluations) { double currentWeight = critEval.Criterion.Weight; sumOfWeights += currentWeight; double?currentScore = critEval.Score; if (currentScore.HasValue) { sumOfWeightedScores += currentWeight * ((double)currentScore / (double)sumOfPointSpreads); } } if (sumOfWeights > 0) //In case there were no weights, we dont want to divide by 0 { gradeOnRubric = sumOfWeightedScores / sumOfWeights; } } } return(gradeOnRubric); }
public static DateTime CourseToUTC(this DateTime date, int?courseID) { using (var db = new OSBLEContext()) { int offsetVal = -8; if (courseID != null) { offsetVal = ((Course)db.AbstractCourses.Find(courseID)).TimeZoneOffset; } TimeZoneInfo tzInfo = GetTimeZone(offsetVal); return(TimeZoneInfo.ConvertTimeToUtc(date, tzInfo)); } }
/// <summary> /// Returns the number of new posts for currentCourseUserID for this discussion /// </summary> /// <param name="currentCourseUserID"></param> /// <returns></returns> public int GetNewPostsCount(int currentCourseUserId) { int returnVal = 0; using (OSBLEContext db = new OSBLEContext()) { if (Assignment.HasDiscussionTeams) //Filter by discussionTeamID { DiscussionAssignmentMetaInfo dtmi = (from mi in db.DiscussionAssignmentMetaTable where mi.CourseUserID == currentCourseUserId && mi.DiscussionTeamID == this.ID select mi).FirstOrDefault(); //if dtmi is null, set LastVisit to MinValue so all posts look new if (dtmi == null) { dtmi = new DiscussionAssignmentMetaInfo(); dtmi.LastVisit = DateTime.MinValue; } returnVal = (from dp in db.DiscussionPosts where dp.Posted > dtmi.LastVisit && dp.DiscussionTeamID == this.ID select dp).Count(); } else //Discussion team ID could be any discussion team in the class. So, queries are a little different { List <int> possibleDiscussionIDs = Assignment.DiscussionTeams.Select(dt => dt.ID).ToList(); DiscussionAssignmentMetaInfo dtmi = (from mi in db.DiscussionAssignmentMetaTable where mi.CourseUserID == currentCourseUserId && possibleDiscussionIDs.Contains(mi.DiscussionTeamID) select mi).FirstOrDefault(); //if dtmi is null, set LastVisit to MinValue so all posts look new if (dtmi == null) { dtmi = new DiscussionAssignmentMetaInfo(); dtmi.LastVisit = DateTime.MinValue; } returnVal = (from dp in db.DiscussionPosts where dp.Posted > dtmi.LastVisit && dp.AssignmentID == AssignmentID select dp).Count(); } } return(returnVal); }
/// <summary> /// Used in annotate to build a unique string for each document in OSBLE /// </summary> /// <param name="assignmentID">The assignment on which the submission took place (NOT THE CRITICAL REVIEW)</param> /// <param name="authorTeamID">The team that submitted the document</param> /// <returns></returns> public static string GetAnnotateDocumentName(int assignmentID, int authorTeamID) { using (OSBLEContext db = new OSBLEContext()) { Assignment assignment = db.Assignments.Find(assignmentID); AssignmentTeam assignmentTeam = new AssignmentTeam(); ReviewTeam reviewTeam = new ReviewTeam(); //needed for anchored discussion string fileName; if (assignment.Type == AssignmentTypes.AnchoredDiscussion) { reviewTeam = (from rt in db.ReviewTeams where rt.AssignmentID == assignment.ID && rt.AuthorTeamID == authorTeamID select rt ).FirstOrDefault(); fileName = string.Format( "{0}-{1}-{2}-{3}", assignment.CourseID, assignment.ID, reviewTeam.ReviewTeamID, assignment.Deliverables[0].ToString() ); } else { assignmentTeam = (from at in db.AssignmentTeams where at.AssignmentID == assignment.ID && at.TeamID == authorTeamID select at ).FirstOrDefault(); fileName = string.Format( "{0}-{1}-{2}-{3}", assignment.CourseID, assignment.ID, assignmentTeam.TeamID, assignment.Deliverables[0].ToString() ); } return(fileName); } }
public override DynamicDictionary BuildHeader(Assignment assignment) { dynamic header = Builder.BuildHeader(assignment); header.AssignmentDetails = new DynamicDictionary(); RubricEvaluation rubricEvaluation = null; //Getting the assignment team for Student, and if its non-null then we take that team ID and find the RubricEvaluation //that they were the recipient of. AssignmentTeam at = OSBLEController.GetAssignmentTeam(assignment, Student); int teamId = 0; if (at != null) { teamId = at.TeamID; using (OSBLEContext db = new OSBLEContext()) { //Only want to look at evaluations where Evaluator.AbstractRole.CanGrade is true, otherwise //the rubric evaluation is a student rubric (not interested in them here) rubricEvaluation = (from re in db.RubricEvaluations where re.AssignmentID == assignment.ID && re.Evaluator.AbstractRole.CanGrade && re.RecipientID == teamId select re).FirstOrDefault(); } } //If the Rubric has been evaluated and is published, calculate the rubric grade % to display to the student if (rubricEvaluation != null && rubricEvaluation.IsPublished) { header.AssignmentDetails.hasGrade = true; header.AssignmentDetails.assignmentID = assignment.ID; header.AssignmentDetails.cuID = Student.ID; header.AssignmentDetails.DisplayValue = "View Graded Rubric " + RubricEvaluation.GetGradeAsPercent(rubricEvaluation.ID); } else { header.AssignmentDetails.DisplayValue = "Not Graded"; header.AssignmentDetails.hasGrade = false; } return(header); }
/// <summary> /// This function builds the column for Rubric Grades in the instructor assignment details table. Note: This only handles non-student-evaluated rubrics. /// </summary> /// <param name="assignmentTeam"></param> /// <returns></returns> public override DynamicDictionary BuildTableForTeam(IAssignmentTeam assignmentTeam) { Assignment assignment = assignmentTeam.Assignment; dynamic data = Builder.BuildTableForTeam(assignmentTeam); data.Grade = new DynamicDictionary(); data.Grade.ActionValues = new { assignmentId = assignment.ID, cuId = assignmentTeam.Team.TeamMembers.FirstOrDefault().CourseUserID, area = "" }; RubricEvaluation rubricEvaluation = null; using (OSBLEContext db = new OSBLEContext()) { rubricEvaluation = db.RubricEvaluations.Where(re => re.RecipientID == assignmentTeam.TeamID && re.Evaluator.AbstractRole.CanGrade && re.AssignmentID == assignment.ID ).FirstOrDefault(); } data.Grade.LinkText = "Not Graded"; if (rubricEvaluation != null) { //A rubric exists, so if it is not published, it's saved as draft. If it is //published, the rubric grade should be displayed. if (rubricEvaluation.IsPublished == false) { data.Grade.LinkText = "Saved as Draft (" + RubricEvaluation.GetGradeAsPercent(rubricEvaluation.ID) + ")"; } else { data.Grade.LinkText = RubricEvaluation.GetGradeAsPercent(rubricEvaluation.ID); } } return(data); }
/// <summary> /// Validates the supplied user/pass combo. /// </summary> /// <param name="userName"></param> /// <param name="password"></param> /// <returns>True if the combo is valid, false otherwise</returns> public static bool ValidateUser(string userName, string password, bool encrypted = false) { int count = 0; using (OSBLEContext db = new OSBLEContext()) { string hashedPassword = !encrypted?UserProfile.GetPasswordHash(password) : password; count = (from user in db.UserProfiles where user.UserName.CompareTo(userName) == 0 && user.Password.CompareTo(hashedPassword) == 0 select user ).Count(); } if (count == 1) { return(true); } return(false); }
public static DateTime UTCToCourse(this DateTime date, int?courseID) { using (var db = new OSBLEContext()) { int offsetVal = -8; if (courseID != null) { //get Abstract Course AbstractCourse abstractCourse = db.AbstractCourses.Find(courseID); //check if it's a course or community if (abstractCourse is Course) { Course course = (Course)abstractCourse; offsetVal = course.TimeZoneOffset; } } TimeZoneInfo tzInfo = GetTimeZone(offsetVal); DateTime utcKind = DateTime.SpecifyKind(date, DateTimeKind.Utc); return(TimeZoneInfo.ConvertTimeFromUtc(utcKind, tzInfo)); } }
private void HandleCourseFileListingRequest(HttpContext context, Models.Users.UserProfile up, int courseID) { // Get the attributable file storage OSBLEDirectory attrFiles = Models.FileSystem.Directories.GetCourseDocs(courseID); if (null == attrFiles) { WriteErrorResponse(context, "Internal error: could not get attributable files manager for course files."); return; } // The permission-oriented attributes depend on the course user OSBLEContext db = new OSBLEContext(); CourseUser courseUser = (from cu in db.CourseUsers where cu.UserProfileID == up.ID && cu.AbstractCourse is AbstractCourse && cu.AbstractCourseID == courseID select cu).FirstOrDefault(); if (null == courseUser) { WriteErrorResponse(context, "User does not have permission to see files in this course."); return; } // Get XML file listing packaged up and return it to the client context.Response.Write( "<CourseFilesOpsResponse success=\"true\">" + attrFiles.GetXMLListing(courseUser, true) + "</CourseFilesOpsResponse>"); }
public OSBLEController(OSBLEContext context) { ActiveCourseUser = null; db = context; Initialize(); }
private AssignmentDetailsViewModel BuildTable(AssignmentDetailsViewModel vm) { //AC NOTE: Items will be displayed in the order in which they are added // to the ViewModel's TableColumnHeaders dictionary. Organize accordingly. Assignment assignment = vm.CurrentAssignment; List <IAssignmentTeam> teams = GetTeams(assignment); List <TeamEvaluation> teamEvaluations = null; List <DiscussionPost> allUserPosts = null; List <ReviewTeam> criticalReviewsPerformedTeams = new List <ReviewTeam>(); List <CriticalReviewsReceivedTeam> criticalReviewsReceivedTeams = new List <CriticalReviewsReceivedTeam>(); using (OSBLEContext db = new OSBLEContext()) { //only need get these when they are needed if (assignment.Type == AssignmentTypes.TeamEvaluation) { teamEvaluations = db.TeamEvaluations.Where(te => te.TeamEvaluationAssignmentID == assignment.ID).ToList(); } if (assignment.Type == AssignmentTypes.DiscussionAssignment || assignment.Type == AssignmentTypes.CriticalReviewDiscussion) { allUserPosts = (from a in db.DiscussionPosts where a.AssignmentID == assignment.ID select a).ToList(); } //run a common query outside of the loop for efficiency if (assignment.Type == AssignmentTypes.CriticalReview) { criticalReviewsPerformedTeams = (from rt in db.ReviewTeams .Include("ReviewingTeam") .Include("AuthorTeam") .Include("AuthorTeam.TeamMembers") where rt.AssignmentID == assignment.ID select rt).ToList(); criticalReviewsReceivedTeams = (from rt in db.ReviewTeams join t in db.Teams on rt.ReviewTeamID equals t.ID join tm in db.TeamMembers on rt.AuthorTeamID equals tm.TeamID where rt.AssignmentID == assignment.ID select new CriticalReviewsReceivedTeam() { CourseUser = tm.CourseUser, TeamName = t.Name, UserProfile = tm.CourseUser.UserProfile }).ToList(); } } //create a builder for each team foreach (IAssignmentTeam assignmentTeam in teams) { Team team = assignmentTeam.Team; vm.TeamTableBuilders[assignmentTeam] = new DefaultBuilder(); if (assignment.HasDeliverables) { //display submission information vm.TeamTableBuilders[assignmentTeam] = new DeliverablesTableDecorator(vm.TeamTableBuilders[assignmentTeam]); vm.TableColumnHeaders["DeliverablesTableDecorator"] = "Submission"; } if (assignment.HasCommentCategories) { //link to inline review vm.TeamTableBuilders[assignmentTeam] = new InlineReviewTableDecorator(vm.TeamTableBuilders[assignmentTeam]); vm.TableColumnHeaders["InlineReviewTableDecorator"] = "Inline Review"; } if (assignment.Type == AssignmentTypes.DiscussionAssignment || assignment.Type == AssignmentTypes.CriticalReviewDiscussion) { //add post count vm.TeamTableBuilders[assignmentTeam] = new DiscussionPostsTableDecorator(vm.TeamTableBuilders[assignmentTeam], allUserPosts); vm.TableColumnHeaders["DiscussionPostsTableDecorator"] = "Posts"; //add reply count vm.TeamTableBuilders[assignmentTeam] = new DiscussionRepliesTableDecorator(vm.TeamTableBuilders[assignmentTeam], allUserPosts); vm.TableColumnHeaders["DiscussionRepliesTableDecorator"] = "Replies"; //add total count vm.TeamTableBuilders[assignmentTeam] = new DiscussionTotalTableDecorator(vm.TeamTableBuilders[assignmentTeam], allUserPosts); vm.TableColumnHeaders["DiscussionTotalTableDecorator"] = "Total"; } if (assignment.Type == AssignmentTypes.CriticalReview) { CriticalReviewsReceivedDecorator crit = new CriticalReviewsReceivedDecorator(vm.TeamTableBuilders[assignmentTeam]); crit.ReviewTeams = criticalReviewsReceivedTeams; vm.TeamTableBuilders[assignmentTeam] = crit; vm.TableColumnHeaders["CriticalReviewsReceivedDecorator"] = "Reviews Received"; if (assignment.HasStudentRubric) { vm.TeamTableBuilders[assignmentTeam] = new StudentRubricsReceivedDecorator(vm.TeamTableBuilders[assignmentTeam]); vm.TableColumnHeaders["StudentRubricsReceivedDecorator"] = "Rubrics Received"; } CriticalReviewsPerformedDecorator performed = new CriticalReviewsPerformedDecorator(vm.TeamTableBuilders[assignmentTeam]); performed.ReviewTeams = criticalReviewsPerformedTeams; vm.TeamTableBuilders[assignmentTeam] = performed; vm.TableColumnHeaders["CriticalReviewsPerformedDecorator"] = "Reviews Performed"; } if (assignment.Type == AssignmentTypes.TeamEvaluation) { //AC TODO: Rewrite after I get new team evaluation model info. //Grabbing all the evaluations for the TeamEvaluation assignment List <TeamEvaluation> evaluations = teamEvaluations.Where(te => te.TeamEvaluationAssignmentID == assignment.ID).ToList(); //add team evaluation progress vm.TeamTableBuilders[assignmentTeam] = new TeamEvaluationProgressTableDecorator( vm.TeamTableBuilders[assignmentTeam], evaluations, assignment ); vm.TableColumnHeaders["TeamEvaluationProgressTableDecorator"] = "Evaluation Status"; //add team evaluation multiplier vm.TeamTableBuilders[assignmentTeam] = new TeamEvaluationMultiplierTableDecorator( vm.TeamTableBuilders[assignmentTeam], evaluations ); vm.TableColumnHeaders["TeamEvaluationMultiplierTableDecorator"] = "Multiplier"; } else { if (assignment.HasRubric) { //add rubric grade info vm.TeamTableBuilders[assignmentTeam] = new RubricTableDecorator( vm.TeamTableBuilders[assignmentTeam] ); vm.TableColumnHeaders["RubricTableDecorator"] = "Rubric Grade"; vm.TableColumnHeaders["LateRubricGradeTableDecorator"] = "Late Rubric Grade"; } if (assignment.HasDeliverables || (assignment.Type == AssignmentTypes.DiscussionAssignment || (assignment.Type == AssignmentTypes.CriticalReviewDiscussion))) { //add late penalty info vm.TeamTableBuilders[assignmentTeam] = new LatePenaltyTableDecorator( vm.TeamTableBuilders[assignmentTeam] ); vm.TableColumnHeaders["LatePenaltyTableDecorator"] = "Late Penalty"; } } // ABET stuff if (assignment.HasDeliverables && null != assignment.ABETDepartment) { vm.TeamTableBuilders[assignmentTeam] = new ABETProficiencyDecorator( vm.TeamTableBuilders[assignmentTeam]); vm.TableColumnHeaders["ABETProficiencyDecorator"] = "ABET Proficiency"; } } return(vm); }
public AnnotateResult ToggleCommentVisibility(int criticalReviewAssignmentID, int authorTeamID, bool makeVisible) { AnnotateResult result = new AnnotateResult(); Assignment criticalReview; result.Result = ResultCode.ERROR; string webResult = ""; long epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds; string apiKey = GenerateAnnotateKey("listNotes.php", ApiUser, epoch); WebClient client = new WebClient(); using (OSBLEContext db = new OSBLEContext()) { criticalReview = db.Assignments.Find(criticalReviewAssignmentID); //step 1: find all people reviewing the document var query = (from rt in db.ReviewTeams .Include("CourseUser") .Include("CourseUser.UserProfile") where rt.AssignmentID == criticalReviewAssignmentID && rt.AuthorTeamID == authorTeamID select rt.ReviewingTeam) .SelectMany(t => t.TeamMembers) .Distinct(); List <TeamMember> reviewers = query.ToList(); //step 2: get all comments for each reviewer on the team AnnotateResult documentResult = UploadDocument((int)criticalReview.PrecededingAssignmentID, authorTeamID); //TODO: the following line was replaced when helplab went down. change again when needed. //string rawNoteUrl = "http://helplab.org/annotate/php/listNotes.php?" + string rawNoteUrl = AnnotateURL + "/annotate/php/listNotes.php?" + "api-user={0}" + //Annotate admin user name (see web config) "&api-requesttime={1}" + //UNIX timestamp "&api-annotateuser={2}" + //the current user (reviewer) "&api-auth={3}" + //Annotate admin auth key "&d={4}" + //document date "&c={5}"; //document code string noteUrl = ""; foreach (TeamMember reviewer in reviewers) { //always refresh our epoch and api key epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds; apiKey = GenerateAnnotateKey("listNotes.php", reviewer.CourseUser.UserProfile.UserName, epoch); noteUrl = string.Format(rawNoteUrl, ApiUser, epoch, reviewer.CourseUser.UserProfile.UserName, apiKey, documentResult.DocumentDate, documentResult.DocumentCode ); try { webResult = client.DownloadString(noteUrl); dynamic jsonResult = Json.Decode(webResult); } catch (Exception) { throw; } } } return(result); }
/// <summary> /// Sends a document that resides on OSBLE to the Annotate server. /// If the document already exists on annotate's servers, this function will not resubmit /// unless forceUpload is set to TRUE. /// </summary> /// <param name="assignmentID">The assignment that the document belongs to</param> /// <param name="authorTeamID">The document's author</param> /// <param name="forceUpload">If set to TRUE, will force a document upload to annotate's servers</param> /// <returns></returns> public AnnotateResult UploadDocument(int assignmentID, int authorTeamID, bool forceUpload = false) { bool needsUpload = true; AnnotateResult result = new AnnotateResult(); result.Result = ResultCode.ERROR; //By default, we only upload documents to annotate if they haven't been uploaded //already. This can be overridden by setting forceUpload = true. if (forceUpload == false) { //check for existing document using (OSBLEContext db = new OSBLEContext()) { string docString = GetAnnotateDocumentName(assignmentID, authorTeamID); AnnotateDocumentReference code = (from c in db.AnnotateDocumentReferences where c.OsbleDocumentCode.CompareTo(docString) == 0 select c ).FirstOrDefault(); if (code == null) { needsUpload = true; } else { needsUpload = false; result.Result = ResultCode.OK; result.DocumentDate = code.AnnotateDocumentDate; result.DocumentCode = code.AnnotateDocumentCode; } } } if (needsUpload) { long epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds; WebClient client = new WebClient(); string sendResult = ""; //Submit document to annotate #if DEBUG //string documentUrl = "http://osble.org/content/icershort.pdf"; string documentUrl = "https://plus.osble.org/FileHandler/GetAnnotateDocument?assignmentID={0}&authorTeamID={1}&apiKey={2}"; documentUrl = string.Format(documentUrl, assignmentID, authorTeamID, ApiKey); #else string documentUrl = "https://plus.osble.org/FileHandler/GetAnnotateDocument?assignmentID={0}&authorTeamID={1}&apiKey={2}"; documentUrl = string.Format(documentUrl, assignmentID, authorTeamID, ApiKey); #endif string apiKey = GenerateAnnotateKey("uploadDocument.php", ApiUser, epoch); //TODO: this was changed when helplab.org went down. //string uploadString = "http://helplab.org/annotate/php/uploadDocument.php?" + string uploadString = AnnotateURL + "/annotate/php/uploadDocument.php?" + "api-user={0}" + //Annotate admin user name (see web config) "&api-requesttime={1}" + //UNIX timestamp "&api-annotateuser={2}" + //the current user (reviewer) "&api-auth={3}" + //Annotate admin auth key "&url={4}"; //URL of the document to upload uploadString = string.Format(uploadString, ApiUser, epoch, ApiUser, apiKey, HttpUtility.UrlEncode(documentUrl) ); try { sendResult = client.DownloadString(uploadString); //WriteLog("UploadDocument: " + sendResult); } catch (Exception ex) { result.RawMessage = ex.Message; result.Result = ResultCode.ERROR; return(result); } string documentCode = ""; string documentDate = ""; result.RawMessage = sendResult; if (sendResult.Substring(0, 2) == "OK") { result.Result = ResultCode.OK; string[] pieces = sendResult.Split(' '); documentDate = pieces[1]; documentCode = pieces[2]; result.DocumentCode = documentCode; result.DocumentDate = documentDate; //add DB entry into OSBLE so that we know something's been sent using (OSBLEContext db = new OSBLEContext()) { string docString = GetAnnotateDocumentName(assignmentID, authorTeamID); AnnotateDocumentReference code = (from c in db.AnnotateDocumentReferences where c.OsbleDocumentCode.CompareTo(docString) == 0 select c ).FirstOrDefault(); if (code == null) { code = new AnnotateDocumentReference(); db.AnnotateDocumentReferences.Add(code); } else { db.Entry(code).State = EntityState.Modified; } code.AnnotateDocumentCode = result.DocumentCode; code.AnnotateDocumentDate = result.DocumentDate; code.OsbleDocumentCode = docString; db.SaveChanges(); } } } return(result); }
private AssignmentDetailsViewModel BuildHeader(AssignmentDetailsViewModel vm) { //AC NOTE: Items will be displayed in the order in which they are added // to the ViewModel's HeaderViews list. Organize accordingly. Assignment assignment = vm.CurrentAssignment; vm.HeaderBuilder = new DefaultBuilder(); List <TeamEvaluation> teamEvaluations = null; using (OSBLEContext db = new OSBLEContext()) { //only need get these when they are needed if (assignment.Type == AssignmentTypes.TeamEvaluation) { teamEvaluations = db.TeamEvaluations.Where(te => te.TeamEvaluationAssignmentID == assignment.ID).ToList(); } } //views common to both students and teachers: if (assignment.Type == AssignmentTypes.DiscussionAssignment || assignment.Type == AssignmentTypes.CriticalReviewDiscussion) { //add initial / final post due date information //TODO: this will replace the "posts due" row vm.HeaderBuilder = new InitialFinalDueDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("InitialFinalDueDecorator"); } //not a team evaluation assignment if (assignment.Type != AssignmentTypes.TeamEvaluation && assignment.Type != AssignmentTypes.AnchoredDiscussion) { //add late policy vm.HeaderBuilder = new LatePolicyHeaderDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("LatePolicyHeaderDecorator"); } //teacher views //AC NOTE: Investigate the differences between CanGrade and CanModify if (vm.Client.AbstractRole.CanGrade || vm.Client.AbstractRole.CanModify) { //add deliverable information if needed if (assignment.HasDeliverables && assignment.Type != AssignmentTypes.AnchoredDiscussion) { //list deliverables add download link vm.HeaderBuilder = new TeacherDeliverablesHeaderDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("TeacherDeliverablesHeaderDecorator"); } //is a discussion assignment if (assignment.Type == AssignmentTypes.DiscussionAssignment && !assignment.HasDiscussionTeams) { //link to classwide discussion vm.HeaderBuilder = new TeacherDiscussionLinkDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("TeacherDiscussionLinkDecorator"); } if (assignment.HasRubric) { //add link to rubric ViewAsUneditable mode vm.HeaderBuilder = new RubricDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("RubricDecorator"); //Show rubric grading progress for assignments with rubrics vm.HeaderBuilder = new RubricGradingProgressDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("RubricGradingProgressDecorator"); } if (assignment.Type == AssignmentTypes.TeamEvaluation) { //Show progress of TeamEvaluation, such as "X of Y Team Evaluations completed" vm.HeaderBuilder = new TeamEvalProgressDecorator(vm.HeaderBuilder, teamEvaluations); vm.HeaderViews.Add("TeamEvalProgressDecorator"); } else if (assignment.Type == AssignmentTypes.CriticalReview) { vm.HeaderBuilder = new PublishCriticalReviewDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("PublishCriticalReviewDecorator"); } else if (assignment.Type == AssignmentTypes.AnchoredDiscussion) { //commented out: for now we don't need anything here for the instructor //in future implementations we may want to let the instructor also review documents with the group, but //how the teams are set up currently it wont work (no team set up for instructor) //link for critical review submission document //vm.HeaderBuilder = new AnchoredDiscussionSubmitDecorator(vm.HeaderBuilder, vm.Client); //vm.HeaderViews.Add("AnchoredDiscussionSubmitDecorator"); } // ABET outcomes - the ABETDepartment property being non-null indicates that // this assignment was labeled for ABET outcomes and assessment. if (null != assignment.ABETDepartment) { vm.HeaderBuilder = new ABETOutcomesDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("ABETOutcomesDecorator"); } } else if (vm.Client.AbstractRoleID == (int)OSBLE.Models.Courses.CourseRole.CourseRoles.Observer) { //has discussion teams? if (assignment.HasDiscussionTeams) { vm.HeaderBuilder = new DiscussionTeamMemberDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("DiscussionTeamMemberDecorator"); } if (assignment.HasRubric) { //add link to rubric ViewAsUneditable mode vm.HeaderBuilder = new RubricDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("RubricDecorator"); } if (assignment.HasDeliverables && assignment.Type != AssignmentTypes.AnchoredDiscussion) { //list deliverables add download link vm.HeaderBuilder = new TeacherDeliverablesHeaderDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("TeacherDeliverablesHeaderDecorator"); } else if (assignment.Type == AssignmentTypes.DiscussionAssignment && !assignment.HasDiscussionTeams) { //link to classwide discussion vm.HeaderBuilder = new StudentDiscussionLinkDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("StudentDiscussionLinkDecorator"); } else if (assignment.Type == AssignmentTypes.CriticalReview) { vm.HeaderBuilder = new TeacherDeliverablesHeaderDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("TeacherDeliverablesHeaderDecorator"); } } else if (vm.Client.AbstractRole.CanSubmit) //students { DateTime due = assignment.DueDate.AddHours(assignment.HoursLateWindow); due = due.UTCToCourse(vm.Client.AbstractCourseID); DateTime now = DateTime.UtcNow; now = now.UTCToCourse(vm.Client.AbstractCourseID); bool canSub = (now < due); //has discussion teams? if (assignment.HasDiscussionTeams) { vm.HeaderBuilder = new DiscussionTeamMemberDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("DiscussionTeamMemberDecorator"); } else if (assignment.HasTeams)//else has teams? { // add team name and list of members vm.HeaderBuilder = new TeamMembersDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("TeamMembersDecorator"); } //needs to submit? if (assignment.HasDeliverables) { if (assignment.Type == AssignmentTypes.AnchoredDiscussion) { //link for critical review submission document vm.HeaderBuilder = new AnchoredDiscussionSubmissionDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("AnchoredDiscussionSubmissionDecorator"); } else { //add student submission link vm.HeaderBuilder = new StudentSubmissionDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("StudentSubmissionDecorator"); } } else if (assignment.Type == AssignmentTypes.CriticalReview) { //critical review submission link vm.HeaderBuilder = new CriticalReviewSubmissionDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("CriticalReviewSubmissionDecorator"); //link for student to download their reviewed assignment vm.HeaderBuilder = new CriticalReviewStudentDownloadDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("CriticalReviewStudentDownloadDecorator"); } else if (assignment.Type == AssignmentTypes.AnchoredDiscussion) { //link for critical review submission document vm.HeaderBuilder = new AnchoredDiscussionSubmissionDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("AnchoredDiscussionSubmissionDecorator"); } else if (assignment.Type == AssignmentTypes.DiscussionAssignment && !assignment.HasDiscussionTeams) { //link to classwide discussion vm.HeaderBuilder = new StudentDiscussionLinkDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("StudentDiscussionLinkDecorator"); } else if (assignment.Type == AssignmentTypes.TeamEvaluation && canSub) { vm.HeaderBuilder = new StudentTeamEvalSubmissionDecorator(vm.HeaderBuilder, teamEvaluations, vm.Client); vm.HeaderViews.Add("StudentTeamEvalSubmissionDecorator"); } //rubric? if (assignment.HasRubric) { RubricEvaluation rubricEvaluation = null; //Getting the assignment team for Student, and if its non-null then we take that team ID and find the RubricEvaluation //that they were the recipient of. AssignmentTeam at = OSBLEController.GetAssignmentTeam(assignment, vm.Client); int teamId = 0; if (at != null) { teamId = at.TeamID; using (OSBLEContext db = new OSBLEContext()) { //Only want to look at evaluations where Evaluator.AbstractRole.CanGrade is true, otherwise //the rubric evaluation is a student rubric (not interested in them here) rubricEvaluation = (from re in db.RubricEvaluations where re.AssignmentID == assignment.ID && re.Evaluator.AbstractRole.CanGrade && re.RecipientID == teamId select re).FirstOrDefault(); } } //add rubric link if (rubricEvaluation == null) { vm.HeaderBuilder = new RubricDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("RubricDecorator"); } //add link to graded rubric link else { vm.HeaderBuilder = new RubricGradeDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("RubricGradeDecorator"); } } } else if (vm.Client.AbstractRoleID == (int)CourseRole.CourseRoles.Moderator) //Moderator decorators { //has discussion teams? if (assignment.HasDiscussionTeams) { vm.HeaderBuilder = new DiscussionTeamMemberDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("DiscussionTeamMemberDecorator"); } else if (assignment.Type == AssignmentTypes.DiscussionAssignment && !assignment.HasDiscussionTeams) { //link to classwide discussion vm.HeaderBuilder = new StudentDiscussionLinkDecorator(vm.HeaderBuilder, vm.Client); vm.HeaderViews.Add("StudentDiscussionLinkDecorator"); } } if (assignment.Type == AssignmentTypes.CriticalReview || assignment.Type == AssignmentTypes.CriticalReviewDiscussion || assignment.Type == AssignmentTypes.TeamEvaluation) { vm.HeaderBuilder = new PreviousAssignmentDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("PreviousAssignmentDecorator"); } if (assignment.Type == AssignmentTypes.CriticalReviewDiscussion && vm.Client.AbstractRole.CanGrade) { vm.HeaderBuilder = new DownloadDiscussionItemsDecorator(vm.HeaderBuilder); vm.HeaderViews.Add("DownloadDiscussionItemsDecorator"); } return(vm); }
private void HandleFileDeletionRequest(HttpContext context, Models.Users.UserProfile up, int courseID) { // Make sure they have access to this course. Right now we only let // people who can modify the course have access to this service function. if (!VerifyModifyPermissions(context, up, courseID)) { return; } // The permission-oriented attributes depend on the course user OSBLEContext db = new OSBLEContext(); CourseUser courseUser = (from cu in db.CourseUsers where cu.UserProfileID == up.ID && cu.AbstractCourse is AbstractCourse && cu.AbstractCourseID == courseID select cu).FirstOrDefault(); if (null == courseUser) { WriteErrorResponse(context, "User does not have permission to view or modify files in this course."); return; } // Make sure the file name parameter is present string fileName = string.Empty; if (!VerifyStringParam(context, "file_name", ref fileName)) { return; } if (string.IsNullOrEmpty(fileName)) { WriteErrorResponse(context, "The following parameter cannot be an empty string: file_name"); return; } // Make sure the file path name is OK (doesn't go up a level with ../ or // other things like that) if (!VerifyPath(context, ref fileName)) { return; } // Get the attributable file storage OSBLEDirectory courseFiles = Models.FileSystem.Directories.GetCourseDocs(courseID); OSBLEDirectory attrFiles = courseFiles; if (null == attrFiles) { WriteErrorResponse(context, "Internal error: could not get attributable files manager for course files."); return; } int slashIndex = fileName.LastIndexOf('\\'); if (-1 == slashIndex) { slashIndex = fileName.LastIndexOf('/'); } if (-1 != slashIndex) { // If the file exists in some nested folders then get the // correct directory object first. attrFiles = (OSBLEDirectory)attrFiles.GetDir(fileName.Substring(0, slashIndex)); // Also remove the path from the beginning of the file name fileName = fileName.Substring(slashIndex + 1); } // Perform the actual deletion attrFiles.DeleteFile(fileName); // Return success message with new file listing context.Response.Write( "<CourseFilesOpsResponse success=\"true\">" + courseFiles.GetXMLListing(courseUser, true) + "</CourseFilesOpsResponse>"); }
public void ProcessRequest(HttpContext context) { // This web service returns XML in most cases context.Response.ContentType = "text/xml"; // We need a "cmd" parameter to tell us what to deliver string cmdParam = context.Request.Params["cmd"]; if (string.IsNullOrEmpty(cmdParam)) { WriteErrorResponse(context, "Course file operations service requires a \"cmd\" parameter."); return; } // We need a "courseID" parameter int courseID = -1; if (!VerifyIntParam(context, "courseID", ref courseID)) { // Can't operate without this value return; } // Try to get the current OSBLE user Models.Users.UserProfile up = OSBLE.Utility.OsbleAuthentication.CurrentUser; if (null == up) { // In the future what I'd like to do here is look for a user name and // password in the request headers. This would allow this web service to // be used by other sources, but for now it requires a logged in OSBLE user. WriteErrorResponse(context, "Could not get active OSBLE user for request. Please login."); return; } // The permissions for service actions depend on the course user OSBLEContext db = new OSBLEContext(); CourseUser courseUser = (from cu in db.CourseUsers where cu.UserProfileID == up.ID && cu.AbstractCourse is AbstractCourse && cu.AbstractCourseID == courseID select cu).FirstOrDefault(); if (null == courseUser) { WriteErrorResponse(context, "User does not have permission to perform this action."); return; } // Now look at the command and handle it appropriately if ("course_files_list" == cmdParam) { HandleCourseFileListingRequest(context, up, courseID); return; } else if ("assignment_files_list" == cmdParam) { // Make sure they have access to this course. Right now we only let // people who can modify the course have access to this service. if (!VerifyModifyPermissions(context, up, courseID)) { return; } // The client wants a list of files from the attributable storage location // for the assignment. // First make sure we have the "assignmentID" parameter int aID = -1; if (!VerifyIntParam(context, "assignmentID", ref aID)) { return; } // Get the attributable file storage OSBLEDirectory attrFiles = Models.FileSystem.Directories.GetAssignment(courseID, aID).AttributableFiles; if (null == attrFiles) { WriteErrorResponse(context, "Internal error: could not get attributable files manager for assignment"); return; } // Get XML file listing packaged up and return it to the client context.Response.Write( "<CourseFilesOpsResponse success=\"true\">" + attrFiles.GetXMLListing(courseUser, false) + "</CourseFilesOpsResponse>"); return; } else if ("assignment_file_download" == cmdParam) { // First make sure we have the "assignmentID" parameter int aID = -1; if (!VerifyIntParam(context, "assignmentID", ref aID)) { return; } // Now make sure we have the "filename" parameter string fileName = context.Request.Params["filename"]; if (string.IsNullOrEmpty(fileName)) { WriteErrorResponse(context, "Missing required parameter: \"filename\""); return; } fileName = System.IO.Path.GetFileName(fileName); // Get the attributable file storage OSBLEDirectory attrFiles = Models.FileSystem.Directories.GetAssignment(courseID, aID).AttributableFiles; if (null == attrFiles) { WriteErrorResponse(context, "Internal error: could not get attributable files manager for assignment"); return; } // Make sure the file exists OSBLEFile af = attrFiles.GetFile(fileName); if (null == af) { WriteErrorResponse(context, "Internal error: could not get attributable file"); return; } // Make sure the user has permission to download, if the user is not able to modify the course or the assignment date is not // past the due time plus the hours late window if (null == courseUser || (!af.CanUserDownload(courseUser) && !DBHelper.AssignmentDueDatePast(aID, courseUser.AbstractCourseID))) { WriteErrorResponse(context, "User does not have permission to download this file"); return; } if (fileName.ToLower().EndsWith(".pdf")) { context.Response.ContentType = "application/pdf"; } else { context.Response.ContentType = "application/octet-stream"; } context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // Transmit file data context.Response.TransmitFile(af.DataFileName); return; } else if ("assignment_file_delete" == cmdParam) { // First make sure we have the "assignmentID" parameter int aID = -1; if (!VerifyIntParam(context, "assignmentID", ref aID)) { return; } // Now make sure we have the "filename" parameter string fileName = context.Request.Params["filename"]; if (string.IsNullOrEmpty(fileName)) { WriteErrorResponse(context, "Missing required parameter: \"filename\""); return; } fileName = System.IO.Path.GetFileName(fileName); // Get the attributable file storage OSBLEDirectory attrFiles = Models.FileSystem.Directories.GetAssignment(courseID, aID).AttributableFiles; if (null == attrFiles) { WriteErrorResponse(context, "Internal error: could not get attributable files manager for assignment"); return; } // Make sure the file exists OSBLEFile af = attrFiles.GetFile(fileName); if (null == af) { WriteErrorResponse(context, "Internal error: could not get attributable file"); return; } //Delete file attrFiles.DeleteFile(fileName); // Return success message with new file listing /*context.Response.Write( * "<CourseFilesOpsResponse success=\"true\">" + * attrFiles.GetXMLListing(courseUser, true) + * "</CourseFilesOpsResponse>");*/ //TODO: fix this... this is a hack... //without redirecting to this page, the user is directed to an XML error page, and has to hit 'back' in order to see the file deleted //This also introduces a bug where the assignment timestamp is now -7 of what it previously was... //this code should redirect back to the page that called this event. //context.Response.Redirect("/AssignmentWizard/Basics"); string referrer = context.Request.UrlReferrer.ToString(); if (!String.IsNullOrEmpty(referrer)) { context.Response.Redirect(context.Request.UrlReferrer.ToString()); } return; } else if ("create_folder" == cmdParam) { // Make sure they have access to this course. Right now we only let // people who can modify the course have access to this service function. if (!VerifyModifyPermissions(context, up, courseID)) { return; } // Make sure the folder name parameter is present string folderName = string.Empty; if (!VerifyStringParam(context, "folder_name", ref folderName)) { return; } if (string.IsNullOrEmpty(folderName)) { WriteErrorResponse(context, "The following parameter cannot be an empty string: folder_name"); return; } // Make sure the folder name is OK if (!VerifyPath(context, ref folderName)) { return; } // Get the attributable file storage OSBLEDirectory attrFiles = Models.FileSystem.Directories.GetCourseDocs(courseID); if (null == attrFiles) { WriteErrorResponse(context, "Internal error: could not get attributable files manager for course files."); return; } // Create the directory attrFiles.CreateDir(folderName); // Return success message with new file listing context.Response.Write( "<CourseFilesOpsResponse success=\"true\">" + attrFiles.GetXMLListing(courseUser, true) + "</CourseFilesOpsResponse>"); return; } else if ("delete_file" == cmdParam) { HandleFileDeletionRequest(context, up, courseID); } else if ("delete_folder" == cmdParam) { HandleFolderDeletionRequest(context, up, courseID); return; } else if ("rename_file" == cmdParam) { HandleFileRenameRequest(context, up, courseID, courseUser); } else if ("rename_folder" == cmdParam) { // Make sure they have access to this course. Right now we only let // people who can modify the course have access to this service function. if (!VerifyModifyPermissions(context, up, courseID)) { return; } // Make sure the folder name parameter is present string folderName = string.Empty; if (!VerifyStringParam(context, "folder_name", ref folderName)) { return; } if (string.IsNullOrEmpty(folderName)) { WriteErrorResponse(context, "The following parameter cannot be an empty string: folder_name"); return; } // Make sure the folder name is OK if (!VerifyPath(context, ref folderName)) { return; } // Get the attributable file storage OSBLEDirectory attrFiles = Models.FileSystem.Directories.GetCourseDocs(courseID); if (null == attrFiles) { WriteErrorResponse(context, "Internal error: could not get attributable files manager for course files."); return; } // Combine the relative path from the request (which has been checked // to make sure it's ok) with the path of the course files. string path = System.IO.Path.Combine(attrFiles.GetPath(), folderName); if (!System.IO.Directory.Exists(path)) { // We can't rename a directory that doesn't exist WriteErrorResponse(context, "Error: Could not find folder to rename: " + folderName); return; } // Now make sure we have the new_name parameter string newName = string.Empty; if (!VerifyStringParam(context, "new_name", ref newName)) { return; } // Verify that it's OK if (!VerifyPath(context, ref newName)) { return; } // Also it must be just the folder name and not have / or \ if (newName.Contains('/') || newName.Contains('\\')) { WriteErrorResponse(context, "New folder name must not contain a path, just the new folder name."); return; } // Lastly, it must not be empty if (string.IsNullOrEmpty(newName)) { WriteErrorResponse(context, "New folder name cannot be empty."); return; } string newNameFull = System.IO.Path.Combine( System.IO.Path.GetDirectoryName(path), newName); // Do the actual rename (move) System.IO.Directory.Move(path, newNameFull); // Do the same for the corresponding folder in the attributable // files directory path = System.IO.Path.Combine(attrFiles.AttrFilesPath, folderName); if (System.IO.Directory.Exists(path)) { newNameFull = System.IO.Path.Combine( System.IO.Path.GetDirectoryName(path), newName); System.IO.Directory.Move(path, newNameFull); } // Return success message with new file listing context.Response.Write( "<CourseFilesOpsResponse success=\"true\">" + attrFiles.GetXMLListing(courseUser, true) + "</CourseFilesOpsResponse>"); return; } else { // Coming here implies an unknown command WriteErrorResponse(context, "Unknown command: " + cmdParam); } }
public CoursesController() : base() { db = new OSBLEContext(); currentUser = OsbleAuthentication.CurrentUser; }
public void ProcessRequest(HttpContext context) { HttpFileCollection coll; //yc: set the max upload size try { coll = context.Request.Files; context.Response.ContentType = "text/xml"; if (0 == coll.Count) { WriteErrorResponse(context, "Course file upload service requires one or more files in the request. " + "It's possible that your browser did not correctly send the file data " + "and you may need to update your browser if the problem persists."); return; } // We're expecting the course ID to be in a parameter (required) string courseIDParam = context.Request.Params["courseID"]; if (string.IsNullOrEmpty(courseIDParam)) { WriteErrorResponse(context, "Course file upload service requires a \"courseID\" parameter."); return; } // Make sure the course ID is an integer and a valid course ID at that int courseID; if (!int.TryParse(courseIDParam, out courseID)) { WriteErrorResponse(context, "The course ID must be a valid integer value."); return; } // There might be an optional "target_folder" parameter string targetFolderParam = context.Request.Params["target_folder"]; // Try to get the current OSBLE user Models.Users.UserProfile up = OSBLE.Utility.OsbleAuthentication.CurrentUser; if (null == up) { // In the future what I'd like to do here is look for a user name and // password in the request headers. This would allow this web service to // be used by other sources, but for now it requires a logged in OSBLE user. WriteErrorResponse(context, "Could not get active OSBLE user for request. Please login."); return; } // Make sure this user has permission to upload to this course OSBLEContext _db = new OSBLEContext(); CourseUser courseUser = ( from cu in _db.CourseUsers where cu.UserProfileID == up.ID && cu.AbstractCourse is AbstractCourse && cu.AbstractCourseID == courseID select cu ).FirstOrDefault(); if (null == courseUser || !courseUser.AbstractRole.CanUploadFiles) { // User cannot upload files for this course context.Response.Write( "<CourseFilesUploaderResponse success=\"false\">" + " <Message>The specified user does not have access to course with ID=" + courseID.ToString() + ". User must be " + "a course owner to access this service.</Message>" + "</CourseFilesUploaderResponse>"); return; } // We will look for an optional "fileusage" parameter that tells us where // the file(s) will go. By default we use "generic" if the parameter is // absent. string fileUsage = context.Request.Params["fileusage"]; if (string.IsNullOrEmpty(fileUsage)) { // Default to "generic", which puts files in the CourseDocs folder. fileUsage = "generic"; } else { fileUsage = fileUsage.ToLower(); } // Save based on the usage if ("generic" == fileUsage) { OSBLEDirectory location = Models.FileSystem.Directories.GetCourseDocs(courseID); // For now the target folder parameter is only allowed for generic files if (!string.IsNullOrEmpty(targetFolderParam) && "\\" != targetFolderParam && "/" != targetFolderParam) { // We can't let it start with / or \ while (targetFolderParam.StartsWith("\\")) { targetFolderParam = targetFolderParam.Substring(1); } while (targetFolderParam.StartsWith("/")) { targetFolderParam = targetFolderParam.Substring(1); } location = location.GetDir(targetFolderParam); if (null == location) { WriteErrorResponse(context, "Could not upload to target folder: " + targetFolderParam); return; } } // Save each file to the target directory for (int i = 0; i < coll.Count; i++) { HttpPostedFile postedFile = coll[i]; //yc: check the file size in MB int size = postedFile.ContentLength / 1024 / 1024; //contentLenght(BYTES)/ 1024 (gets KB) / 1024 (GETS MB) if (size < 30) { } else { //too large } string fileName = Path.GetFileName(postedFile.FileName); location.AddFile(fileName, postedFile.InputStream); } context.Response.Write(string.Format( "<CourseFilesUploaderResponse success=\"true\">" + " <Message>Successfully uploaded {0} files</Message>" + "</CourseFilesUploaderResponse>", coll.Count)); return; } else if ("assignment_description" == fileUsage || "assignment_solution" == fileUsage) { // In this case we also need an assignment ID parameter string aIDString = context.Request.Params["assignmentID"]; if (string.IsNullOrEmpty(aIDString)) { WriteErrorResponse(context, "An \"assignmentID\" parameter is required when uploading a " + "file for an assignment " + (("assignment_description" == fileUsage) ? "description." : "solution.")); return; } int aID; if (!int.TryParse(aIDString, out aID)) { WriteErrorResponse(context, "The \"assignmentID\" parameter must be an integer value."); return; } // Assignment must exist Models.FileSystem.AssignmentFilePath afs = Models.FileSystem.Directories.GetAssignment(courseID, aID); if (null == afs) { WriteErrorResponse(context, "Could not get assignment file path for assignment: " + aIDString); return; } // Get the attributable files storage for this assignment OSBLE.Models.FileSystem.OSBLEDirectory attrFiles = afs.AttributableFiles; if (null == attrFiles) { WriteErrorResponse(context, "Internal error: could not get attributable files manager for assignment"); return; } // Set up the system attributes for this file Dictionary <string, string> sys = new Dictionary <string, string>(); sys.Add("created", DateTime.Now.ToString()); sys.Add(fileUsage, aIDString); sys.Add("uploadedby", up.UserName); if ("assignment_solution" != fileUsage) { sys.Add("any_course_user_can_download", null); } // Save each file to the target directory for (int i = 0; i < coll.Count; i++) { HttpPostedFile postedFile = coll[i]; string fileName = Path.GetFileName(postedFile.FileName); attrFiles.AddFile(fileName, postedFile.InputStream, sys, null); } context.Response.Write(string.Format( "<CourseFilesUploaderResponse success=\"true\">" + " <Message>Successfully uploaded {0} files</Message>" + "</CourseFilesUploaderResponse>", coll.Count)); return; } // Coming here implies we didn't recognize the file usage WriteErrorResponse(context, "Unsupported file usage: " + fileUsage); } catch (HttpException ex) { if (ex.WebEventCode == 3004) { WriteErrorResponse(context, "File exceeds 30MB upload limit"); return; } } // This web service returns XML }
public override DynamicDictionary BuildHeader(Assignment assignment) { dynamic header = Builder.BuildHeader(assignment); header.Submission = new DynamicDictionary(); header.IsAnnotatable = new bool(); header.DeliverableType = assignment.Deliverables.FirstOrDefault().Type; DateTime?submissionTime = null; //get id of current student's team List <TeamMember> allMembers = assignment.AssignmentTeams.SelectMany(at => at.Team.TeamMembers).ToList(); TeamMember member = allMembers.Where(m => m.CourseUserID == Student.ID).FirstOrDefault(); header.Submission.allowSubmit = true; //get submission time: foreach (AssignmentTeam team in assignment.AssignmentTeams) { //if the team matches with the student if (team.TeamID == member.TeamID) { submissionTime = team.GetSubmissionTime(); break; } } if (submissionTime == null) { header.Submission.hasSubmitted = false; } else { header.Submission.hasSubmitted = true; header.Submission.SubmissionTime = submissionTime.Value.ToString(); } header.Submission.assignmentID = assignment.ID; FileCache Cache = FileCacheHelper.GetCacheInstance(OsbleAuthentication.CurrentUser); //Same functionality as in the other controller. //did the user just submit something? If so, set up view to notify user if (Cache["SubmissionReceived"] != null && Convert.ToBoolean(Cache["SubmissionReceived"]) == true) { header.Submission.SubmissionReceived = true; Cache["SubmissionReceived"] = false; } else { header.Submission.SubmissionReceived = false; Cache["SubmissionReceived"] = false; } //handle link for viewing annotated documents RubricEvaluation rubricEvaluation = null; //Getting the assignment team for Student, and if its non-null then we take that team ID and find the RubricEvaluation //that they were the recipient of. AssignmentTeam ateam = OSBLEController.GetAssignmentTeam(assignment, Student); int teamId = 0; if (ateam != null) { teamId = ateam.TeamID; header.Submission.authorTeamID = teamId; using (OSBLEContext db = new OSBLEContext()) { //Only want to look at evaluations where Evaluator.AbstractRole.CanGrade is true, otherwise //the rubric evaluation is a student rubric (not interested in them here) rubricEvaluation = (from re in db.RubricEvaluations where re.AssignmentID == assignment.ID && re.Evaluator.AbstractRole.CanGrade && re.RecipientID == teamId select re).FirstOrDefault(); //if annotatable if (assignment.IsAnnotatable) { //yc: determine if there has been an annotation for this document //there will be an issue with linking from a critical review untill further discussion on how to handle this //when an instructor grades this, the reviewerid of the annoation is the teamid string lookup = assignment.CourseID.ToString() + "-" + assignment.ID.ToString() + "-" + teamId.ToString() + "-"; AnnotateDocumentReference d = (from adr in db.AnnotateDocumentReferences where adr.OsbleDocumentCode.Contains(lookup) select adr).FirstOrDefault(); if (d != null && assignment.DueDate < DateTime.UtcNow) { header.IsAnnotatable = true; } else { header.IsAnnotatable = false; } } else { header.IsAnnotatable = false; } } } //If the Rubric has been evaluated and is published, calculate the rubric grade % to display to the student if (rubricEvaluation != null && rubricEvaluation.IsPublished) { header.IsPublished = true; } else { header.IsPublished = false; } return(header); }
/// <summary> /// This gets the late penalty for a regular assignment. Will not currently work for Critical Review assignments /// Returns the late penalty as a percentage. I.e. 80% late penalty will return as 80.0 /// </summary> /// <param name="team"></param> /// <returns></returns> public static double GetLatePenalty(IAssignmentTeam team) { var latePenalty = 0.0; DateTime?submissionTime = null; var dueDate = team.Assignment.DueDate + TimeSpan.FromMinutes(1); //Need initial value to get compiler to be quiet. if (team.Assignment.HasDeliverables) { //Handle late penaly based off deliverable submission time submissionTime = FileSystem.GetSubmissionTime(team); //Adding 1 minute to dueDate. This is to keep submissions turned in at 12:00am for an assignment with a due date of 12:00am as non-late. dueDate = team.Assignment.DueDate + TimeSpan.FromMinutes(1); } else if (team.Assignment.Type == AssignmentTypes.DiscussionAssignment || team.Assignment.Type == AssignmentTypes.CriticalReviewDiscussion) { //Handle late penalty based off of initial post due date. //Note that the team sent in is a non-db saved, forged team. The teamID corrisponds to the correct team, but there is only one teammember //and that is the user we want the late penaly for. var cuID = team.Team.TeamMembers.First().CourseUserID; using (OSBLEContext db = new OSBLEContext()) { submissionTime = (from dp in db.DiscussionPosts where dp.AssignmentID == team.AssignmentID && dp.CourseUserID == cuID orderby dp.Posted select dp.Posted).FirstOrDefault(); } dueDate = team.Assignment.DiscussionSettings.InitialPostDueDate + TimeSpan.FromMinutes(1); } TimeSpan lateness; if (submissionTime != null && submissionTime != DateTime.MinValue) { lateness = (DateTime)submissionTime - dueDate; } else //if the assignment has not been submitted, use the current time to calculate late penalty. { lateness = DateTime.UtcNow - dueDate; } if (lateness.TotalHours >= team.Assignment.HoursLateWindow) { //The document (or post) is too late to be accepted. Therefor 100% late penalty latePenalty = 100; } else if (lateness.TotalHours <= 0) { //The document (or post) wasnt late at all, no late penalty latePenalty = 0; } else { //The document (or post) was late, but less than HoursLateWindow //So, to calculate the late penalty,we want integer division here to keep units whole. //Example of applying late penalty: A submission is 25hours late, HoursPerDeduction is 24 //gets 2 deductions. 1 for the (0,24] hour late range, and then another for the (24,48] hour late range. //Notice begining of ranges are non-inclusive. This was handled by adding 1 minute to dueDate above. var numberOfDeductions = 1; numberOfDeductions += ((int)lateness.TotalHours / (int)team.Assignment.HoursPerDeduction); latePenalty = numberOfDeductions * team.Assignment.DeductionPerUnit; //cannot have higher than 100% late penalty if (latePenalty > 100) { latePenalty = 100; } } return(latePenalty); }
public override DynamicDictionary BuildHeader(Assignment assignment) { dynamic header = Builder.BuildHeader(assignment); header.Assignment = assignment; header.CRdownload = new DynamicDictionary(); header.CRdownload.hasPublished = assignment.IsCriticalReviewPublished; header.CRdownload.publishedDate = assignment.CriticalReviewPublishDate; header.CRdownload.hasRubricToView = false; //get student's team AssignmentTeam assignmentTeam = null; assignmentTeam = OSBLEController.GetAssignmentTeam(assignment.PreceedingAssignment, Student); header.CRdownload.teamID = assignmentTeam.TeamID; header.CRdownload.hasRecievedReview = false; //PDF reviews don't get sent to the file system (they get sent to annotate) //so we can't check the file system for review items. //yc: but we can check to see if the file has been submitted into annotate //dbo.annotatedocumentreferences has a field osbledocumentcode, and we have the date it was "uploaded" //it follows the format:#-#-#-filename.PDF == courseID-PreviousAssignmentid-teamthatisreviewingreviewing-filename.PDF //we also have dbo.reviewteams that show if some one has reviewed your assignment Assignment previousAssignment = assignment.PreceedingAssignment; //yc: locate all reivew teams ReviewTeam reviewers = null; bool foundAnnotateEntry = false; using (OSBLEContext db = new OSBLEContext()) { if (assignmentTeam != null) { reviewers = (from rte in db.ReviewTeams where rte.AuthorTeamID == assignmentTeam.TeamID select rte).FirstOrDefault(); } if (reviewers != null) { //if a review team exists, determin if the annoation exisits string lookup = assignment.CourseID.ToString() + "-" + previousAssignment.ID.ToString() + "-" + assignmentTeam.TeamID.ToString() + "-"; AnnotateDocumentReference d = (from adr in db.AnnotateDocumentReferences where adr.OsbleDocumentCode.Contains(lookup) select adr).FirstOrDefault(); if (d != null && (assignment.DueDate < DateTime.Now || assignment.IsCriticalReviewPublished)) { foundAnnotateEntry = true; } } } if (foundAnnotateEntry)//( //previousAssignment.HasDeliverables //&& previousAssignment.Deliverables[0].DeliverableType == DeliverableType.PDF //&& previousAssignment.Deliverables.Count == 1 //) { header.CRdownload.hasRecievedReview = true; } else { if (assignmentTeam != null) { //get list of all teams reviewing student List <AssignmentTeam> reviewersOfStudent = (from rt in assignment.ReviewTeams join at in assignment.AssignmentTeams on rt.ReviewTeamID equals at.TeamID where rt.AuthorTeamID == assignmentTeam.TeamID select at).ToList(); //check each team for a submission foreach (AssignmentTeam at in reviewersOfStudent) { //if(at.GetSubmissionTime() != null) if (FileSystem.GetSubmissionTime(at, assignmentTeam.Team) != null) { header.CRdownload.hasRecievedReview = true; break; } } } //check if there is at one student rubric that has been filled out for the current user if (assignment.HasStudentRubric) { using (OSBLEContext db = new OSBLEContext()) { header.CRdownload.hasRubricToView = (from e in db.RubricEvaluations where e.AssignmentID == assignment.ID && e.RecipientID == assignmentTeam.TeamID && e.Evaluator.AbstractRoleID == (int)CourseRole.CourseRoles.Student && e.DatePublished != null select e.ID).Count() > 0; } } } header.CRdownload.student = Student; header.CRdownload.assignmentID = assignment.ID; return(header); }
/// <summary> /// This function prepares DiscussionPostViewModels for a Critical Review Discussion. /// </summary> private void InitializeViewModelForCriticalReviewDiscussion() { //booleans used for anonymization checks bool currentUserIsAuthor = discussionTeam.AuthorTeam.TeamMembers.Where(tm => tm.CourseUserID == currentUser.ID).ToList().Count > 0; bool currentUserIsReviewer = discussionTeam.Team.TeamMembers.Where(tm => tm.CourseUserID == currentUser.ID).ToList().Count > 0; using (OSBLEContext db = new OSBLEContext()) { //Gathering all posts made by students on discussionTeam.AuthorTeam. List <DiscussionPost> AuthorPosts = (from Team authorTeam in db.Teams join TeamMember member in db.TeamMembers on authorTeam.ID equals member.TeamID join DiscussionPost post in db.DiscussionPosts .Include("CourseUser") .Include("CourseUser.AbstractRole") on member.CourseUserID equals post.CourseUserID where authorTeam.ID == discussionTeam.AuthorTeamID && post.DiscussionTeamID == discussionTeam.ID select post).ToList(); //Gathering all posts made by students on discussionTeam.Team. Note: (Some of these will be duplcates from AuthorDiscussionPosts. Handle later) List <DiscussionPost> ReviewerPosts = (from Team reviewTeam in db.Teams join TeamMember member in db.TeamMembers on reviewTeam.ID equals member.TeamID join DiscussionPost post in db.DiscussionPosts .Include("CourseUser") .Include("CourseUser.AbstractRole") on member.CourseUserID equals post.CourseUserID where reviewTeam.ID == discussionTeam.TeamID && post.DiscussionTeamID == discussionTeam.ID && post.CourseUser.AbstractRoleID == (int)CourseRole.CourseRoles.Student select post).ToList(); //Gathering all non-student posts. (TAs, moderators, instructors) List <DiscussionPost> NonStudentPosts = (from DiscussionPost post in db.DiscussionPosts .Include("CourseUser") .Include("CourseUser.AbstractRole") where post.DiscussionTeamID == discussionTeam.ID && post.CourseUser.AbstractRoleID != (int)CourseRole.CourseRoles.Student select post).ToList(); //Gathering all posts made by students no longer in the discusison. First gathering all student posts... List <DiscussionPost> OldReviewerPosts = (from DiscussionPost post in db.DiscussionPosts .Include("CourseUser") .Include("CourseUser.AbstractRole") where post.DiscussionTeamID == discussionTeam.ID && post.CourseUser.AbstractRoleID == (int)CourseRole.CourseRoles.Student select post).ToList(); //...then removing Author and reviewer posts OldReviewerPosts = OldReviewerPosts.Except(AuthorPosts).Except(ReviewerPosts).ToList(); //Now that we have our lists, we will remove duplicates and convert each lists based off Author, Reviewers, Author/Reviewers, and finally NonStudent List <DiscussionPost> AuthorReviewers = AuthorPosts.Intersect(ReviewerPosts, new DiscussionPostComparer()).ToList(); //Converting AuthorPosts to ViewModels, then authorReviewers, then Reviewers, and finally NonSTudent posts. ConvertPostsToViewModel(AuthorPosts.Except(AuthorReviewers, new DiscussionPostComparer()).ToList(), "Author", currentUserIsAuthor, currentUserIsReviewer); ConvertPostsToViewModel(ReviewerPosts.Except(AuthorReviewers, new DiscussionPostComparer()).ToList(), "Reviewer", currentUserIsAuthor, currentUserIsReviewer); ConvertPostsToViewModel(OldReviewerPosts, "Reviewer", currentUserIsAuthor, currentUserIsReviewer); ConvertPostsToViewModel(AuthorReviewers.ToList(), "Author/Reviewer", currentUserIsAuthor, currentUserIsReviewer); ConvertPostsToViewModel(NonStudentPosts.ToList(), null, currentUserIsAuthor, currentUserIsReviewer); //Now adding all the replies from ReplyListViewModels into their correct discussionPost OrganizeReplies(); } }