/// <summary> /// Calls CS4Database.ExportClassesStructure to export Class Server 4 classes, /// groups and users into XML file. File name is taken from settings file. /// </summary> private void llExportClassesXML_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { if (!AllAppSettingsSet()) { lblExportClassesStatus.Text = TextResources.AppSettingsNotSet; return; } lblExportClassesStatus.Text = String.Empty; CS4Database database = new CS4Database(SiteBuilder.Default.ClassServerDBConnectionString); try { bool result = database.ExportClassesStructure(System.IO.Directory.GetCurrentDirectory() + "\\" + SiteBuilder.Default.ClassStructureXML); if (result) { lblExportClassesStatus.Text = String.Format(TextResources.SuccessExportingData, SiteBuilder.Default.ClassStructureXML); } else { lblExportClassesStatus.Text = String.Format(TextResources.FailedToExportData, SiteBuilder.Default.ClassStructureXML); } } catch (System.Exception ex) { lblExportClassesStatus.Text = TextResources.DataExportError + ex.Message; } }
/// <summary> /// Contains logic for testing of the connection string /// </summary> /// <param name="dbConnection">connection string</param> /// <param name="status">returns status of the connection attempt</param> /// <returns>true if the connection successful</returns> private static bool TestDBConnection(string dbConnection, out string status) { bool result = false; CS4Database database = new CS4Database(dbConnection); try { database.TestConnection(); result = true; status = AppResources.ConnectionSuccessful; } catch (SystemException ex) { status = AppResources.ConnectionFailed + ex.Message; } return(result); }
/// <summary> /// tries to establish connection with the CS4 database and displays the status /// </summary> private void btnTestDBConnection_Click(object sender, EventArgs e) { this.btnTestDBConnection.Enabled = false; this.lblConnectionStatus.Text = String.Empty; CS4Database database = new CS4Database(this.BuildConnectionString()); try { database.TestConnection(); this.lblConnectionStatus.Text = TextResources.ConnectionSuccessful; } catch (SystemException ex) { this.lblConnectionStatus.Text = ex.Message; } this.btnTestDBConnection.Enabled = true; }
/// <summary> /// Gets the list of users from Class Server database and checks /// if users belong to Active Directory. This is necessary as /// SLK sites base their permissions and membership on AD authentication /// </summary> /// <param name="ActiveDirectoryPath">LDAP path of the Active Directory</param> /// <param name="LogFileName">file name of the log file (will be created in the working directory)</param> /// <param name="worker">BackgroundWorker object, used to report progress</param> /// <param name="e">not used</param> /// <returns>"Completed" if successful, or exception message if there was an error.</returns> public string VerifyAgainstActiveDirectory(string activeDirectoryPath, string logFileName, BackgroundWorker worker, DoWorkEventArgs e) { try { CS4Database database = new CS4Database(SiteBuilder.Default.ClassServerDBConnectionString); DataTable usersTable = null; m_totalUsers = database.GetUsersList(ref usersTable); LogFile log = new LogFile(logFileName); log.WriteToLogFile("Verifying Class Server users against Active Directory at " + activeDirectoryPath); ADHelper helper = new ADHelper(); helper.DoADBinding(activeDirectoryPath); for (int userIndex = 0; userIndex < m_totalUsers; userIndex++) { CS4User user = new CS4User(usersTable.Rows[userIndex][0].ToString(), usersTable.Rows[userIndex][1].ToString(), System.String.Empty, System.String.Empty); if (!helper.UserExistsInActiveDirectory(user.UserDomain, user.UserLogin)) { log.WriteToLogFile(user.UserLoginWithDomain + " NOT FOUND"); m_usersNotInAD++; } else { log.WriteToLogFile(user.UserLoginWithDomain + " found"); } m_usersProcessed++; worker.ReportProgress(0, "Verified " + m_usersProcessed.ToString() + " of " + m_totalUsers.ToString() + " users."); } log.FinishLogging(); string sReport = "Completed."; return(sReport); } catch (System.Exception ex) { //catching any exception here as this will be executed in a separate thread return(ex.Message); } }
/// <summary> /// Reads config file to get db connection string and a path to process. /// Reads manifest file (index.xml, if index.xml not found then imsmanifest.xml) /// for every learning package in the folder and retrieves the package identifier. /// If the processing path is a Class Server 4 activity folder path, then /// puts the AssignmentID and respective package identifier into AssignmentPackageTransfer table /// for every assigment found. /// </summary> /// <param name="args">ignores parameters</param> static void Main(string[] args) { //starting log MigrationHelper.LogFile log = new LogFile("app.log"); log.WriteToLogFile(AppResources.StartedProcessing + System.Environment.NewLine); log.WriteToLogFile(AppResources.GettingDataFromConfig + System.Environment.NewLine); //get processing folder from config string activityPath = PackageAnalyser.App.Default.Path; bool processingAssignments = App.Default.IsSchoolActivityPath; log.WriteToLogFile("SchoolActivityPath = " + activityPath + System.Environment.NewLine); //check if path exists bool activityPathExists = System.IO.Directory.Exists(activityPath); if (activityPathExists) { log.WriteToLogFile(AppResources.ActivityPathValid + System.Environment.NewLine); } else { log.WriteToLogFile(AppResources.ActivityPathInvalid + System.Environment.NewLine); } bool connectionOK = false; string dbConnection = String.Empty; if (processingAssignments) { //get database connection from config dbConnection = PackageAnalyser.App.Default.SchoolDBConnectionString; log.WriteToLogFile("SchoolDBConnectionString = " + dbConnection + System.Environment.NewLine); //test connection string connectionStatus = ""; connectionOK = TestDBConnection(dbConnection, out connectionStatus); log.WriteToLogFile(AppResources.TestingDBConnection + connectionStatus + System.Environment.NewLine); } if ((processingAssignments && connectionOK && activityPathExists) || ((!processingAssignments) && (activityPathExists))) { //if parameters are valid, start processing List <learningResource> packagesInfo = new List <learningResource>(); try { GetAssignmentPackagesInfo(activityPath, ref packagesInfo); } catch (System.Exception ex) { log.WriteToLogFile(AppResources.ErrorGatheringAssignments + ex.Message + System.Environment.NewLine); } if (packagesInfo.Count == 0) { //nothing found //no learning packages found, log log.WriteToLogFile(AppResources.NoPackagesFound + Environment.NewLine); } else { //log the list of packages log.WriteToLogFile(AppResources.FoundAssignments + System.Environment.NewLine); for (int packageInfoIndex = 0; packageInfoIndex < packagesInfo.Count; packageInfoIndex++) { string foundPackagesLog = String.Format(AppResources.Path, packagesInfo[packageInfoIndex].path); if (packagesInfo[packageInfoIndex].assignmentId > 0) { foundPackagesLog += String.Format(AppResources.AssignmentId, packagesInfo[packageInfoIndex].assignmentId); } if (packagesInfo[packageInfoIndex].packageIdentifier != Guid.Empty) { foundPackagesLog += String.Format(AppResources.PackageId, packagesInfo[packageInfoIndex].packageIdentifier); } if (packagesInfo[packageInfoIndex].licensed) { foundPackagesLog += String.Format(AppResources.RequiresLicense); } if (packagesInfo[packageInfoIndex].processingError != null) { foundPackagesLog += packagesInfo[packageInfoIndex].processingError; } log.WriteToLogFile(foundPackagesLog + Environment.NewLine); } if (processingAssignments) { //put the list of assignments into database DataTable assignments = new DataTable(); assignments.Columns.Add(new DataColumn("AssignmentID", System.Type.GetType("System.Int32"))); assignments.Columns.Add(new DataColumn("PackageIdentifier", System.Type.GetType("System.Guid"))); for (int packageInfoIndex = 0; packageInfoIndex < packagesInfo.Count; packageInfoIndex++) { if ((packagesInfo[packageInfoIndex].assignmentId > 0) && (packagesInfo[packageInfoIndex].packageIdentifier != Guid.Empty)) { DataRow assignment = assignments.NewRow(); assignment[0] = packagesInfo[packageInfoIndex].assignmentId; assignment[1] = packagesInfo[packageInfoIndex].packageIdentifier; assignments.Rows.Add(assignment); } } CS4Database database = new CS4Database(dbConnection); try { database.WriteAssignmentsTransferTable(assignments); log.WriteToLogFile(AppResources.SuccessWritingToDB + System.Environment.NewLine); } catch (System.Exception ex) { log.WriteToLogFile(AppResources.AnErrorWhileSaving + ex.Message + Environment.NewLine); } } } } else { //one or more parameters are not valid log.WriteToLogFile(AppResources.ParametersInvalid + System.Environment.NewLine); } log.WriteToLogFile(AppResources.FinishedProcessing + System.Environment.NewLine); log.FinishLogging(); }
/// <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; } } }