/// <summary> /// This is an internal helper function. This function will bring back an SLKStore Object. /// </summary> /// <returns>SLKStore Object stamped with the currently logged user</returns> private SlkStore GetSLKStore() { try { //Getting User Object using (SPSite siteForUser = new SPSite(classesUrl)) { using (SPWeb webForUser = siteForUser.RootWeb) { //TODO: Does not handle invalid users gracefully. SPUserToken token = webForUser.AllUsers[Username].UserToken; using (SPSite site = new SPSite(classesUrl, token)) { using (SPWeb web = site.OpenWeb()) { return(SlkStore.GetStore(web)); } } } } } catch (Exception exception) { hasError = true; errorDesc = exception.Message; return(null); } }
/// <summary> /// Adds a SharePoint Web site to the SLK user web list of a given user. A user web list is /// the list of Web sites shown in E-Learning Actions pages that are displayed within a given /// site collection. /// </summary> /// /// <param name="loginName">The login name, e.g. "MyDomain\SlkLearner123". If the login name /// starts with ".\", it's assumed to be a local machine account.</param> /// /// <param name="siteCollectionUrl">The URL of the site collection containing the user web /// list to update.</param> /// /// <param name="webSiteUrl">The URL of the Web site to add to the user web list.</param> /// static void AddToUserWebList(string loginName, string siteCollectionUrl, string webSiteUrl) { Console.WriteLine("Adding \"{0}\" to the user web list of \"{1}\" in \"{2}\"", webSiteUrl, loginName, siteCollectionUrl); // "log in" to SharePoint as the user running this program using (SPSite currentUserSite = new SPSite(siteCollectionUrl)) { if (loginName.StartsWith(@".\")) { loginName = String.Format(@"{0}\{1}", currentUserSite.HostName, loginName.Substring(2)); } SPWeb rootWeb = currentUserSite.RootWeb; // set <spUser> to the user corresponding to <loginName> SPUser spUser = rootWeb.AllUsers[loginName]; // "log in" to SharePoint as the user <spUser>, and set <slkStore> to refer to that // user and the site collection specified by <siteCollectionUrl> using (SPSite destinationSite = new SPSite(webSiteUrl, spUser.UserToken)) { using (SPWeb destinationWeb = destinationSite.OpenWeb()) { SlkStore slkStore = SlkStore.GetStore(destinationWeb); slkStore.AddToUserWebList(destinationWeb); } } } }
/// <summary>Process the emails for a given url.</summary> public void Process(string url) { using (SPSite site = new SPSite(url)) { using (SPWeb web = site.OpenWeb()) { SlkStore store = SlkStore.GetStore(web); Process(store); } } }
void CreateSitesDropDown() { SPWeb web = SPContext.Current.Web; SlkStore store = SlkStore.GetStore(web); webList = new UserWebList(store, web); sites = new DropDownList(); foreach (WebListItem item in webList.Items) { sites.Items.Add(new ListItem(item.Title, item.SPWebGuid.ToString())); } Controls.Add(sites); }
protected override void OnLoad(EventArgs e) { // ensure the user is an administrator, then execute the remaining code within a // LearningStorePrivilegedScope (which grants full access to database views) if (!SPFarm.Local.CurrentUserIsAdministrator()) { throw new UnauthorizedAccessException( "Access is denied. Only adminstrators can access this page."); } using (new LearningStorePrivilegedScope()) { // skip the code below during postback since <OriginalInstructor> will have been // populated from view state already if (IsPostBack) { return; } // populate the <OriginalInstructor> drop-down list with the names and SLK user // identifiers of all users who are instructors on any assignments in the current // SharePoint site collection using (SPWeb spWeb = SPControl.GetContextWeb(HttpContext.Current)) { SlkStore slkStore = SlkStore.GetStore(spWeb); LearningStoreJob job = slkStore.LearningStore.CreateJob(); LearningStoreQuery query = slkStore.LearningStore.CreateQuery( "AllAssignmentInstructors"); query.SetParameter("SPSiteGuid", spWeb.Site.ID); query.AddColumn("InstructorName"); query.AddColumn("InstructorId"); query.AddSort("InstructorName", LearningStoreSortDirection.Ascending); job.PerformQuery(query); DataRowCollection rows = job.Execute <DataTable>().Rows; OriginalInstructor.Items.Add(String.Empty); foreach (DataRow row in rows) { ListItem listItem = new ListItem(); listItem.Text = (string)row["InstructorName"]; UserItemIdentifier originalInstructorId = new UserItemIdentifier((LearningStoreItemIdentifier)row["InstructorId"]); listItem.Value = originalInstructorId.GetKey().ToString( CultureInfo.InvariantCulture); OriginalInstructor.Items.Add(listItem); } } } }
bool Show() { if (showEvaluated == false) { if (AlwaysShow) { show = true; } else { SPWeb web = SPContext.Current.Web; SlkStore store = SlkStore.GetStore(web); show = store.IsInstructor(web); } showEvaluated = true; } return(show); }
/// <summary>Unlocks a file.</summary> /// <param name="file">The file to unlock.</param> /// <param name="currentUser">The current user id.</param> public static void UnlockFile(SPFile file, int currentUser) { try { if (file.LockedByUser != null && file.LockedByUser.ID != currentUser) { using (new AllowUnsafeUpdates(file.Web)) { file.ReleaseLock(file.LockId); } } } catch (SPException e) { SlkCulture culture = new SlkCulture(); string message = string.Format(CultureInfo.CurrentUICulture, culture.Resources.FailUnlockFile, file.Item.Url); SlkStore.GetStore(file.Web).LogException(e); throw new SafeToDisplayException(message); } }
/// <summary> /// accesses the document library at the path provided, /// loops through the learning packages /// located the library and reads the package Id from package manifest /// </summary> /// <param name="siteURL">web site url</param> /// <param name="documentLibraryName">document library name</param> /// <returns></returns> public Hashtable GetAllLearningResources(string siteURL, string documentLibraryName) { Hashtable resources = new Hashtable(); SharePointV3 sharepoint = new SharePointV3(); SPWeb documentLibWeb = sharepoint.OpenWeb(siteURL); SPDocumentLibrary docLibrary = sharepoint.GetDocumentLibrary(documentLibraryName, documentLibWeb); Microsoft.SharePointLearningKit.SlkStore store = SlkStore.GetStore(documentLibWeb); foreach (SPListItem item in docLibrary.Items) { //if this list item is a file if (item.File != null) { SharePointFileLocation fileLocation = new SharePointFileLocation(documentLibWeb, item.UniqueId, item.File.UIVersion); string location = fileLocation.ToString(); try { PackageInformation info = store.GetPackageInformation(location); XPathNavigator manifestNavigator = info.ManifestReader.CreateNavigator(); Guid packageIdentifier = ManifestParser.ParseIndexXml(manifestNavigator); if (packageIdentifier == Guid.Empty) { packageIdentifier = ManifestParser.ParseImsManifestXml(manifestNavigator); } if (packageIdentifier != Guid.Empty) { resources.Add(packageIdentifier.ToString(), location); } } catch { //not a valid learning package, do nothing } } } return(resources); }
public static void RunProgram(string classWebUrl) { Stack <IDisposable> disposer = new Stack <IDisposable>(); try { // "log in" to SLK as the current user, and set <memberships> to information about // the instructors and learners in the class Web site (i.e. the SPWeb with URL // <classWebUrl>) SPSite spSite = new SPSite(classWebUrl); disposer.Push(spSite); SPWeb spWeb = spSite.OpenWeb(); disposer.Push(spWeb); SlkStore slkStore = SlkStore.GetStore(spWeb); SlkMemberships memberships = slkStore.GetMemberships(spWeb, null, null); // make sure there's at least one instructor and one learner on the class Web; these // roles are defined by the "SLK Instructor" and "SLK Learner" permissions (as defined // in the SharePoint Learning Kit configuration page in SharePoint Central // Administration) if (memberships.Instructors.Count == 0) { throw new Exception("Class Web must have at least one instructor"); } if (memberships.Learners.Count == 0) { throw new Exception("Class Web must have at least one learner"); } // arbitrarily choose the first instructor in the class as the user who will create // the assignments SlkUser primaryInstructor = memberships.Instructors[0]; // set <classWeb> to the SPWeb of the SharePoint Web site that the new assignment will // be associated with; "log into" this Web site as the instructor retrieved above SPSite classSite = new SPSite(classWebUrl, primaryInstructor.SPUser.UserToken); disposer.Push(classSite); SPWeb classWeb = classSite.OpenWeb(); disposer.Push(classWeb); // set <slkStore> to the SharePoint Learning Kit store associated with the SPSite of // <classWeb> slkStore = SlkStore.GetStore(classWeb); // set <packageLocations> to the SharePointPackageStore-format location strings // corresponding to each element of <PackageUrls>; "log into" these Web sites as the // instructor retrieved above string[] packageLocations = new string[PackageUrls.Length]; for (int packageIndex = 0; packageIndex < packageLocations.Length; packageIndex++) { // set <packageWeb> to the SPWeb of the SharePoint Web site containing the package // or document to assign string packageUrl = PackageUrls[packageIndex]; SPSite packageSite = new SPSite(packageUrl, primaryInstructor.SPUser.UserToken); disposer.Push(packageSite); SPWeb packageWeb = packageSite.OpenWeb(); disposer.Push(packageWeb); // set <spFile> to the SPFile of the package or document to assign SPFile spFile = packageWeb.GetFile(packageUrl); // set the current element of <packageLocation> to the SharePointPackageStore // format location string that uniquely identifies the current version of the // <spFile> packageLocations[packageIndex] = new SharePointFileLocation( packageWeb, spFile.UniqueId, spFile.UIVersion).ToString(); } // create a random number generator s_random = new Random(RandomNumberSeed); // set <maxNumberOfLearners> to the number of learners in the class int maxNumberOfLearners = memberships.Learners.Count; // set <learners> to an array of learners of this class; for each assignment, we'll // shuffle this array and choose a subset to be learners on the assignment SlkUser[] learners = new SlkUser[memberships.Learners.Count]; memberships.Learners.CopyTo(learners, 0); // display table header Console.WriteLine("Assign. No. of Due Not"); Console.WriteLine("ID Learners Date Started Active Completed Final"); Console.WriteLine("----------------------------------------------------------"); // create assignments as specified by the constants at the top of this source file for (int assignmentIndex = 0; assignmentIndex < NumberOfAssignments; assignmentIndex++) { // set <fraction> to be proportional to <assignmentIndex>, between 0.0 and 1.0 double fraction = (double)assignmentIndex / NumberOfAssignments; // randomly choose an e-learning package or non-e-learning document to be assigned string packageLocation = packageLocations[s_random.Next(0, PackageUrls.Length)]; // get some information about the package/document; set <isNonELearning> to true if // if it's a non-e-learning document; NOTE: this is oversimplified code -- proper // production code should handle error conditions more carefully SPFile spFile = SlkUtilities.GetSPFileFromPackageLocation(packageLocation); bool isNonELearning; SharePointFileLocation spFileLocation; SharePointFileLocation.TryParse(packageLocation, out spFileLocation); using (SharePointPackageReader spPackageReader = new SharePointPackageReader(slkStore.SharePointCacheSettings, spFileLocation)) { isNonELearning = PackageValidator.Validate(spPackageReader).HasErrors; } // set <assignmentProperties> to the default assignment properties for the package // or document being assigned; some of these properties will be overridden below LearningStoreXml packageWarnings; int?organizationIndex = (isNonELearning ? (int?)null : 0); AssignmentProperties assignmentProperties = slkStore.GetNewAssignmentDefaultProperties( classWeb, packageLocation, organizationIndex, SlkRole.Instructor, out packageWarnings); // randomly generate a title for the assignment assignmentProperties.Title = CreateRandomTitle(); // set the due date of the assignment based on <fraction>, // <OldestAssignmentDaysAgo>, and <NewestAssignmentDaysFromNow> assignmentProperties.DueDate = DateTime.Now.AddDays( (OldestAssignmentDaysAgo + NewestAssignmentDaysFromNow) * fraction - OldestAssignmentDaysAgo); // set the start date of the assignment to be a day earlier than the earliest // due date assignmentProperties.StartDate = DateTime.Today.AddDays( -OldestAssignmentDaysAgo - 1); // randomly set Points Possible if ((assignmentProperties.PointsPossible == null) && (s_random.NextDouble() > FractionOfBlankPointsPossible)) { const int divideBy = 4; const int maxValue = 100; assignmentProperties.PointsPossible = (float)Math.Round( s_random.NextDouble() * divideBy * maxValue) / maxValue; } // make all instructors of this class (i.e. all SharePoint users that have the SLK // Instructor permission) be instructors on this assignment assignmentProperties.Instructors.Clear(); foreach (SlkUser slkUser in memberships.Instructors) { assignmentProperties.Instructors.Add(slkUser); } // shuffle <learners> for (int learnerIndex = 0; learnerIndex < learners.Length; learnerIndex++) { int otherLearnerIndex = s_random.Next(0, learners.Length); SlkUser temp = learners[learnerIndex]; learners[learnerIndex] = learners[otherLearnerIndex]; learners[otherLearnerIndex] = temp; } // randomly choose a number of learners for this assignment int numberOfLearners = s_random.Next( Math.Min(maxNumberOfLearners, MinLearnersPerAssignment), maxNumberOfLearners + 1); // copy the first <numberOfLearners> learners to <assignmentProperties> assignmentProperties.Learners.Clear(); for (int learnerIndex = 0; learnerIndex < numberOfLearners; learnerIndex++) { assignmentProperties.Learners.Add(learners[learnerIndex]); } // create the assignment AssignmentItemIdentifier assignmentId = slkStore.CreateAssignment(classWeb, packageLocation, organizationIndex, SlkRole.Instructor, assignmentProperties); // set <gradingPropertiesList> to information about the learner assignments of the // new assignment; in particular, we need the learner assignment IDs AssignmentProperties basicAssignmentProperties; ReadOnlyCollection <GradingProperties> gradingPropertiesList = slkStore.GetGradingProperties(assignmentId, out basicAssignmentProperties); // adjust the status of each learner assignment of this assignment according to // the rules specified in constants at the top of this source file int[] newStatusCount = new int[(int)LearnerAssignmentState.Final + 1]; for (int learnerIndex = 0; learnerIndex < gradingPropertiesList.Count; learnerIndex++) { // set <gradingProperties> to information about this learner assignment GradingProperties gradingProperties = gradingPropertiesList[learnerIndex]; // set <newStatus> to the new status of the assignment, applying the rules // specified in constants at the top of this source file if (fraction > 1 - FractionOfAssignmentsNotStarted) { gradingProperties.Status = LearnerAssignmentState.NotStarted; } else if (fraction < FractionOfAssignmentsAllFinal) { gradingProperties.Status = LearnerAssignmentState.Final; } else { gradingProperties.Status = (LearnerAssignmentState) s_random.Next(0, (int)LearnerAssignmentState.Final + 1); } // if we're transitioning learner assignment to Final state, optionally // assign a final points value if ((gradingProperties.Status == LearnerAssignmentState.Final) && (assignmentProperties.PointsPossible != null)) { if (s_random.NextDouble() < FractionOfOverriddenFinalPoints) { const int divideBy = 4; gradingProperties.FinalPoints = (float)Math.Round( s_random.NextDouble() * divideBy * assignmentProperties.PointsPossible.Value) / divideBy; } } // update statistics newStatusCount[(int)gradingProperties.Status]++; } // save changes to the assignment string warnings = slkStore.SetGradingProperties(assignmentId, gradingPropertiesList); Debug.Assert(warnings == null, warnings); // display feedback Console.WriteLine("{0,-8}{1,-10}{2,-10:d}{3,-8}{4,-7}{5,-10}{6,-6}", assignmentId.GetKey(), assignmentProperties.Learners.Count, assignmentProperties.DueDate, newStatusCount[0], newStatusCount[1], newStatusCount[2], newStatusCount[3]); } } finally { // dispose of objects used by this method while (disposer.Count > 0) { disposer.Pop().Dispose(); } } }
protected void addButton_Click(object sender, EventArgs e) { // user clicked "Add" button (after clicking "Add a site to this list") bool showAddSite = true; bool previousValue = SPSecurity.CatchAccessDeniedException; SPSecurity.CatchAccessDeniedException = false; try { string destinationUrl = txtNewSite.Text.Trim(); Uri destinationUri = new Uri(destinationUrl); using (SPSite site = new SPSite(destinationUri.AbsoluteUri)) { using (SPWeb destinationWeb = site.OpenWeb()) { // check if the site is a valid Slk site SlkStore destinationSlkStore; try { destinationSlkStore = SlkStore.GetStore(destinationWeb); } catch (SlkNotConfiguredException) { errorBanner.AddHtmlErrorText(ErrorType.Warning, PageCulture.Format(PageCulture.Resources.ActionsNotEnabled, Server.HtmlEncode(destinationUrl))); DisplayAddSite(); return; } // check if the user is an instructor on that site if (!destinationSlkStore.IsInstructor(destinationWeb)) { errorBanner.AddHtmlErrorText(ErrorType.Warning, PageCulture.Format(PageCulture.Resources.ActionsNotInstructor, Server.HtmlEncode(destinationUrl))); DisplayAddSite(); return; } // check if the site is already in the list ReadOnlyCollection <SlkUserWebListItem> userWebList = SlkStore.FetchUserWebList(); foreach (SlkUserWebListItem webListItem in userWebList) { if (destinationWeb.ID.Equals(webListItem.SPWebGuid)) { errorBanner.AddHtmlErrorText(ErrorType.Info, PageCulture.Format(PageCulture.Resources.ActionsAlreadyInList, Server.HtmlEncode(destinationWeb.Title))); break; } } // add the web to the list SlkStore.AddToUserWebList(destinationWeb); //local slkstore ShowAllSites = false; txtNewSite.Text = string.Empty; newSite = destinationWeb.ID; showAddSite = false; } } } catch (UriFormatException) { // the url is an invalid format errorBanner.AddHtmlErrorText(ErrorType.Warning, PageCulture.Format(PageCulture.Resources.ActionsInvalidSite, Server.HtmlEncode(txtNewSite.Text))); } catch (UnauthorizedAccessException) { // the user doesn't have permission to access this site, so show an error message errorBanner.AddHtmlErrorText(ErrorType.Warning, PageCulture.Format(PageCulture.Resources.ActionsInvalidSite, Server.HtmlEncode(txtNewSite.Text))); } catch (FileNotFoundException) { errorBanner.AddHtmlErrorText(ErrorType.Warning, PageCulture.Format(PageCulture.Resources.ActionsInvalidSite, Server.HtmlEncode(txtNewSite.Text))); } finally { SPSecurity.CatchAccessDeniedException = previousValue; } if (showAddSite) { DisplayAddSite(); } }
protected void BtnOk_Click(object sender, EventArgs e) { // the user clicked the OK button... // ensure the user is an administrator, then execute the remaining code within a // LearningStorePrivilegedScope (which grants full access to database views) if (!SPFarm.Local.CurrentUserIsAdministrator()) { throw new UnauthorizedAccessException( "Access is denied. Only adminstrators can access this page."); } using (new LearningStorePrivilegedScope()) { // if the user didn't select an "original instructor", do nothing if (OriginalInstructor.SelectedValue.Length == 0) { return; // real code would display an error message here } // if the user didn't enter any "new instructors", do nothing if (NewInstructors.Accounts.Count == 0) { return; // the <NewInstructors> control already displays a validation error } // set <originalInstructorId> to the SLK identifier of the selected "original // instructor" UserItemIdentifier originalInstructorId = new UserItemIdentifier( long.Parse(OriginalInstructor.SelectedValue, CultureInfo.InvariantCulture)); // execute the following code within the context of the current SharePoint Web site; // in fact, the operations below are actually done across the entire site *collection*, // but SlkStore.GetStore needs to be passed a Web site, so we use the current site using (SPWeb spWeb = SPControl.GetContextWeb(HttpContext.Current)) { // set <assignmentIds> to a list containing the IDs of the assignments for which // <originalInstructorId> is an instructor List <AssignmentItemIdentifier> assignmentIds = new List <AssignmentItemIdentifier>(); SlkStore slkStore = SlkStore.GetStore(spWeb); LearningStoreJob job = slkStore.LearningStore.CreateJob(); LearningStoreQuery query = slkStore.LearningStore.CreateQuery("AllAssignmentIds"); query.AddCondition("SPSiteGuid", LearningStoreConditionOperator.Equal, spWeb.Site.ID); query.AddCondition("InstructorId", LearningStoreConditionOperator.Equal, originalInstructorId); query.AddColumn("AssignmentId"); job.PerformQuery(query); DataRowCollection rows = job.Execute <DataTable>().Rows; OriginalInstructor.Items.Add(String.Empty); foreach (DataRow row in rows) { assignmentIds.Add(new AssignmentItemIdentifier( (LearningStoreItemIdentifier)row["AssignmentId"])); } // set <newInstructorIds> to a list of SLK numeric user IDs corresponding to the // users in the <NewInstructors> control List <UserItemIdentifier> newInstructorIds = new List <UserItemIdentifier>(); foreach (string loginName in NewInstructors.Accounts) { // set <spUser> to the SharePoint SPUser corresponding to <loginName> (which // was retrieved from the <NewInstructors> control>; quit with an error // message if that user isn't in "All People" for this site collection SPUser spUser; try { spUser = spWeb.AllUsers[loginName]; } catch (SPException) { NewInstructors.ErrorMessage = "User isn't in \"All People\": " + loginName; return; } // set <userKey> to the SLK "user key", which is a string used to identify a // user in the SLK database; SLK uses a user's security identifier (SID) if // they have one, or their login name if they don't (e.g. in the case of forms // authentication) string userKey = String.IsNullOrEmpty(spUser.Sid) ? spUser.LoginName : spUser.Sid; // set <userId> to the SLK UserItemIdentifier of the user <spUser> by // searching the SLK UserItem table; if the user isn't found in UserItem, // add them UserItemIdentifier userId; job = slkStore.LearningStore.CreateJob(); query = slkStore.LearningStore.CreateQuery("UserItem"); query.AddCondition("Key", LearningStoreConditionOperator.Equal, userKey); query.AddColumn("Id"); job.PerformQuery(query); rows = job.Execute <DataTable>().Rows; if (rows.Count != 0) { // found user in the SLK UserItem table userId = new UserItemIdentifier( (LearningStoreItemIdentifier)rows[0]["Id"]); } else { // user not found in SLK UserItem table -- add them; we use // LearningStoreJob.AddOrUpdateItem rather than LearningStoreJob.AddItem // to account for the rare case where the user may be added simultaneously // by another process job = slkStore.LearningStore.CreateJob(); Dictionary <string, object> findProperties = new Dictionary <string, object>(); findProperties["Key"] = userKey; Dictionary <string, object> setProperties = new Dictionary <string, object>(); setProperties["Name"] = spUser.Name; job.AddOrUpdateItem("UserItem", findProperties, setProperties, null, true); userId = new UserItemIdentifier( job.Execute <LearningStoreItemIdentifier>()); } // update <newInstructorIds> newInstructorIds.Add(userId); } // add each user in <newInstructorIds> as an instructor to each assignment in // <assignmentIds>; set <updatedAssignmentCount> to the number of assignments that // were updated (note that we don't update assignments for which the new // instructors are already instructors) Dictionary <UserItemIdentifier, bool> oldInstructors = new Dictionary <UserItemIdentifier, bool>(); int updatedAssignmentCount = 0; foreach (AssignmentItemIdentifier assignmentId in assignmentIds) { AssignmentProperties assignmentProperties = slkStore.GetAssignmentProperties(assignmentId, SlkRole.Instructor); oldInstructors.Clear(); foreach (SlkUser slkUser in assignmentProperties.Instructors) { oldInstructors[slkUser.UserId] = true; } int oldInstructorCount = oldInstructors.Count; foreach (UserItemIdentifier userId in newInstructorIds) { if (!oldInstructors.ContainsKey(userId)) { assignmentProperties.Instructors.Add(new SlkUser(userId)); } } if (assignmentProperties.Instructors.Count != oldInstructorCount) { slkStore.SetAssignmentProperties(assignmentId, assignmentProperties); updatedAssignmentCount++; } } // provide user feedback SuccessPanel.Visible = true; SuccessLabel.Text = String.Format("Found {0} assignment(s); updated {1} assignment(s).", assignmentIds.Count, updatedAssignmentCount); OriginalInstructorSection.Visible = false; NewInstructorsSection.Visible = false; ButtonSection.Visible = false; } } }
/// <summary> /// Creates a SharePoint Learning Kit assignment. /// </summary> /// /// <param name="packageUrl">The URL of the e-learning package or non-e-learning document /// to assign. This file must be located within a SharePoint document library.</param> /// /// <param name="organizationIndex">If <paramref name="packageUrl"/> refers to an e-learning /// package (e.g. a SCORM .zip file), <paramref name="organizationIndex"/> should be /// the zero-based index of the organization to assign. (Use 0 to assign the first /// organization.) If <paramref name="packageUrl"/> is a non-e-learning document, /// <paramref name="organizationIndex"/> should be <c>null</c>.</param> /// /// <param name="assignmentWebUrl">The URL of the SharePoint Web site that the new assignment /// will be associated with.</param> /// /// <param name="title"></param> /// /// <param name="instructorLoginName">The SharePoint login name of the instructor of the /// assignment. If the instructor account is a local machine account, the caller can /// specify @".\account-name". This user must have read access to the file specified by /// <paramref name="packageUrl"/>, and must have the "SLK Instructor" permission on the /// SharePoint Web site specified by <paramref name="assignmentWebUrl"/>.</param> /// /// <param name="learnerLoginNames">The SharePoint login names of the learners of the /// assignment. If a learner account is a local machine account, the caller can /// specify @".\account-name". Learners need not have access to the file specified by /// <paramref name="packageUrl"/>, but they must have the "SLK Learner" permission on the /// SharePoint Web site specified by <paramref name="assignmentWebUrl"/>.</param> /// /// <returns> /// The <c>AssignmentItemIdentifier</c> of the newly-created SharePoint Learning Kit /// assignment. /// </returns> /// static AssignmentItemIdentifier CreateAssignment(string packageUrl, int?organizationIndex, string assignmentWebUrl, string title, string instructorLoginName, params string[] learnerLoginNames) { Stack <IDisposable> disposer = new Stack <IDisposable>(); try { // set <instructorToken> to the SPUserToken of the instructor SPUser instructor; SPUserToken instructorToken; SPSite anonymousSite = new SPSite(packageUrl); disposer.Push(anonymousSite); if (instructorLoginName.StartsWith(@".\")) { instructorLoginName = anonymousSite.HostName + instructorLoginName.Substring(1); } disposer.Push(anonymousSite.RootWeb); instructor = anonymousSite.RootWeb.AllUsers[instructorLoginName]; instructorToken = instructor.UserToken; // set <packageWeb> to the SPWeb of the SharePoint Web site containing the package // or document to assign SPSite packageSite = new SPSite(packageUrl, instructorToken); disposer.Push(packageSite); SPWeb packageWeb = packageSite.OpenWeb(); disposer.Push(packageWeb); // set <spFile> to the SPFile of the package or document to assign SPFile spFile = packageWeb.GetFile(packageUrl); // set <packageLocation> to the SharePointPackageStore-format location string that // uniquely identifies the current version of the <spFile> string packageLocation = new SharePointFileLocation(packageWeb, spFile.UniqueId, spFile.UIVersion).ToString(); // set <assignmentWeb> to the SPWeb of the SharePoint Web site that the new assignment // will be associated with SPSite assignmentSite = new SPSite(assignmentWebUrl, instructorToken); disposer.Push(assignmentSite); SPWeb assignmentWeb = assignmentSite.OpenWeb(); disposer.Push(assignmentWeb); // set <slkStore> to the SharePoint Learning Kit store associated with the SPSite of // <assignmentWeb> SlkStore slkStore = SlkStore.GetStore(assignmentWeb); // set <assignmentProperties> to the default assignment properties for the package or // document being assigned; some of these properties will be overridden below LearningStoreXml packageWarnings; AssignmentProperties assignmentProperties = slkStore.GetNewAssignmentDefaultProperties( assignmentWeb, packageLocation, organizationIndex, SlkRole.Instructor, out packageWarnings); // set the assignment title assignmentProperties.Title = title; // set <allLearners> to a dictionary that maps SharePoint user login names to SlkUser // objects, for all users that have the "SLK Learner" permission on <assignmentWeb> SlkMemberships memberships = slkStore.GetMemberships(assignmentWeb, null, null); Dictionary <string, SlkUser> allLearners = new Dictionary <string, SlkUser>( StringComparer.OrdinalIgnoreCase); foreach (SlkUser learner in memberships.Learners) { allLearners.Add(learner.SPUser.LoginName, learner); } // set the learners of the assignment to be <learnerLoginNames> assignmentProperties.Learners.Clear(); foreach (string rawLearnerLoginName in learnerLoginNames) { string learnerLoginName; if (rawLearnerLoginName.StartsWith(@".\")) { learnerLoginName = anonymousSite.HostName + rawLearnerLoginName.Substring(1); } else { learnerLoginName = rawLearnerLoginName; } SlkUser slkUser; if (allLearners.TryGetValue(learnerLoginName, out slkUser)) { assignmentProperties.Learners.Add(slkUser); } else { throw new Exception(String.Format("Not a learner: {0}", learnerLoginName)); } } // create the assignment AssignmentItemIdentifier assignmentId = slkStore.CreateAssignment(assignmentWeb, packageLocation, organizationIndex, SlkRole.Instructor, assignmentProperties); // return the ID of the new assignment return(assignmentId); } finally { // dispose of objects used by this method while (disposer.Count > 0) { disposer.Pop().Dispose(); } } }
static void Main(string[] args) { Stack <IDisposable> disposer = new Stack <IDisposable>(); try { // "log in" to SharePoint and SLK as the current user SPSite spSite = new SPSite(ParentWebUrl); disposer.Push(spSite); s_parentWeb = spSite.OpenWeb(); disposer.Push(s_parentWeb); s_slkStore = SlkStore.GetStore(s_parentWeb); // set <instructorPermission> and <learnerPermission> to the name of the SharePoint // permission (or "role definition", to be more precise) that indicates that a user // is a SLK instructor or learner, respectively; examples: "SLK Instructor", // "SLK Learner" string instructorPermission = s_slkStore.Mapping.InstructorPermission; string learnerPermission = s_slkStore.Mapping.LearnerPermission; // initialize <s_computerChildren> and <s_guests>, used by CreateUser DirectoryEntry computer = new DirectoryEntry( String.Format("WinNT://{0},computer", Environment.MachineName)); disposer.Push(computer); s_computerChildren = computer.Children; s_guests = s_computerChildren.Find("Guests", "group"); disposer.Push(s_guests); // if <DeleteWebsOnly> is true, just delete the <NumberOfWebs> Web sites and exit #if DeleteWebsOnly for (int webNumber = 1; webNumber <= NumberOfWebs; webNumber++) { DeleteWeb(String.Format("SlkSampleWeb{0}", webNumber)); } return; #else // create SharePoint Web sites for simulated training classes, if they don't exist // yet; if they do exist, remove the instructors and learners on those sites for (int webNumber = 1; webNumber <= NumberOfWebs; webNumber++) { CreateWeb(String.Format("SlkSampleWeb{0}", webNumber), String.Format("SLK Sample Web Site {0}", webNumber)); } // create local machine accounts for simulated instructors (if they don't exist yet), // and add them as instructors on <WebsPerInstructor> randomly-chosen Web sites; also, // ensure each instructor has read access to each file listed in // <SimulateClassProgram.PackageUrls> (in ..\SimulateClass\SimulateClass.cs) for (int instructorNumber = 1; instructorNumber <= NumberOfInstructors; instructorNumber++) { // create the user account string loginName = String.Format(InstructorLoginNamePrefix + "{0}", instructorNumber); string fullName = String.Format("SLK Sample Instructor {0}", instructorNumber); CreateUser(loginName, fullName); // add the user as instructors on <WebsPerInstructor> randomly-chosen Web sites foreach (int webNumber in ShuffledNumbers(1, NumberOfWebs, WebsPerInstructor)) { string relativeUrl = String.Format("SlkSampleWeb{0}", webNumber); AddUserToWeb(loginName, relativeUrl, instructorPermission); } // ensure the instructor has read access to each file listed in // <SimulateClassProgram.PackageUrls> (in ..\SimulateClass\SimulateClass.cs) for (int packageIndex = 0; packageIndex < SimulateClassProgram.PackageUrls.Length; packageIndex++) { string packageUrl = SimulateClassProgram.PackageUrls[packageIndex]; GiveUserReadAccessToFile(loginName, packageUrl); } } // create local machine accounts for simulated learners (if they don't exist yet), // and add them as learners on <WebsPerLearner> randomly-chosen Web sites for (int learnerNumber = 1; learnerNumber <= NumberOfLearners; learnerNumber++) { // create the user account string loginName = String.Format(LearnerLoginNamePrefix + "{0}", learnerNumber); string fullName = String.Format("SLK Sample Learner {0}", learnerNumber); CreateUser(loginName, fullName); // add the user as learners on <WebsPerLearner> randomly-chosen Web sites foreach (int webNumber in ShuffledNumbers(1, NumberOfWebs, WebsPerLearner)) { string relativeUrl = String.Format("SlkSampleWeb{0}", webNumber); AddUserToWeb(loginName, relativeUrl, learnerPermission); } } // ensure all our Web sites have at least one instructor and one learner -- if any // don't, randomly select an instructor and/or learner as needed IEnumerator <int> shuffledInstructorNumbers = ShuffledNumbers(1, NumberOfInstructors, int.MaxValue).GetEnumerator(); IEnumerator <int> shuffledLearnerNumbers = ShuffledNumbers(1, NumberOfLearners, int.MaxValue).GetEnumerator(); for (int webNumber = 1; webNumber <= NumberOfWebs; webNumber++) { string relativeUrl = String.Format("SlkSampleWeb{0}", webNumber); if (!DoesWebHaveAnyoneWithPermission(relativeUrl, instructorPermission)) { shuffledInstructorNumbers.MoveNext(); string loginName = String.Format(InstructorLoginNamePrefix + "{0}", shuffledInstructorNumbers.Current); AddUserToWeb(loginName, relativeUrl, instructorPermission); } if (!DoesWebHaveAnyoneWithPermission(relativeUrl, learnerPermission)) { shuffledLearnerNumbers.MoveNext(); string loginName = String.Format(LearnerLoginNamePrefix + "{0}", shuffledLearnerNumbers.Current); AddUserToWeb(loginName, relativeUrl, learnerPermission); } } // create assignments in each of the Web sites we created for (int webNumber = 1; webNumber <= NumberOfWebs; webNumber++) { string relativeUrl = String.Format("SlkSampleWeb{0}", webNumber); Console.WriteLine("Creating assignments in Web site {0} of {1}: {2}", webNumber, NumberOfWebs, relativeUrl); using (SPWeb spWeb = s_parentWeb.Webs[relativeUrl]) { SimulateClassProgram.RunProgram(spWeb.Url); } } #endif } finally { // dispose of objects used by this method while (disposer.Count > 0) { disposer.Pop().Dispose(); } } }
/// <summary>Removes observer permissions.</summary> public void RemoveObserverPermission() { bool isReader = false, isObserver = false; foreach (SPRoleAssignment learnerSubfolderRoleAssignment in assignmentFolder.RoleAssignments) { for (int i = 0; i < learnerSubfolderRoleAssignment.RoleDefinitionBindings.Count; i++) { if (learnerSubfolderRoleAssignment.RoleDefinitionBindings[i].Type == SPRoleType.Reader) { isReader = true; foreach (SPRoleAssignment webRoleAssignment in web.RoleAssignments) { for (int j = 0; j < webRoleAssignment.RoleDefinitionBindings.Count; j++) { if (webRoleAssignment.Member.Name == learnerSubfolderRoleAssignment.Member.Name && webRoleAssignment.RoleDefinitionBindings[j].Name == SlkStore.GetStore(web).Mapping.ObserverPermission) { isObserver = true; break; } } if (isObserver) { break; } } } if (isReader && isObserver) { learnerSubfolderRoleAssignment.RoleDefinitionBindings.RemoveAll(); using (new AllowUnsafeUpdates(web)) { learnerSubfolderRoleAssignment.Update(); } isReader = false; isObserver = false; break; } } } }
static void Main(string[] args) { // load the XML spreadsheet into memory XPathNavigator rootNode; string path; if (args.Length == 1) { path = args[0]; } else { path = Path.Combine(Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location), "UserWebList.xls"); } using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { rootNode = new XPathDocument(stream).CreateNavigator(); } // create a namespace manager for accessing the XML spreadsheet string ssNamespace = "urn:schemas-microsoft-com:office:spreadsheet"; XmlNamespaceManager nsm = new XmlNamespaceManager(rootNode.NameTable); nsm.AddNamespace("ss", ssNamespace); // set <worksheetNode> to the "User Web Lists" worksheet XPathNavigator worksheetNode = rootNode.SelectSingleNode( "ss:Workbook/ss:Worksheet[@ss:Name = 'User Web Lists']", nsm); // loop once for each row in the worksheet const int ExpectedCellCount = 2; List <string> cells = new List <string>(ExpectedCellCount); foreach (XPathNavigator rowNode in worksheetNode.Select("ss:Table/ss:Row", nsm)) { // set <cells> to the cells of this row cells.Clear(); foreach (XPathNavigator cellNode in rowNode.Select("ss:Cell", nsm)) { if (cellNode.MoveToAttribute("Index", ssNamespace)) { while (cells.Count < cellNode.ValueAsInt - 1) { cells.Add(String.Empty); } cellNode.MoveToParent(); } XPathNavigator dataNode = cellNode.SelectSingleNode("ss:Data", nsm); cells.Add(dataNode.Value.Trim()); } // ensure there are at least <ExpectedCellCount> cells while (cells.Count < ExpectedCellCount) { cells.Add(String.Empty); } // get the login name (i.e. "<domain>\<login-name>", or ".\<login-name>" for // local machine accounts), and the URL of the SharePoint Web site, listed in // this row of the worksheet; skip this row if either is blank string loginName = cells[0]; string webUrl = cells[1]; if ((loginName.Length == 0) || (webUrl.Length == 0)) { continue; } // "log in" to SharePoint as the user running this program, and set <spUser> to the // SPUser of the user specified by this worksheet row SPUser spUser; using (SPSite anonymousSite = new SPSite(webUrl)) { if (loginName.StartsWith(@".\")) { loginName = anonymousSite.HostName + loginName.Substring(1); } using (SPWeb rootWeb = anonymousSite.RootWeb) { spUser = rootWeb.AllUsers[loginName]; } } // "log in" to SharePoint as the user <spUser>, then add <webUrl> to the SLK user Web // list of that user using (SPSite spSite = new SPSite(webUrl, spUser.UserToken)) { using (SPWeb spWeb = spSite.OpenWeb()) { Console.WriteLine("Adding {0} to the user Web list of {1}", spWeb.Url, spUser.Name); SlkStore slkStore = SlkStore.GetStore(spWeb); slkStore.AddToUserWebList(spWeb); } } } }
/// <summary> /// For the class requested gets the assignments data from Class Server 4 database /// and transfers assignments and grading points and teacher comments using SLK API /// </summary> /// <param name="classData">class information from Class Server 4 classes config file</param> /// <param name="logText">returns log of operations performed</param> /// <param name="learningPackages">information about learning packages available on SLK school site</param> private void MoveAssignments(CS4Class classData, ref string logText, Hashtable learningPackages) { SharePointV3 assignmentSite = new SharePointV3(); string assignmentSiteUrl = assignmentSite.BuildSubSiteUrl(SiteBuilder.Default.SLKSchoolWeb, classData.ClassWeb); //for the getmemberships operation to succeed the current user has to be an SLK instructor on the web site //looping through all the class users to see if any of them are instructors //and trying to open the class web with and instructor's token SPWeb assignmentWeb = null; SPWeb assignmentWebUnderCurrentUser = assignmentSite.OpenWeb(assignmentSiteUrl); SPRoleDefinition instructorsRole = assignmentWebUnderCurrentUser.RoleDefinitions[SiteBuilder.Default.SLKInstructorSharePointRole]; bool foundInstructor = false; foreach (CS4User user in classData.Users) { if ((user.IsTeacher) && (user.Transfer)) { try { SPUser spUser = assignmentWebUnderCurrentUser.SiteUsers[user.UserLoginWithDomain]; SPUserToken token = spUser.UserToken; SPSite site = new SPSite(assignmentSiteUrl, token); assignmentWeb = site.OpenWeb(); if (assignmentWeb.AllRolesForCurrentUser.Contains(instructorsRole)) { foundInstructor = true; break; } } catch { //doing nothing, will try the next instructor } } } if (!foundInstructor) { logText += TextResources.AssignmentsTransferErrorNoClassInstructors + Environment.NewLine; return; } //open the Class SLK store //note we are using SPWeb opened with an instructor's SPUserToken Microsoft.SharePointLearningKit.SlkStore slkStore = SlkStore.GetStore(assignmentWeb); //get all learners and instructors for the class SlkMemberships memberships = slkStore.GetMemberships(assignmentWeb, null, null); Dictionary <string, SlkUser> allLearners = new Dictionary <string, SlkUser>( StringComparer.OrdinalIgnoreCase); foreach (SlkUser learner in memberships.Learners) { allLearners.Add(learner.SPUser.LoginName, learner); } Dictionary <string, SlkUser> allInstructors = new Dictionary <string, SlkUser>( StringComparer.OrdinalIgnoreCase); foreach (SlkUser instructor in memberships.Instructors) { allInstructors.Add(instructor.SPUser.LoginName, instructor); } //instructors list will always be the same for all assignments //because there is no link between assignments and teachers in CS4 SlkUserCollection classInstructors = new SlkUserCollection(); foreach (CS4User user in classData.Users) { if ((user.IsTeacher) && (user.Transfer)) { SlkUser slkUser; if (allInstructors.TryGetValue(user.UserLoginWithDomain, out slkUser)) { classInstructors.Add(slkUser); } else { //instructor not found on slk site, log logText += String.Format(TextResources.InstructorNotRegisteredWithSLKSite, user.UserLoginWithDomain, assignmentSiteUrl) + Environment.NewLine; } } } //get assignments for this class from the CS4 data base CS4Database database = new CS4Database(SiteBuilder.Default.ClassServerDBConnectionString); DataTable assignmentItems; DataTable userAssignments; int numAssignments = database.GetAssignments(classData.ClassId, out assignmentItems, out userAssignments); //loop through assignments list for (int assignmentIndex = 0; assignmentIndex < numAssignments; assignmentIndex++) { try { string packageIdent = (assignmentItems.Rows[assignmentIndex]["PackageIdentifier"] != System.DBNull.Value ? assignmentItems.Rows[assignmentIndex]["PackageIdentifier"].ToString() : String.Empty); int assignmentId = (assignmentItems.Rows[assignmentIndex]["AssignmentID"] != System.DBNull.Value ? System.Convert.ToInt32(assignmentItems.Rows[assignmentIndex]["AssignmentID"]) : 0); logText += String.Format(TextResources.TransferringAssignment, assignmentId.ToString()) + Environment.NewLine; //get assignment's package identifier string packageLocation = GetPackageLocation(packageIdent, learningPackages); if (packageLocation.Length == 0) { if (packageIdent.Length == 0) { //log: not importing assignment as the package cannot be identified logText += String.Format(TextResources.CantTransferAssignmentUnknownLearningResource, assignmentId) + Environment.NewLine; } else { //log - assignment cannot be imported as the package is not imported into slk logText += String.Format(TextResources.CantTransferAssignmentNoLearningResource, assignmentId) + Environment.NewLine; } //move on to the next assignment break; } //set assignment properties AssignmentProperties properties = ReadAssignmentPropertiesFromDataRow(assignmentItems.Rows[assignmentIndex]); Hashtable gradingPoints = new Hashtable(); Hashtable gradingComments = new Hashtable(); //set instructors list foreach (SlkUser classInstructor in classInstructors) { properties.Instructors.Add(classInstructor); } //set learners list for (int userAssignmentIndex = 0; userAssignmentIndex < userAssignments.Rows.Count; userAssignmentIndex++) { DataRow assignmentRow = userAssignments.Rows[userAssignmentIndex]; int userAssignmentTableID = (assignmentRow["AssignmentID"] == System.DBNull.Value) ? 0 : System.Convert.ToInt32(assignmentRow["AssignmentID"]); int userId = (assignmentRow["StudentID"] == System.DBNull.Value) ? 0 : System.Convert.ToInt32(assignmentRow["StudentID"]); bool isAssignmentGraded = (assignmentRow["HasTeacherGraded"].ToString().ToLower() == "true" ? true : false); float points = (assignmentRow["Points"] == System.DBNull.Value) ? 0 : System.Convert.ToSingle(assignmentRow["Points"]); string instructorComments = assignmentRow["TeacherComments"].ToString(); //to minimize sql queries the UserAssignments table contains all assignments for the class //so we need to check if this row is for the assignment currently being processed if (assignmentId == userAssignmentTableID) { //find this user in list of users from classes.xml CS4User user = classData.Users.GetByUserId(userId); if (user != null) { //see if this user is for transfer in classes.xml if (user.Transfer) { //see if this user is a learner member on SLK site SlkUser slkUser; if (allLearners.TryGetValue(user.UserLoginWithDomain, out slkUser)) { properties.Learners.Add(slkUser); //save grading info for this learner to be used later if (isAssignmentGraded) { gradingPoints.Add(slkUser.UserId, points); gradingComments.Add(slkUser.UserId, instructorComments); } } else { //user not found on slk site, log logText += String.Format(TextResources.UserNotRegisteredWithSLKSite, user.UserLoginWithDomain, assignmentSiteUrl, assignmentId) + Environment.NewLine; } } else { //user assignments will not be transferred as user is marked "not for transfer" logText += String.Format(TextResources.UserNotForTransfer, user.UserLoginWithDomain) + Environment.NewLine; } } else { //user is not found in xml file, log logText += String.Format(TextResources.UserNotFoundInXMLFile, userId, assignmentSiteUrl, SiteBuilder.Default.ClassStructureXML, assignmentId) + Environment.NewLine; } } //create the assignment AssignmentItemIdentifier assignmentIdSLK = slkStore.CreateAssignment(assignmentWeb, packageLocation, 0, SlkRole.Instructor, properties); //transfer the grading results for the assignments AssignmentProperties basicAssignmentProperties; ReadOnlyCollection <GradingProperties> gradingPropertiesList = slkStore.GetGradingProperties(assignmentIdSLK, out basicAssignmentProperties); for (int learnerIndex = 0; learnerIndex < gradingPropertiesList.Count; learnerIndex++) { // set <gradingProperties> to information about this learner assignment GradingProperties gradingProperties = gradingPropertiesList[learnerIndex]; if (gradingPoints.ContainsKey(gradingProperties.LearnerId)) { //assignment has been graded, transfer grade and comment to SLK gradingProperties.Status = LearnerAssignmentState.Final; gradingProperties.FinalPoints = (float)gradingPoints[gradingProperties.LearnerId]; gradingProperties.InstructorComments = gradingComments[gradingProperties.LearnerId].ToString(); } } //this call will not save the grade, but it will set the correct state and //put the teacher's comment. logText += slkStore.SetGradingProperties(assignmentIdSLK, gradingPropertiesList) + Environment.NewLine; //calling the second time to save grades for (int learnerIndex = 0; learnerIndex < gradingPropertiesList.Count; learnerIndex++) { gradingPropertiesList[learnerIndex].Status = null; } logText += slkStore.SetGradingProperties(assignmentIdSLK, gradingPropertiesList) + Environment.NewLine; logText += String.Format(TextResources.TransferredAssignment, assignmentId.ToString(), assignmentIdSLK.GetKey().ToString()) + Environment.NewLine; } } catch (System.Exception ex) { //exception when transferring an assignment logText += TextResources.AnError + ex.Message + Environment.NewLine; } } }