Compare commits
	
		
			92 Commits 
		
	
	
		
			Bug557-Ayo
			...
			Hui-Organi
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 246565c8e9 | |
|  | b37955daa8 | |
|  | 4e0d97afb4 | |
|  | b0a44c001d | |
|  | f6833e7398 | |
|  | 2ce0aa95b2 | |
|  | 43e9cfeffe | |
|  | b264ce4299 | |
|  | a86c810a2d | |
|  | 8876825ef9 | |
|  | 21918cf883 | |
|  | 62966c82fa | |
|  | bc77fa1aa4 | |
|  | 9a4a8d2818 | |
|  | 07ba57eebb | |
|  | 1f602e3db2 | |
|  | 5ce55c3f1e | |
|  | 9d170fea87 | |
|  | 0f42a68461 | |
|  | e8bbce386a | |
|  | 545915b8be | |
|  | aa82e9b5db | |
|  | 0a12b69d2c | |
|  | 54cb51d3a6 | |
|  | 5cef5875f6 | |
|  | 5e1cfcbbcc | |
|  | 44aa38be76 | |
|  | debd85e74d | |
|  | 39c14f7425 | |
|  | 1ed7e2e394 | |
|  | a34ab61916 | |
|  | 33f997412b | |
|  | b1dbd94b00 | |
|  | 7388868678 | |
|  | aa85b742f5 | |
|  | e1c95395ef | |
|  | 65920bc0ac | |
|  | e66af1f419 | |
|  | 162b347119 | |
|  | 5ebb0ccd6c | |
|  | 5bbd812189 | |
|  | 162de63b4d | |
|  | 88d20ed476 | |
|  | 5d0d0d91f7 | |
|  | fea32072c3 | |
|  | 5639ce4c6b | |
|  | 8f3919d3bb | |
|  | da18cb617d | |
|  | 23e192568f | |
|  | dc3ff79b5d | |
|  | 690db8d5fe | |
|  | 1a01b4facd | |
|  | 4024a36021 | |
|  | f600f2bc24 | |
|  | 8e200b647f | |
|  | dcd0e522c7 | |
|  | 4da1c5a641 | |
|  | f2aa60c994 | |
|  | 5b72461eda | |
|  | ff092f2a8e | |
|  | 622ed4350f | |
|  | 64ffc3af1c | |
|  | fde44f7600 | |
|  | 44a7d4533e | |
|  | 70d2bb4504 | |
|  | 9f03d380cd | |
|  | c1f95ce017 | |
|  | 9d1670577e | |
|  | a87c741c13 | |
|  | adc9daef98 | |
|  | 2dcbfab501 | |
|  | cd7ece13bc | |
|  | 20cc8a332c | |
|  | 61212c8e94 | |
|  | da9e29c5b6 | |
|  | f3f7e0ccfd | |
|  | f29f2d5212 | |
|  | e6487c5d1a | |
|  | 3ee85d0bda | |
|  | 2255a1a9eb | |
|  | 2b0574fd6d | |
|  | 0a7d4a5afa | |
|  | 12e9038dec | |
|  | 71ce1e1345 | |
|  | 7f26ff5fc9 | |
|  | fec5499861 | |
|  | f3ef8d8e5c | |
|  | ef87c1248f | |
|  | cf30889bdd | |
|  | ff407da550 | |
|  | 7b68043060 | |
|  | fc8ad0c0a9 | 
|  | @ -1,2 +1,5 @@ | |||
| .vscode | ||||
| .DS_Store | ||||
| venv/ | ||||
| __pycache__/ | ||||
| *.pyc | ||||
|  |  | |||
							
								
								
									
										80
									
								
								Admin.php
								
								
								
								
							
							
						
						
									
										80
									
								
								Admin.php
								
								
								
								
							|  | @ -9,7 +9,7 @@ include 'Header.php'; | |||
| 
 | ||||
| 
 | ||||
| <?php | ||||
| // Only Lecturer or Admin could access this page
 | ||||
|  //Only Lecturer or Admin could access this page
 | ||||
| if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") { | ||||
|     die("Sorry.  Nothing to see here."); | ||||
| } | ||||
|  | @ -30,11 +30,11 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") { | |||
| 	    <ul class="nav nav-tabs" id="myTab"> | ||||
| 
 | ||||
| 		<li class="nav-item"> | ||||
| 		    <a class="nav-link active" href="#tab-student-accounts" id="batch_tab">Create student accounts</a> | ||||
| 		    <a class="nav-link active" href="#tab-student-accounts" id="batch_tab">Enter student numbers</a> | ||||
| 		</li> | ||||
| 
 | ||||
| 		<li class="nav-item"> | ||||
| 		    <a class="nav-link" href="#tab-ins-accounts">Create instructor account</a> | ||||
| 		    <a class="nav-link" href="#tab-ins-accounts" id="tab_ins_accounts">Create instructor account</a> | ||||
| 		</li> | ||||
| 
 | ||||
| 		<li class="nav-item"> | ||||
|  | @ -65,33 +65,32 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") { | |||
| 		    } | ||||
| 
 | ||||
| 		    ?>
 | ||||
| 		    <form method="post" action="Script.php" id="create_account_form"> | ||||
| 			<input type="hidden" name="form_createlecturrer" value="true" required="" /> | ||||
| 		    <form method="post" action="Script.php"  id="create_account_form"> | ||||
| 			<input type="hidden" name="form_createlecturer" value="true" required="" /> | ||||
| 			Full name | ||||
| 			<input type="text" name="fullname" placeholder="Full Name" class="form-control" required=""> <br> | ||||
| 			Email | ||||
| 			<input type="text" name="email" placeholder="Email / Student Number" class="form-control" required=""> <br> | ||||
| 			Passport No. (used as the initial password) | ||||
| 			<input type="text" class="form-control" name="passport" placeholder="Passport No" required=""> <br> | ||||
| 			<input type="text" name="email" placeholder="Email / Student Number" class="form-control" > <br> | ||||
|                         Initial password (Enter a strong password or leave it empty to let LRR generate one) | ||||
|                         <input type="password" class="form-control" name="password"  minlength="8" placeholder="Initial password" > <br> | ||||
| 			User type: | ||||
| 			<?php | ||||
| 			if ($_SESSION['user_type'] == "Lecturer") { | ||||
| 			    echo ' <input type="radio" name="type" value="TA" required="" id="role_TA"> TA (Teaching Assistant) '; | ||||
| 			} else if ($_SESSION['user_type'] == "Admin"){ | ||||
| 			    echo " <input type='radio' name='type' value='Lecturer' required='' id='role_lecturer'> Lecturer "; | ||||
| 			} | ||||
| 			?>
 | ||||
|                 <?php | ||||
| 
 | ||||
|                 if ($_SESSION['user_type'] == "Lecturer") { | ||||
|                     echo ' <input type="radio" name="type" value="TA" required="" id="role_TA"> TA (Teaching Assistant) '; | ||||
|                 } else if ($_SESSION['user_type'] == "Admin"){ | ||||
|                     echo " <input type='radio' name='type' value='Lecturer' required='' id='role_lecturer'> Lecturer "; | ||||
|                 } | ||||
| 
 | ||||
|                 ?>
 | ||||
| 
 | ||||
| 			<br><br> | ||||
| 			<button type="submit" class="btn btn-primary" id="create_btn">Create</button> | ||||
|                 <button type="submit" class="btn btn-primary" name="create_btn">Create</button> | ||||
| 
 | ||||
| 			<?php | ||||
| 			error_reporting(E_ALL); | ||||
| 			if (isset($_SESSION['info_Admin_Users'])) { | ||||
| 			    echo  '<hr><div class="alert alert-info" role="alert">' . $_SESSION['info_Admin_Users'] . '</div>'; | ||||
| 			    $_SESSION['info_Admin_Users'] = null; | ||||
| 			} | ||||
| 			if (isset($_SESSION['info_Admin_Users'])) { | ||||
| 			    echo  '<hr><div class="alert alert-info" role="alert">' . $_SESSION['info_Admin_Users'] . '</div>'; | ||||
| 			    echo  '<hr><div class="alert alert-warning" role="alert">' . $_SESSION['info_Admin_Users'] . '</div>'; | ||||
| 			    $_SESSION['info_Admin_Users'] = null; | ||||
| 			} | ||||
| 			?>
 | ||||
|  | @ -108,17 +107,27 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") { | |||
| 			    <th>ID</th> | ||||
| 			    <th>Name</th> | ||||
| 			    <th>Email</th> | ||||
| 			    <th>Passport / ID </th> | ||||
| 			    <th>Reset password </th> | ||||
| 			    <th>Block/Activate </th> | ||||
| 			</tr> | ||||
| 			<?php | ||||
| 
 | ||||
| 			if ($_SESSION['user_type'] == "Lecturer") { | ||||
| 
 | ||||
| 			    $user_id = $_SESSION['user_id']; | ||||
| 			    echo "<script>console.log('here {$user_id}');</script>"; // debug trick
 | ||||
| 			    // find the TAs in the courses taught by this instructor
 | ||||
| 			    $ta_result = mysqli_query( | ||||
| 				$con, | ||||
| 				"SELECT TA FROM course_ta INNER JOIN courses_table ON course_ta.Course_ID=courses_table.Course_ID WHERE courses_table.Lecturer_User_ID=$user_id" | ||||
| 			    ); | ||||
| 			    $ta_ids = array(-1); // -1 is non-existent ID
 | ||||
| 			    while ($row =  mysqli_fetch_assoc($ta_result)) { | ||||
| 				array_push($ta_ids, $row['TA']); | ||||
| 			    } | ||||
| 			    $ta_ids2 = implode(', ', $ta_ids); | ||||
| 			    $result = mysqli_query( | ||||
| 				$con, | ||||
| 				"SELECT * FROM users_table WHERE UserType in ('TA')" | ||||
| 				"SELECT * FROM users_table WHERE UserType in ('TA') and User_ID in ($ta_ids2)" | ||||
| 			    ); | ||||
| 			} | ||||
| 
 | ||||
|  | @ -129,8 +138,9 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") { | |||
| 			    ); | ||||
| 			} | ||||
| 
 | ||||
| 			$num_rows = 0; | ||||
| 			while ($row = mysqli_fetch_assoc($result)) { | ||||
| 			    $pass = $row['Passport_Number']; | ||||
| 			    $pass =  $row['Password']; | ||||
| 			    $btn = "<button class='btn btn-warning' onclick=\"updatePassword(" . $row['User_ID'] . ",'$pass')\">Reset</button>"; | ||||
| 			    if ($row['Status'] == "Active") { | ||||
| 				$newstatus = "Blocked"; | ||||
|  | @ -140,7 +150,11 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") { | |||
| 				$btnBlock = "<button class='btn btn-success' onclick=\"blockUser(" . $row['User_ID'] . ",'$newstatus')\" id=\"activate_account_1\">Activate</button>"; | ||||
| 			    } | ||||
| 
 | ||||
| 			    echo "<tr><td>" . $row['User_ID'] . "</td><td>" . $row['Full_Name'] . "</td><td>" . $row['Email'] . "</td> <td>" . $row['Passport_Number'] . "</td><td>$btn</td><td>$btnBlock</td></tr>"; | ||||
| 			    echo "<tr><td>" . $row['User_ID'] . "</td><td>" . $row['Full_Name'] . "</td><td>" . $row['Email'] . "</td><td>$btn</td><td>$btnBlock</td></tr>"; | ||||
| 			    $num_rows += 1; | ||||
| 			} | ||||
| 			if ($num_rows == 0) { | ||||
| 			    echo "<p>No TA</p>"; | ||||
| 			} | ||||
| 			?>
 | ||||
| 		    </table> | ||||
|  | @ -225,8 +239,22 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") { | |||
|      | ||||
| </div> | ||||
| 
 | ||||
| 
 | ||||
| <?php include 'Footer.php';?>
 | ||||
| 
 | ||||
| <script> | ||||
|  /** After creating a TA account, stay on the same tab "Create instructor account" | ||||
|      Side effect: ?tacreated will be appended on the URL | ||||
|  */ | ||||
|  document.addEventListener("DOMContentLoaded", () => { | ||||
|      const url = new URL(window.location.href); | ||||
|      if (url.searchParams.has('tacreated')) { | ||||
| 	 const elem = document.querySelector('#tab_ins_accounts'); | ||||
| 	 elem.click(); | ||||
|      } | ||||
|  }); | ||||
| </script> | ||||
| 
 | ||||
| <script> | ||||
|  function updatePassword(id, pass) { | ||||
|      if (!confirm('Are you sure to reset user password?')) { | ||||
|  |  | |||
|  | @ -0,0 +1,87 @@ | |||
| <?php | ||||
| include 'NoDirectPhpAcess.php'; | ||||
| include 'Header.php'; | ||||
| include "get_mysql_credentials.php"; // Database credentials
 | ||||
| error_reporting(E_ALL); | ||||
| ini_set('display_errors', 1); | ||||
| 
 | ||||
| // Connect to the database
 | ||||
| $con = mysqli_connect("localhost", $mysql_username, $mysql_password, "lrr"); | ||||
| 
 | ||||
| if (mysqli_connect_errno()) { | ||||
|     die("Connection failed: " . mysqli_connect_error()); | ||||
| } | ||||
| 
 | ||||
| // Check if user is logged in
 | ||||
| if (isset($_SESSION['email'])) { | ||||
|     $email = $_SESSION['email']; | ||||
| 
 | ||||
|     // Check if form is submitted
 | ||||
|     if ($_SERVER['REQUEST_METHOD'] == 'POST') { | ||||
|         // Get the submitted answers
 | ||||
|         $answer1 = strtolower(trim($_POST['answer1'])); | ||||
|         $answer2 = strtolower(trim($_POST['answer2'])); | ||||
| 
 | ||||
|         // Fetch correct answers from the database
 | ||||
|         $sql = "SELECT user_id, answer1, answer2 FROM password_recovery_security_questions WHERE email = '$email'"; | ||||
|         $result = mysqli_query($con, $sql); | ||||
| 
 | ||||
|         if ($row = mysqli_fetch_assoc($result)) { | ||||
|             // Compare submitted answers with stored answers
 | ||||
|             if (hash_equals($row['answer1'], $answer1) && hash_equals($row['answer2'], $answer2)) { | ||||
|                 $_SESSION['user_id'] = $row['user_id']; | ||||
|                 header("Location: ResetPassword.php"); // Redirect to password reset page
 | ||||
|                 exit; | ||||
|             } else { | ||||
|                 $error_message = "Incorrect answers. Please try again."; | ||||
|             } | ||||
|         } else { | ||||
|             echo '<div class="container mt-5"><div class="alert alert-warning" role="alert">No security questions found for this user.</div></div>'; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Fetch security questions from the database for display
 | ||||
|     $sql = "SELECT question1, question2 FROM password_recovery_security_questions WHERE email = '$email'"; | ||||
|     $result = mysqli_query($con, $sql); | ||||
| 
 | ||||
|     if ($row = mysqli_fetch_assoc($result)) { | ||||
|         // Display the questions in a form
 | ||||
|         echo'<br/><br/><br/>'; | ||||
|         echo '<div class="container">'; | ||||
|         echo '<div class="row">'; | ||||
|         echo '<div class="col-md-5"></div>'; | ||||
|         echo '<div class="col-md-5">'; | ||||
|          if (isset($error_message)) { | ||||
|             echo '<div id="alertbad" class="alert alert-danger" role="alert">' . $error_message . '</div>'; // Display error message
 | ||||
|         } | ||||
| 
 | ||||
|         //echo '<center>';
 | ||||
|         echo '<form action="" method="POST" class="">'; | ||||
|         echo '<legend>Answer Your Security Questions.</legend>'; | ||||
| 
 | ||||
|         // Question 1
 | ||||
|         echo '<div class="mb-3">'; | ||||
|         echo '<label class="form-label">' . htmlspecialchars($row['question1']) . '</label>'; | ||||
|         echo '<input type="text" class="form-control" name="answer1" required>'; | ||||
|         echo '</div>'; | ||||
|         echo'<br/>'; | ||||
| 
 | ||||
|         // Question 2
 | ||||
|         echo '<div class="mb-3">'; | ||||
|         echo '<label class="form-label">' . htmlspecialchars($row['question2']) . '</label>'; | ||||
|         echo '<input type="text" class="form-control" name="answer2" required>'; | ||||
|         echo '</div>'; | ||||
| 
 | ||||
|         echo '<button id="sub" type="submit" class="btn btn-primary">Submit Answers</button>'; | ||||
|         echo '</form>'; | ||||
|         echo '</div></div></div>'; // Close container
 | ||||
|     } else { | ||||
|         echo '<div class="container mt-5"><div class="alert alert-warning" role="alert">No security questions found for this user.</div></div>'; | ||||
|     } | ||||
| } else { | ||||
|     header("Location: RecoverPassword.php"); // Redirect if session data is missing
 | ||||
|     exit; | ||||
| } | ||||
| 
 | ||||
| mysqli_close($con); | ||||
| ?>
 | ||||
							
								
								
									
										40
									
								
								Course.php
								
								
								
								
							
							
						
						
									
										40
									
								
								Course.php
								
								
								
								
							|  | @ -86,22 +86,22 @@ include 'Header.php'; | |||
| 
 | ||||
| 		<ul class="nav nav-tabs" id="myTab"> | ||||
| 		    <li class="nav-item"> | ||||
| 			<a class="nav-link active" href="#menu1">New</a> | ||||
| 			<a class="nav-link <?php if (!isset($_GET['tab']) || $_GET['tab'] == 'New') echo 'active'; ?>" data-toggle="tab" href="#menu1">New</a> | ||||
| 		    </li> | ||||
| 		    <li class="nav-item"> | ||||
| 			<a class="nav-link" href="#menu2">Missed</a> | ||||
| 			<a class="nav-link <?php if ($_GET['tab'] == 'Missed') echo 'active'; ?>" data-toggle="tab" href="#menu2">Missed</a> | ||||
| 		    </li> | ||||
| 		    <li class="nav-item"> | ||||
| 			<a class="nav-link" href="#menu3">Submitted</a> | ||||
| 			<a class="nav-link <?php if ($_GET['tab'] == 'Submitted') echo 'active'; ?>" data-toggle="tab" href="#menu3">Submitted</a> | ||||
| 		    </li> | ||||
| 		    <li class="nav-item"> | ||||
| 			<a class="nav-link" href="#menu4">Marked</a> | ||||
| 			<a class="nav-link <?php if ($_GET['tab'] == 'Marked') echo 'active'; ?>" data-toggle="tab" href="#menu4">Marked</a> | ||||
| 		    </li> | ||||
| 		</ul> | ||||
| 
 | ||||
| 		<div class="tab-content"> | ||||
| 
 | ||||
| 		    <div id="menu1" class="tab-pane active"> | ||||
| 		    <div id="menu1" class="tab-pane <?php if (!isset($_GET['tab']) || $_GET['tab'] == 'New') echo 'active'; ?>"> | ||||
| 
 | ||||
| 			<?php | ||||
| 
 | ||||
|  | @ -152,7 +152,7 @@ include 'Header.php'; | |||
| 				$att3 = $row['Attachment_link_3']; | ||||
| 				$att4 = $row['Attachment_link_4']; | ||||
| 				$labid = $row['Lab_Report_ID']; | ||||
| 				$days_remaining = date_diff(date_create($deadline), date_create())->format('%a days, %h hours, %i minutes'); | ||||
| 				$days_remaining = "Days remaining: ".date_diff(date_create($deadline), date_create())->format('%a days, %h hours, %i minutes'); | ||||
| 				$full_link = "<a href='~\..\Download.php?file=$att1'>$att1</a>"; | ||||
| 
 | ||||
| 				if($att2 != "") { | ||||
|  | @ -165,6 +165,11 @@ include 'Header.php'; | |||
| 				    $full_link = $full_link."| <a href='~\..\Download.php?file=$att4'>$att4</a>"; | ||||
| 				} | ||||
| 
 | ||||
| 				// check if the student has already submitted the assignment
 | ||||
| 				$query_result = mysqli_query($con, "SELECT * FROM lab_report_submissions WHERE Student_id=$student_id AND Lab_Report_ID=$labid"); | ||||
| 				if (mysqli_num_rows($query_result) > 0) | ||||
| 				    $days_remaining = 'You have already submitted this assignment.'; | ||||
| 
 | ||||
| 				echo "<div class='card mt-md-2' style='word-wrap: break-word;'>
 | ||||
|                                           <div class='card-body'> | ||||
|                                               <h5 class='card-title'>$title</h5> | ||||
|  | @ -172,7 +177,7 @@ include 'Header.php'; | |||
|                                               <p class='card-text'> $ins </p> | ||||
|                                               <p> <small>Attachments</small>: $full_link </p> | ||||
|                                               <p class='card-text'> <small> Posted: $posted     Deadline: $deadline </small> </p> | ||||
|                                               <div class='alert alert-warning'>Time left: $days_remaining</div> | ||||
|                                               <div class='alert alert-warning'>$days_remaining</div> | ||||
|                                               <p><a href='~\..\SubmitLab.php?id=$labid&url=$url' class='btn btn-primary'>Submit</a></p> | ||||
|                                           </div> | ||||
|                                       </div>";
 | ||||
|  | @ -185,7 +190,7 @@ include 'Header.php'; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 		    <div id="menu2" class="tab-pane"> | ||||
| 		    <div id="menu2" class="tab-pane <?php if ($_GET['tab'] == 'Missed') echo 'active'; ?>"> | ||||
| 
 | ||||
| 			<?php | ||||
| 			$group_id = $_SESSION['group_id']; | ||||
|  | @ -251,7 +256,7 @@ include 'Header.php'; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 		    <div id="menu3" class="tab-pane"> | ||||
| 		    <div id="menu3" class="tab-pane <?php if ($_GET['tab'] == 'Submitted') echo 'active'; ?>"> | ||||
| 			<?php | ||||
| 
 | ||||
| 			$group_id = $_SESSION['group_id']; | ||||
|  | @ -324,10 +329,10 @@ include 'Header.php'; | |||
| 					$att2 = $row['Attachment2']; | ||||
| 					$att3 = $row['Attachment3']; | ||||
| 					$att4 = $row['Attachment4']; | ||||
| 					$base_att1 = basename($att1); | ||||
| 					$base_att2 = basename($att2); | ||||
| 					$base_att3 = basename($att3); | ||||
| 					$base_att4 = basename($att4); | ||||
| 					$base_att1 = basename(rawurldecode($att1)); | ||||
| 					$base_att2 = basename(rawurldecode($att2)); | ||||
| 					$base_att3 = basename(rawurldecode($att3)); | ||||
| 					$base_att4 = basename(rawurldecode($att4)); | ||||
| 
 | ||||
| 					$full_link = "<a href='~\..\Download.php?file=$att1&attachment=1'>$base_att1</a>";  // prevent students from directly accessing their classmates' submissions
 | ||||
| 
 | ||||
|  | @ -371,7 +376,7 @@ include 'Header.php'; | |||
| 		    ?>
 | ||||
| 
 | ||||
| 
 | ||||
| 		    <div id="menu4" class="tab-pane"> | ||||
| 		    <div id="menu4" class="tab-pane <?php if ($_GET['tab'] == 'Marked') echo 'active'; ?>"> | ||||
| 			<?php | ||||
| 			$resultx  = mysqli_query($con, "SELECT Submission_ID, Submission_Date, lab_reports_table.Lab_Report_ID, Student_id, Course_Group_id, Notes, lab_report_submissions.Marks, lab_report_submissions.Remarking_Reason, Status, lab_reports_table.Title Lab_Title, lab_reports_table.Marks Original_marks
 | ||||
|                                                         FROM lab_report_submissions | ||||
|  | @ -647,11 +652,12 @@ include 'Header.php'; | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  function remarking(data) | ||||
|  function remarking(url) | ||||
|  { | ||||
|      const details = prompt("Please enter your remarking reasons",""); | ||||
| 
 | ||||
|      window.location.href = data+"&details="+details; | ||||
|      if (details != null) { | ||||
| 	 window.location.href = url+"&details="+details; | ||||
|      } | ||||
|  } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -324,7 +324,7 @@ include 'Header.php'; | |||
|             } | ||||
|             echo "</div>"; | ||||
| 
 | ||||
|             $resultx1 = mysqli_query($con, "SELECT course_students_table.Student_ID, users_table.Full_Name
 | ||||
|             $resultx1 = mysqli_query($con, "SELECT DISTINCT course_students_table.Student_ID, users_table.Full_Name
 | ||||
|                                             FROM course_students_table | ||||
|                                             INNER JOIN users_table on users_table.Student_ID=course_students_table.Student_ID | ||||
|                                             WHERE Course_ID=$course_id");
 | ||||
|  | @ -494,6 +494,10 @@ include 'Header.php'; | |||
| 		    echo '<hr><span class="alert alert-success" role="alert">' . $_SESSION['info_Courses_student'] . '</span>'; | ||||
| 		    $_SESSION['info_Courses_student'] = null; | ||||
| 		} | ||||
| 		if (isset($_SESSION['info_signup'])) { | ||||
|             echo  '<hr><div class="alert alert-danger" role="alert">' . $_SESSION['info_signup'] . '</div>'; | ||||
|             $_SESSION['info_signup'] = null; | ||||
| 		} | ||||
| 		?>
 | ||||
| 		<br><br> | ||||
| 	    </div> | ||||
|  | @ -534,7 +538,7 @@ include 'Header.php'; | |||
| 		    } | ||||
| 
 | ||||
| 		    if (mysqli_num_rows($result) == 0) { | ||||
|                 echo "No results. <hr>"; | ||||
|                 echo "No such course offered in this academic year.  Please check that your have entered the correct course code.<hr>"; | ||||
| 		    } else { | ||||
|                 while($row = mysqli_fetch_assoc($result)) { | ||||
|                     $name = $row['Course_Name']; | ||||
|  |  | |||
							
								
								
									
										16
									
								
								Header.php
								
								
								
								
							
							
						
						
									
										16
									
								
								Header.php
								
								
								
								
							|  | @ -1,14 +1,24 @@ | |||
| <?php | ||||
| error_reporting(E_ALL); | ||||
| ini_set('display_errors', 1); | ||||
| ?>
 | ||||
| 
 | ||||
| <?php | ||||
| session_start(); | ||||
| error_reporting(0); | ||||
| date_default_timezone_set('Asia/Shanghai'); | ||||
| 
 | ||||
| include "get_mysql_credentials.php"; | ||||
| $con = mysqli_connect("localhost", $mysql_username, $mysql_password, "lrr"); | ||||
| try { | ||||
|     $con = mysqli_connect("localhost", $mysql_username, $mysql_password, "lrr"); | ||||
| } catch (mysqli_sql_exception $e) { | ||||
|     echo $e->getMessage(); | ||||
| } | ||||
| 
 | ||||
| // Check database connection
 | ||||
| if (mysqli_connect_errno()) { | ||||
|     echo "Failed to connect to MySQL: " . mysqli_connect_error(); | ||||
|     echo " Error number: ".mysqli_connect_errno(); | ||||
|     exit(); | ||||
| } | ||||
| ?>
 | ||||
| 
 | ||||
|  | @ -152,7 +162,7 @@ if (mysqli_connect_errno()) { | |||
| 
 | ||||
| 			<?php | ||||
| 			if (isset($_SESSION["user_fullname"])) { | ||||
|                 if ($_SESSION['user_type'] == "Student" || $_SESSION['user_type'] == 'Lecturer') { | ||||
|                 if ($_SESSION['user_type'] == "Student" || $_SESSION['user_type'] == 'Lecturer' || $_SESSION['user_type'] == 'TA') { | ||||
|                     echo "<a class='nav-link' href='~\..\Courses.php'><i class='fa fa-book'></i> My courses </a>"; | ||||
|                 } | ||||
| 			?>
 | ||||
|  |  | |||
							
								
								
									
										23
									
								
								README.md
								
								
								
								
							
							
						
						
									
										23
									
								
								README.md
								
								
								
								
							|  | @ -3,9 +3,9 @@ | |||
| LRR (Lab Report Repository) is an online software application for course instructors to post, receive and mark assignments, and for students to submit assignments, or submit re-marking requests. | ||||
| 
 | ||||
| This software was originally developed by Mahomed Nor in 2018, a graduate student in the Department of Computer Science at the Zhejiang Normal University, | ||||
| while he was taking a graduate course called **Advanced Software Engineering** (http://lanlab.org/course/2018f/se/homepage.html). | ||||
| while he was taking a graduate course called Advanced Software Engineering. | ||||
| 
 | ||||
| The LRR's project home page is at http://121.4.94.30/homepage/.  For potential project contributors, we recommend that you browse its home page first to familiarize yourself  with the project. | ||||
| For potential project contributors, we recommend that you browse its home page at ./homepage/index.html first to familiarize yourself with the project. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -159,7 +159,16 @@ https://github.com/spm2020spring/TeamCollaborationTutorial/blob/master/team.rst | |||
| 
 | ||||
| ## Testing | ||||
| 
 | ||||
| Make sure your changes can pass all the tests in folder [./test](http://121.4.94.30:3000/mrlan/LRR/src/branch/master/test). | ||||
| Make sure your changes can pass all the tests in folder ./test. | ||||
| 
 | ||||
| You cannot do too much unit testing for LRR because it almost does not | ||||
| have functions or classes.  However, you can do end-to-end testing. | ||||
| It is important that you *restore* the database each time before your | ||||
| run a test case.  The fixture *restore_database* in ./test/conftest.py | ||||
| is used to restore the database. Please check that.  A use case for | ||||
| this fixture can be found in the test script | ||||
| ./test/SeleniumMpiana/test_bug418_yaaqob.py.  You could run this test script | ||||
| by typing the following command: `pytest ./SeleniumMpiana/test_bug418_yaaqob.py` | ||||
| 
 | ||||
| 
 | ||||
| ## Communications Method | ||||
|  | @ -173,10 +182,10 @@ We can also communicate through pull requests.  You make a pull request, I revie | |||
| ## Frequently Asked Questions | ||||
| 
 | ||||
| 
 | ||||
| 1. Q: The web application's front page does not show properly, i.e., elements are not well aligned.  | ||||
| 1. Q: The web application's front page does not show properly, i.e., elements are not well aligned.      | ||||
|    A: You missed two folders `css` and `font-awesome`.  These folders include third-party js or css files and therefore are not included. | ||||
| 
 | ||||
| 1. Q: What if I do not have any information about the `lrr` database? | ||||
| 1. Q: What if I do not have any information about the `lrr` database?     | ||||
|    A: You could use `lrr_database.sql` to make a new database.  | ||||
| 
 | ||||
| 
 | ||||
|  | @ -249,6 +258,6 @@ Nicole-Rutagengwa  - Nicole Rutagengwa  - 2019169 | |||
| 
 | ||||
| # References | ||||
| 
 | ||||
| - 詹沈晨. (2020). [网页程序测试自动化 (Selenium) 测试效率](http://lanlab.org/ZhanShenchen-On-Automated-Web-Application-Test-Efficiency-with-Selenium.doc) | ||||
| - 詹沈晨. (2020). 网页程序测试自动化 (Selenium) 测试效率. | ||||
| 
 | ||||
| - Ibrahim. (2021).  [Defect analysis for LRR](http://lanlab.org/thesis/Defect-Analysis-for-LRR.docx) | ||||
| - Ibrahim. (2021).  Defect analysis for LRR] | ||||
|  |  | |||
|  | @ -15,11 +15,9 @@ include 'Header.php'; | |||
| 	    <form method="post" action="Script.php"> | ||||
| 		<legend>Recover password</legend> | ||||
| 		<input type="hidden" name="form_recover_password" value="true"/> | ||||
| 		Student number | ||||
| 		<input type="text" name="sno" placeholder="Enter your student number" class="form-control" required="required" value="<?php echo htmlspecialchars($_SESSION['student_number']); ?>"> <br/> | ||||
| 		Email | ||||
| 		<input type="text" name="email" placeholder="Enter your email address" class="form-control" required="required" value="<?php echo htmlspecialchars($_SESSION['user_email']); ?>"> <br/> | ||||
| 		<button type="submit" class="btn btn-primary">Recover</button> | ||||
| 		<button id="rec"  type="submit" class="btn btn-primary">Recover</button> | ||||
| 	    </form> | ||||
| 	</div> | ||||
|     </div> | ||||
|  | @ -0,0 +1,78 @@ | |||
| <?php | ||||
| require_once 'Header.php'; | ||||
| require_once 'NoDirectPhpAcess.php'; | ||||
| require_once "get_mysql_credentials.php"; | ||||
| 
 | ||||
| ini_set('display_errors', 0); | ||||
| error_reporting(E_ALL); | ||||
| 
 | ||||
| $con = mysqli_connect("localhost", $mysql_username, $mysql_password, "lrr"); | ||||
| 
 | ||||
| if (mysqli_connect_errno()) { | ||||
|     error_log("Database connection failed: " . mysqli_connect_error()); | ||||
|     die("An error occurred. Please try again later."); | ||||
| } | ||||
| 
 | ||||
| // Check if user_id is set in the session
 | ||||
| if (!isset($_SESSION['email'])) { | ||||
|     die("Session expired. Please log in again."); | ||||
| } | ||||
| 
 | ||||
| $email = $_SESSION['email']; | ||||
| 
 | ||||
| if ($_SERVER['REQUEST_METHOD'] == 'POST') { | ||||
|     // Handle password reset
 | ||||
|     if (isset($_POST['new_password']) && isset($_POST['confirm_password'])) { | ||||
|         $new_password = $_POST['new_password']; | ||||
|         $confirm_password = $_POST['confirm_password']; | ||||
| 
 | ||||
|         if (!preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\d\s]).{8,}$/', $new_password)) { | ||||
|             echo '<div class="alert alert-danger">Password must be at least 8 characters long and include uppercase and lowercase letters, numbers, and special characters.</div>'; | ||||
|         } elseif ($new_password !== $confirm_password) { | ||||
|             echo '<div class="alert alert-danger">Passwords do not match. Please try again.</div>'; | ||||
|         } else { | ||||
|             $hashed_password = password_hash($new_password, PASSWORD_ARGON2ID); | ||||
|             $user_id = $_SESSION['user_id']; | ||||
| 
 | ||||
|             $stmt = $con->prepare("UPDATE users_table SET Password = ? WHERE email = ? AND user_id = ?"); | ||||
|             $stmt->bind_param("sss", $hashed_password, $email, $user_id); | ||||
| 
 | ||||
|             if ($stmt->execute()) { | ||||
|                 echo '<div class="alert alert-success">Password reset successfully. You can now log in with your new password.</div>'; | ||||
|                 unset($_SESSION['user_id']); // Clear user_id after successful password reset
 | ||||
|                 header("Location: index.php"); | ||||
|             } else { | ||||
|                 error_log("Error updating password for user ID: $user_id"); | ||||
|                 echo '<div class="alert alert-danger">An error occurred. Please try again later.</div>'; | ||||
|             } | ||||
|             $stmt->close(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Display the reset password form
 | ||||
| echo ' | ||||
| <br/><br/><br/> | ||||
| <div class="container"> | ||||
| <div class="row"> | ||||
| <div class="col-md-5"></div> | ||||
| <div class="col-md-5"> | ||||
| <form action="" method="POST" class=""> | ||||
|     <legend>Reset Your Password</legend><br/> | ||||
|        New Password <label class="form-text">Must include uppercase and lowercase letters, digits and special characters.</label>   | ||||
|        <input type="password" name="new_password"  placeholder=" Enter New Password" class="form-control" required> | ||||
|        <br/> | ||||
|       Confirm New Password | ||||
|         <input type="password" name="confirm_password" placeholder="Confirm New Password" class="form-control" required> | ||||
|      <br/> | ||||
|     <button id="butt" type="submit" class="btn btn-primary">Reset Password</button> | ||||
| </form> | ||||
| </div></div></div> | ||||
| <style> | ||||
| .guideline { display: none;} | ||||
| #newPassword:focus + .guideline {display: block;}
 | ||||
| '; | ||||
| 
 | ||||
| 
 | ||||
| mysqli_close($con); | ||||
| ?>
 | ||||
							
								
								
									
										247
									
								
								Script.php
								
								
								
								
							
							
						
						
									
										247
									
								
								Script.php
								
								
								
								
							|  | @ -2,6 +2,7 @@ | |||
| include 'NoDirectPhpAcess.php'; | ||||
| ?>
 | ||||
| 
 | ||||
| 
 | ||||
| <?php | ||||
| 
 | ||||
| /*  | ||||
|  | @ -12,7 +13,6 @@ session_start(); | |||
| 
 | ||||
| date_default_timezone_set('Asia/Shanghai'); | ||||
| 
 | ||||
| // Connect to MySQL database
 | ||||
| include "get_mysql_credentials.php"; | ||||
| $con = mysqli_connect("localhost",  $mysql_username, $mysql_password, "lrr"); | ||||
| 
 | ||||
|  | @ -70,15 +70,20 @@ if (!empty($_POST["form_signup"])) { | |||
|     // check if email is taken
 | ||||
|     $result = mysqli_query($con, "SELECT * FROM users_table WHERE email='$email'"); | ||||
|     if (mysqli_num_rows($result) != 0) { | ||||
|         $_SESSION["info_signup"] = "Email address " . $email . "  is already in use."; | ||||
|         $_SESSION['user_fullname'] = null; | ||||
|         header("Location: signup.php"); | ||||
|         return; | ||||
|         $_SESSION["info_signup"] = "Email address " . $email . "  is already in use.  You have already signed up?"; | ||||
|     } | ||||
| 
 | ||||
|     $_SESSION['user_fullname'] = $_POST["fullname"]; | ||||
|     $_SESSION['user_fullname_temp'] = $_POST["fullname"]; | ||||
|     $_SESSION['user_email'] = $_POST["email"]; | ||||
|     $_SESSION['user_student_id_temp'] = $_POST["user_student_id"]; | ||||
|     | ||||
| 
 | ||||
| 
 | ||||
|     // validate student number
 | ||||
|     if (!is_valid_student_number($student_id)) { | ||||
|         $_SESSION["info_signup"] = "Invalid student number."; | ||||
|         $_SESSION['user_fullname'] = null; | ||||
|         header("Location: signup.php"); | ||||
|         return; | ||||
|     } | ||||
|  | @ -87,6 +92,10 @@ if (!empty($_POST["form_signup"])) { | |||
|     $result = mysqli_query($con, "SELECT * FROM `students_data` WHERE Student_ID='$student_id'"); | ||||
|     if (mysqli_num_rows($result) == 0) { | ||||
|         $_SESSION["info_signup"] = "Your entered student number could not be verified.  Please contact Student Management Office <lanhui at zjnu.edu.cn>.  Thanks."; | ||||
|           $_SESSION['user_fullname'] = null; | ||||
| 
 | ||||
|          | ||||
| 
 | ||||
|         header("Location: signup.php"); | ||||
|         return; | ||||
|     } | ||||
|  | @ -97,6 +106,7 @@ if (!empty($_POST["form_signup"])) { | |||
|     $student_result = mysqli_query($con, "SELECT * FROM `users_table` WHERE Student_ID='$student_id'"); | ||||
|     if (mysqli_num_rows($student_result) > 0) { | ||||
|         $_SESSION["info_signup"] = "This Student ID is already in use! Please contact Student Management Office <lanhui at zjnu.edu.cn> for help."; | ||||
|         $_SESSION['user_fullname'] = null; | ||||
|         header("Location: signup.php"); | ||||
|         return; | ||||
|     } | ||||
|  | @ -106,18 +116,75 @@ if (!empty($_POST["form_signup"])) { | |||
| if (!empty($_POST["form_signup"])) { | ||||
|     $fullname = mysqli_real_escape_string($con, $_POST["fullname"]); | ||||
|     $student_id = mysqli_real_escape_string($con, $_POST["user_student_id"]); | ||||
|     $_SESSION['user_fullname'] = $fullname; | ||||
| 
 | ||||
|     $email = mysqli_real_escape_string($con, $_POST["email"]); | ||||
|     $password = mysqli_real_escape_string($con, $_POST["password"]); | ||||
|     $confirmpassword = mysqli_real_escape_string($con, $_POST["confirmpassword"]); | ||||
| 
 | ||||
|     $_SESSION['user_student_id'] = $_POST["student_id"]; | ||||
|     $_SESSION['user_type'] = "Student"; | ||||
|      | ||||
|     // check confirmed password
 | ||||
|     if (strcasecmp($password, $confirmpassword) != 0) { | ||||
|         $_SESSION['info_signup'] = "Password confirmation failed."; | ||||
|         $_SESSION['user_fullname'] = null;  // such that Header.php do not show the header information.        
 | ||||
|         header("Location: signup.php"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // validate email
 | ||||
|     if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { | ||||
|         $_SESSION['info_signup'] = "Invalid email address."; | ||||
|         $_SESSION['user_fullname'] = null; | ||||
| 
 | ||||
|         header("Location: signup.php"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     $upperLetter     = preg_match('@[A-Z]@',    $password); | ||||
|     $smallLetter     = preg_match('@[a-z]@',    $password); | ||||
|     $containsDigit   = preg_match('@[0-9]@',    $password); | ||||
|     $containsSpecial = preg_match('@[^\w]@',    $password); | ||||
|     $containsAll = $upperLetter && $smallLetter && $containsDigit && $containsSpecial; | ||||
| 
 | ||||
|     // check for strong password
 | ||||
|     if (!$containsAll) { | ||||
|         $_SESSION['info_signup'] = "Password must have at least characters that include lowercase letters, uppercase letters, numbers and special characters (e.g., !?.,*^)."; | ||||
|         $_SESSION['user_fullname'] = null; | ||||
| 
 | ||||
|         header("Location: signup.php"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // check if email is taken
 | ||||
|     $result = mysqli_query($con, "SELECT * FROM users_table WHERE email='$email'"); | ||||
|     if(mysqli_num_rows($result) != 0) | ||||
|     { | ||||
|         $_SESSION["info_signup"]="Email address ".$email." is already in use.  Do you have an old LRR account?"; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     $_SESSION['user_type'] = "Student"; | ||||
|     $_SESSION['user_email'] = $email; | ||||
|     $_SESSION['user_student_id'] = $student_id; | ||||
| 
 | ||||
|     // apply password_hash()
 | ||||
|     $password_hash = password_hash($password, PASSWORD_DEFAULT); | ||||
|     $sql = "INSERT INTO `users_table`(`Email`, `Password`, `Full_Name`, `UserType`, `Student_ID`) VALUES " | ||||
|         . "('$email','$password_hash','$fullname','Student','$student_id')"; | ||||
|     $sql = "INSERT INTO `users_table`(`Email`, `Password`, `HashPassword`, `Full_Name`, `UserType`, `Student_ID`) VALUES " | ||||
|         . "('$email','$password_hash','','$fullname','Student','$student_id')"; | ||||
|      | ||||
| 
 | ||||
|     $_SESSION['user_fullname'] =$_SESSION['user_fullname_temp']; | ||||
| 
 | ||||
|     if ($con->query($sql) === TRUE) { | ||||
|         header("Location: Courses.php"); | ||||
|     	// Get the newly inserted user's ID
 | ||||
|     	$user_id = $con->insert_id; | ||||
|     	 | ||||
|     	//Set the user_id in the session
 | ||||
|     	$_SESSION['user_id'] = $user_id; | ||||
|     	 | ||||
|     	//Redirect to SecurityQuestions.php
 | ||||
|         header("Location: SecurityQuestions.php"); | ||||
|     } else { | ||||
|         echo "Something really bad (SQL insertion error) happened during sign up."; | ||||
|     } | ||||
|  | @ -130,11 +197,15 @@ if (!empty($_POST["form_login"])) { | |||
|     $user = mysqli_real_escape_string($con, $_POST["user"]); // user could be a 12-digit student number or an email address
 | ||||
|     $is_student_number = 0; | ||||
| 
 | ||||
|     $_SESSION["failed_login_user"] = $user;  // Save the entered username in a session variable
 | ||||
|     echo "Failed login user: " . $_SESSION["failed_login_user"]; | ||||
| 
 | ||||
|     // Validate student number
 | ||||
|     if (is_valid_student_number($user)) { | ||||
|         $is_student_number = 1; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     // Validate email address if what provided is not a student number
 | ||||
|     if (!$is_student_number && !filter_var($user, FILTER_VALIDATE_EMAIL)) { | ||||
|         $_SESSION["info_login"] = "Invalid email address: " . "$user"; | ||||
|  | @ -160,61 +231,91 @@ if (!empty($_POST["form_login"])) { | |||
|                 $_SESSION['user_type'] = $row['UserType']; | ||||
|                 $_SESSION['user_fullname'] = $row['Full_Name']; | ||||
| 
 | ||||
|  // Check if the user is a student and has not set up their password recovery yet
 | ||||
| 
 | ||||
|                 if ($_SESSION['user_type'] == "Student") { | ||||
|                     header("Location: Courses.php"); | ||||
|                     // Query to check if the student has completed the password recovery setup
 | ||||
|                     $recovery_result = mysqli_query($con, "SELECT * FROM password_recovery_security_questions WHERE Student_ID = '" . $row['Student_ID'] . "'"); | ||||
|                     if (mysqli_num_rows($recovery_result) == 0) { | ||||
|                         // If the student has not set up password recovery, redirect to the setup page
 | ||||
|                         header("Location: SecurityQuestions.php"); | ||||
|                         exit(); | ||||
|                     } else { | ||||
|                         // If the student has set up password recovery, redirect to the Courses page
 | ||||
|                         header("Location: Courses.php"); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                // Redirect other user types to their respective pages
 | ||||
| 
 | ||||
|                 if ($_SESSION['user_type'] == "Lecturer") { | ||||
|                     header("Location: Courses.php"); | ||||
|                     $recovery_result = mysqli_query($con, "SELECT * FROM password_recovery_security_questions WHERE user_id = '" . $row['User_ID'] . "' AND user_type = 'Lecturer'"); | ||||
|                     if (mysqli_num_rows($recovery_result) == 0) { | ||||
|                      header("Location: SecurityQuestions.php"); | ||||
|                      exit(); | ||||
|                    } else { | ||||
|                      header("Location: Courses.php"); } | ||||
|                 } | ||||
| 
 | ||||
|                 if ($_SESSION['user_type'] == "TA") { | ||||
|                     header("Location: Courses.php"); | ||||
|                     $recovery_result = mysqli_query($con, "SELECT * FROM password_recovery_security_questions WHERE user_id = '" . $row['User_ID'] . "' AND user_type = 'TA'"); | ||||
|                     if (mysqli_num_rows($recovery_result) == 0) { | ||||
|                      header("Location: SecurityQuestions.php"); | ||||
|                      exit(); | ||||
|                    } else {  | ||||
|                      header("Location: Courses.php"); } | ||||
| 
 | ||||
|                 } | ||||
| 
 | ||||
|                 if ($_SESSION['user_type'] == "Admin") { | ||||
|                     header("Location: Admin.php"); | ||||
|                     $recovery_result = mysqli_query($con, "SELECT * FROM password_recovery_security_questions WHERE user_id = '" . $row['User_ID'] . "' AND user_type = 'Admin'"); | ||||
|                     if (mysqli_num_rows($recovery_result) == 0) { | ||||
|                      header("Location: SecurityQuestions.php"); | ||||
|                      exit(); | ||||
|                    } else {  | ||||
|                      header("Location: Admin.php"); } | ||||
| 
 | ||||
|                 } | ||||
|                 //  report wrong pass if not correct
 | ||||
|             } else { | ||||
|                 return; | ||||
| 
 | ||||
|             }  else { | ||||
|                  | ||||
|                 $_SESSION["wrong_pass"] = "Wrong Password."; | ||||
|                 echo $_SESSION["wrong_pass"];  // Optional: Display the error message for debugging
 | ||||
|                 | ||||
|                 header("Location: index.php"); | ||||
|                 exit();  // Add this line to prevent further execution after redirect
 | ||||
|             } | ||||
|             // Reset the session variable when needed
 | ||||
|             unset($_SESSION["failed_login_user"]); | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // ################################ Recover Password  #####################################
 | ||||
| 
 | ||||
| if (!empty($_POST["form_recover_password"])) { | ||||
| 
 | ||||
|     $student_id = mysqli_real_escape_string($con, $_POST["sno"]); | ||||
|     $email = mysqli_real_escape_string($con, $_POST["email"]); | ||||
| 
 | ||||
|     // validate student number
 | ||||
|     if (strlen($student_id) != 12  || is_numeric($student_id) == FALSE) { | ||||
|         $_SESSION["info_recover_password"] = "Invalid student number."; | ||||
|         header("Location: recover_password.php"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // validate email
 | ||||
|     // Validate email
 | ||||
|     if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { | ||||
|         $_SESSION["info_recover_password"] = "Invalid email address."; | ||||
|         // echo "Invalid email address.";
 | ||||
|         header("Location: recover_password.php"); | ||||
|         header("Location: RecoverPassword.php"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     $result = mysqli_query($con, "SELECT * FROM users_table WHERE Email='$email' and Student_ID='$student_id'"); | ||||
|     if (mysqli_num_rows($result) == 0) { | ||||
|         $_SESSION["info_recover_password"] = "Email address is not recognised."; | ||||
|         $_SESSION["info_recover_password"] = "Identity not recognized.  Try again or send an inquiry email message to lanhui at zjnu.edu.cn."; | ||||
|         header("Location: recover_password.php"); | ||||
|     } else { | ||||
|         $result = mysqli_query($con, "DELETE FROM users_table WHERE Email='$email' and Student_ID='$student_id'"); | ||||
|         header("Location: signup.php"); | ||||
|     } | ||||
|     // Check if user exists in the database
 | ||||
| $result = mysqli_query($con, "SELECT * FROM users_table WHERE Email='$email'"); | ||||
| if (mysqli_num_rows($result) == 0) { | ||||
|     $_SESSION["info_recover_password"] = "Email address is not recognized."; | ||||
|     header("Location: RecoverPassword.php"); | ||||
| } else { | ||||
|     // Store the student ID and email in the session
 | ||||
|     $_SESSION['email'] = $email; | ||||
|     header("Location: AnswerSecurityQuestions.php"); | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // ################################ RESET Password  #####################################
 | ||||
|  | @ -263,32 +364,52 @@ if (!empty($_POST["form_reset_password"])) { | |||
| } | ||||
| 
 | ||||
| // ############################### CREATE Lecturer/TA USER ##################################
 | ||||
| if (!empty($_POST["form_createlecturrer"])) { | ||||
| if (!empty($_POST["form_createlecturer"])){ | ||||
|     $email = mysqli_real_escape_string($con, $_POST["email"]); | ||||
|     $fullname = mysqli_real_escape_string($con, $_POST["fullname"]); | ||||
|     $type = mysqli_real_escape_string($con, $_POST["type"]); | ||||
|     $password = mysqli_real_escape_string($con, $_POST["passport"]); | ||||
|     // check if email is taken
 | ||||
|     $password = mysqli_real_escape_string($con, $_POST["password"]); | ||||
|     $pass_len = strlen($password); | ||||
|     if ($pass_len == 0) { | ||||
|         $password = generateStrongPassword(); | ||||
|     } | ||||
| 
 | ||||
|     $result = mysqli_query( | ||||
|         $con, | ||||
|         "SELECT * FROM Users_Table WHERE email='$email'" | ||||
|         "SELECT * FROM users_table WHERE email='$email'" | ||||
|     ); | ||||
|     if (mysqli_num_rows($result) != 0) { | ||||
|         $_SESSION["info_Admin_Users"] = "Email address : " . $email . " is already in use."; | ||||
|         header("Location: Admin.php"); | ||||
|         exit; | ||||
|     } | ||||
|     $password_hash = password_hash("$password", PASSWORD_DEFAULT); | ||||
|     $sql = "INSERT INTO `users_table`(`Email`, `Password`, `Full_Name`, `UserType`) VALUES " | ||||
|         . "('$email','$password_hash','$fullname','$type')"; | ||||
|     $sql = "INSERT INTO `users_table`(`Email`, `Password`, `HashPassword`, `Full_Name`, `UserType`) VALUES ('$email','$password_hash','','$fullname','$type')"; | ||||
| 
 | ||||
|     if ($con->query($sql) === TRUE) { | ||||
|         $_SESSION["info_Admin_Users"] = $type . " user created successfully. Use email " . $email . " as account name and $password as password."; | ||||
|         header("Location: Admin.php"); | ||||
|     } else { | ||||
|         echo "Error: " . $sql . "<br>" . $con->error; | ||||
|     try { | ||||
|         $result = mysqli_query($con, $sql); | ||||
|         $_SESSION["info_Admin_Users"] = $type . " user created successfully. Use email " . $email . " as account name and ". $password ." as password."; | ||||
|         header("Location: Admin.php?tacreated"); | ||||
|     } catch (Exception $ex) { | ||||
|         echo "$ex"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // ### FUNCTION TO GENERATE INITIAL PASSWORDS ###//
 | ||||
| function generateStrongPassword() { | ||||
| 
 | ||||
|     $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_'; | ||||
|     $password_length = 12; | ||||
|     $gen_password = ''; | ||||
|     for ($i = 0; $i < $password_length; $i++) { | ||||
|         $random_index = mt_rand(0, strlen($characters) - 1); | ||||
|         $gen_password .= $characters[$random_index]; | ||||
|     } | ||||
| 
 | ||||
|     // Return the generated password
 | ||||
|     return $gen_password; | ||||
| } | ||||
| 
 | ||||
| // #### FUNCTION CHECK FILE TYPES ////
 | ||||
| 
 | ||||
| function is_valid_file_format($file) | ||||
|  | @ -691,8 +812,8 @@ if (!empty($_GET["remarking"])) { | |||
| 
 | ||||
|     if ($con->query($sql) === TRUE) { | ||||
| 
 | ||||
|         $_SESSION["info_general"] = "Remarking request sent"; | ||||
|         header("Location: Course.php?url=" . $url); | ||||
|         $_SESSION["info_general"] = "Remarking Request Sent"; | ||||
|         header("Location: Course.php?url=" . $url . "&tab=Marked"); | ||||
|     } else { | ||||
|         echo "Error: " . $sql . "<br>" . $con->error; | ||||
|     } | ||||
|  | @ -912,18 +1033,32 @@ if (!empty($_GET["ignoreremarking"])) { | |||
| #Assign TA
 | ||||
| 
 | ||||
| if (!empty($_GET["assignTA"])) { | ||||
| 
 | ||||
|     $id = mysqli_real_escape_string($con, $_GET["id"]); | ||||
|     $ta = mysqli_real_escape_string($con, $_GET["ta"]); | ||||
| 
 | ||||
|     $sql = "INSERT INTO `course_ta`(`Course_ID`, `TA`) VALUES ('$id','$ta')"; | ||||
|     // Check if the TA is already assigned to the course
 | ||||
|     $check_sql = "SELECT * FROM course_ta WHERE Course_ID='$id' AND TA='$ta'"; | ||||
|     $check_result = $con->query($check_sql); | ||||
| 
 | ||||
|     if ($con->query($sql) === TRUE) { | ||||
| 
 | ||||
|         $_SESSION["info_Admin_Courses"] = $type . " Course TA Assigned "; | ||||
|         header("Location: Admin.php"); | ||||
|     if ($check_result->num_rows > 0) { | ||||
|         // Alert user about the duplicate assignment
 | ||||
|         echo "<script>
 | ||||
|             alert('The selected TA is already assigned to this course.'); | ||||
|             window.location.href='Admin.php'; | ||||
|         </script>";
 | ||||
|     } else { | ||||
|         echo "Error: " . $sql . "<br>" . $con->error; | ||||
|         // Proceed with the TA assignment
 | ||||
|         $sql = "INSERT INTO course_ta(Course_ID, TA) VALUES ('$id','$ta')"; | ||||
| 
 | ||||
|         if ($con->query($sql) === TRUE) { | ||||
|             $_SESSION["info_Admin_Courses"] = $type . " Course TA Assigned "; | ||||
|             header("Location: Admin.php"); | ||||
|         } else { | ||||
|             echo "<script>
 | ||||
|                 alert('You must select a TA first!.'); | ||||
|                 window.location.href='Admin.php'; | ||||
|             </script>";
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,139 @@ | |||
| <?php | ||||
| session_start(); | ||||
| error_reporting(0); | ||||
| date_default_timezone_set('Asia/Shanghai'); | ||||
| 
 | ||||
| include 'NoDirectPhpAcess.php'; | ||||
| include "get_mysql_credentials.php"; // Database credentials
 | ||||
| error_reporting(E_ALL); | ||||
| ini_set('display_errors', 1); | ||||
| 
 | ||||
| $con = mysqli_connect("localhost", $mysql_username, $mysql_password, "lrr"); | ||||
| 
 | ||||
| if (mysqli_connect_errno()) { | ||||
|     die("Connection failed: " . mysqli_connect_error()); | ||||
| } | ||||
| 
 | ||||
| // Check if user_id is set in the session
 | ||||
| if (!isset($_SESSION['user_id'])) { | ||||
|     echo '<div class="alert alert-danger" role="alert">Session expired. Please log in again.</div>'; | ||||
|     exit(); // Stop script execution if user_id is not set
 | ||||
| } | ||||
| 
 | ||||
| if ($_SERVER['REQUEST_METHOD'] == 'POST') { | ||||
|     // Get the security questions and answers from the form
 | ||||
|     $question1 = mysqli_real_escape_string($con, $_POST['security_question1']); | ||||
|     $answer1 = strtolower(mysqli_real_escape_string($con, $_POST['security_answer1'])); | ||||
|     $question2 = mysqli_real_escape_string($con, $_POST['security_question2']); | ||||
|     $answer2 = strtolower(mysqli_real_escape_string($con, $_POST['security_answer2'])); | ||||
| 
 | ||||
|     // Get the user ID and user type from the session
 | ||||
|     $user_id = $_SESSION['user_id']; // Use user_id from session
 | ||||
|     $user_type = $_SESSION['user_type']; //Get user type from session
 | ||||
|     $email = $_SESSION['user_email']; | ||||
|     $student_id = isset($_SESSION['user_student_id']) ? $_SESSION['user_student_id'] : NULL; //Handle student_id for students
 | ||||
| 
 | ||||
|     // Prepare SQL statement
 | ||||
|     if($user_type == 'Student') {  | ||||
|     $sql = "INSERT INTO password_recovery_security_questions (user_id,user_type,  student_id, email, question1, answer1, question2, answer2)    
 | ||||
|             VALUES ('$user_id', '$user_type', '$student_id', '$email', '$question1', '$answer1', '$question2', '$answer2')  | ||||
|             ON DUPLICATE KEY UPDATE  | ||||
|                 question1='$question1',  | ||||
|                 answer1='$answer1',  | ||||
|                 question2='$question2',  | ||||
|                 answer2='$answer2'";
 | ||||
|     } else { | ||||
|     // For non-students (Lecturer, TA, etc.), exclude student_id
 | ||||
|         $sql = "INSERT INTO password_recovery_security_questions (user_id, user_type, email, question1, answer1, question2, answer2)    
 | ||||
|                 VALUES ('$user_id', '$user_type', '$email', '$question1', '$answer1', '$question2', '$answer2')  | ||||
|                 ON DUPLICATE KEY UPDATE  | ||||
|                     question1='$question1',  | ||||
|                     answer1='$answer1',  | ||||
|                     question2='$question2',  | ||||
|                     answer2='$answer2'";
 | ||||
|     } | ||||
| 
 | ||||
|     // Execute the query and check for success
 | ||||
|     if (mysqli_query($con, $sql)) { | ||||
|         echo '<div id="alertgood" class="alert alert-success" role="alert">Password recovery details set successfully. Please remember your answers! Redirecting to Courses page...</div>'; | ||||
| 	echo '<script>'; | ||||
| 	echo ' setTimeout(function() {'; | ||||
| 	echo ' 	var userType = "'. $_SESSION['user_type'] . '";'; | ||||
| 	echo ' 	if (userType === "Admin") {'; | ||||
| 	echo ' 	   window.location.href = "Admin.php";'; | ||||
| 	echo '  } else {'; | ||||
| 	echo ' 	   window.location.href = "Courses.php";'; | ||||
| 	echo ' 	}'; | ||||
| 	echo ' }, 2000);';  | ||||
| 	echo '</script>'; | ||||
|     } else { | ||||
|         echo '<div class="alert alert-danger" role="alert">Error: ' . mysqli_error($con) . '</div>'; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| mysqli_close($con); | ||||
| ?>
 | ||||
| 
 | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>Security Questions</title> | ||||
|     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet"> | ||||
| </head> | ||||
| <body> | ||||
| <nav class="navbar navbar-expand-lg bg-body-tertiary" style="padding-left:180px;padding-right:150px;margin:auto;"> | ||||
| 	    <div class="container-fluid"> | ||||
| 
 | ||||
| 		<a class="navbar-brand" href="#"> <img src="logo.png" style="width:30px;height:30px;" alt="LRR Logo"> LRR </a> | ||||
| </nav> | ||||
| <br/><br/><br/> | ||||
| <div class="container"> | ||||
|  <div class="col-md-5"></div> | ||||
|      <form action="SecurityQuestions.php" method="POST"> | ||||
|        <label> Set Password Recovery (Make sure you remember your answers) </label>  | ||||
|         <div class="mb-3"> | ||||
| 		<br/> | ||||
|             <label for="security_question1" class="form-label">Select Security Question 1</label> | ||||
|             <select class="form-select" id="security_question1" name="security_question1" required> | ||||
|                 <option value="">-- Select a question --</option> | ||||
|                 <option value="What is the name of your first pet?">What is the name of your first pet?</option> | ||||
|                 <option value="What is your mother's maiden name?">What is your mother's maiden name?</option> | ||||
|                 <option value="What is the name of the town where you were born?">What is the name of the town where you were born?</option> | ||||
|                 <option value="What was the name of your first best friend?">What was the name of your first best friend?</option> | ||||
|                 <option value="What is your favorite book?">What is your favorite book?</option> | ||||
|                 <option value="What was the make and model of your first car?">What was the make and model of your first car?</option> | ||||
|                 <!-- Add more options if needed --> | ||||
|             </select> | ||||
|         </div> | ||||
|         <div class="mb-3"> | ||||
|             <label for="security_answer1" class="form-label">Answer 1</label> | ||||
|             <input type="text" class="form-control" id="security_answer1" name="security_answer1" required> | ||||
|         </div> | ||||
| 		<br/> | ||||
|         <div class="mb-3"> | ||||
|             <label for="security_question2" class="form-label">Select Security Question 2</label> | ||||
|             <select class="form-select" id="security_question2" name="security_question2" required> | ||||
|                 <option value="">-- Select a question --</option> | ||||
|                 <option value="What was the name of your first school?">What was the name of your first school?</option> | ||||
|                 <option value="What is your favorite movie?">What is your favorite movie?</option> | ||||
|                 <option value="What was your childhood nickname?">What was your childhood nickname?</option> | ||||
|                 <option value="What is the name of your favorite teacher?">What is the name of your favorite teacher?</option> | ||||
|                 <option value="What street did you grow up on?">What street did you grow up on?</option> | ||||
|                 <option value="What is your favorite food?">What is your favorite food?</option> | ||||
|                 <!-- Add more options if needed --> | ||||
|             </select> | ||||
|         </div> | ||||
|         <div class="mb-3"> | ||||
|             <label for="security_answer2" class="form-label">Answer 2</label> | ||||
|             <input type="text" class="form-control" id="security_answer2" name="security_answer2" required> | ||||
|         </div> | ||||
| 
 | ||||
| 		<br/> | ||||
|         <button id="submit_recovery" type="submit" class="btn btn-primary">Save Answers</button> | ||||
|     </form> | ||||
| </div> | ||||
| 
 | ||||
| </body> | ||||
| </html> | ||||
|  | @ -151,10 +151,10 @@ echo "<div><a href='Courses.php?course=$url'> $header </a></div>"; | |||
|                                 $submitted_by = "$student_name ($submitter_student_number) for group $groupname "; | ||||
|                             } | ||||
| 
 | ||||
|                             $base_att1 = basename($att1); | ||||
|                             $base_att2 = basename($att2); | ||||
|                             $base_att3 = basename($att3); | ||||
|                             $base_att4 = basename($att4); | ||||
|                             $base_att1 = basename(rawurldecode($att1)); | ||||
|                             $base_att2 = basename(rawurldecode($att2)); | ||||
|                             $base_att3 = basename(rawurldecode($att3)); | ||||
|                             $base_att4 = basename(rawurldecode($att4)); | ||||
| 
 | ||||
|                             $full_link = "<a href='~\..\Download.php?file=$att1&attachment=1'>$base_att1</a>";  // prevent students from directly accessing their classmates' submissions
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,94 @@ | |||
| Contributed by Aya Boussouf 2025-05-19 | ||||
| 
 | ||||
| 
 | ||||
| # ---------------------- System Update & LAMP Stack Installation ---------------------- | ||||
| sudo apt update && sudo apt upgrade -y | ||||
| sudo apt install apache2 mysql-server php libapache2-mod-php php-mysql unzip git -y | ||||
| 
 | ||||
| # ---------------------- Start and Enable Apache & MySQL Services ---------------------- | ||||
| sudo systemctl start apache2 | ||||
| sudo systemctl enable apache2 | ||||
| 
 | ||||
| sudo systemctl start mysql | ||||
| sudo systemctl enable mysql | ||||
| 
 | ||||
| # ---------------------- Configure MySQL Root User ---------------------- | ||||
| sudo mysql | ||||
| ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root'; | ||||
| FLUSH PRIVILEGES; | ||||
| exit; | ||||
| 
 | ||||
| # ---------------------- Create LRR Database ---------------------- | ||||
| mysql -u root -p  | ||||
| CREATE DATABASE lrr; | ||||
| exit; | ||||
| 
 | ||||
| # ---------------------- Clone LRR Project Repository ---------------------- | ||||
| cd /var/www/html/ | ||||
| sudo git clone http://118.25.96.118:3000/mrlan/LRR.git | ||||
| sudo chown -R $USER:$USER /var/www/html/LRR | ||||
| 
 | ||||
| # ---------------------- Switch to Hui-Organize Branch ---------------------- | ||||
| cd /var/www/html/LRR | ||||
| git branch         | ||||
| git checkout -b Hui-Organize | ||||
| git pull origin Hui-Organize | ||||
| 
 | ||||
| # ---------------------- Import SQL Data into MySQL ---------------------- | ||||
| sudo mysql -u root -p lrr < /var/www/html/LRR/lrr_database.sql | ||||
| 
 | ||||
| # ---------------------- Create Submission Folder for Assignments ---------------------- | ||||
| cd /var/www/ | ||||
| sudo mkdir lrr_submission | ||||
| sudo chown -R www-data:www-data lrr_submission | ||||
| sudo chmod -R g+rw lrr_submission | ||||
| 
 | ||||
| # ---------------------- Configure Database Credentials in KeepItSafe.txt ---------------------- | ||||
| sudo nano /var/www/lrr_submission/KeepItSafe.txt | ||||
| # Add: root,root (username,password for MySQL connection) | ||||
| 
 | ||||
| 
 | ||||
| # ---------------------- Configure Apache Virtual Host for LRR ---------------------- | ||||
| sudo nano /etc/apache2/sites-available/LRR.conf | ||||
| <VirtualHost *:80> | ||||
|     ServerName localhost | ||||
|     DocumentRoot /var/www/html | ||||
|     ErrorLog ${APACHE_LOG_DIR}/error.log | ||||
|     CustomLog ${APACHE_LOG_DIR}/access.log combined | ||||
| </VirtualHost> | ||||
| 
 | ||||
| # ---------------------- Enable Apache Config and Rewrite Module ---------------------- | ||||
| sudo a2ensite LRR | ||||
| sudo a2enmod rewrite | ||||
| sudo systemctl reload apache2 | ||||
| 
 | ||||
| # ---------------------- Install Google Chrome (for Selenium Tests) ---------------------- | ||||
| cd ~/Downloads | ||||
| wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb | ||||
| sudo apt install ./google-chrome-stable_current_amd64.deb | ||||
| 
 | ||||
| # ---------------------- Install ChromeDriver ---------------------- | ||||
| wget https://storage.googleapis.com/chrome-for-testing-public/136.0.7103.92/linux64/chromedriver-linux64.zip | ||||
| unzip chromedriver-linux64.zip | ||||
| sudo mv chromedriver-linux64/chromedriver /usr/local/bin/ | ||||
| sudo chmod +x /usr/local/bin/chromedriver | ||||
| 
 | ||||
| # ---------------------- Install Python, pip and Virtual Environment ---------------------- | ||||
| sudo apt install python3 python3-pip -y | ||||
| sudo apt install python3-venv -y | ||||
| 
 | ||||
| # ---------------------- Create and Activate Virtual Environment for LRR ---------------------- | ||||
| cd /var/www/html/LRR | ||||
| python3 -m venv venv | ||||
| source venv/bin/activate | ||||
| 
 | ||||
| # ---------------------- Install Required Python Packages ---------------------- | ||||
| pip install selenium | ||||
| pip install pytest | ||||
| 
 | ||||
| # ---------------------- Run Selenium Tests ---------------------- | ||||
| cd test  | ||||
| # Make necessary edits in `conftest.py` and `test_lrr.py`. | ||||
| pytest -v SeleniumHui/test_lrr.py | ||||
| 
 | ||||
| 
 | ||||
|  | @ -30,7 +30,7 @@ if (isset($_SESSION["user_fullname"])) { | |||
| 		<legend>Sign in</legend> | ||||
| 		<input type="hidden" name="form_login" value="true"/> | ||||
| 		<label for="user_name" class="form-label">Account name</label> | ||||
| 		<input type="text" name="user" placeholder="Student Number / Email address" class="form-control" required="required" id="user_name" /> | ||||
| 		<input type="text" name="user" placeholder="Student Number / Email address" class="form-control" required="required" id="user_name" value="<?php echo isset($_SESSION['failed_login_user']) ? htmlspecialchars($_SESSION['failed_login_user']) : ''; ?>" /> | ||||
| 		<br> | ||||
| 		<label for="user_password" class="form-label">Password</label> | ||||
| 		<input type="password" class="form-control"  name="password" placeholder="password" required="required" id="user_password" /> | ||||
|  | @ -41,7 +41,7 @@ if (isset($_SESSION["user_fullname"])) { | |||
| 		<label class="form-text">Don't have an account yet?</label> <a href="signup.php" id="signup_link">Sign up</a> | ||||
| 
 | ||||
| 		<br> | ||||
| 		<label class="form-text">Forget your password?</label> <a href="recover_password.php">Recover</a> | ||||
| 		<label class="form-text">Forget your password?</label> <a id="goRecover" href="RecoverPassword.php">Recover</a> | ||||
| 
 | ||||
| 
 | ||||
| 		<?php | ||||
|  |  | |||
|  | @ -61,7 +61,7 @@ CREATE TABLE `courses_table` ( | |||
| 
 | ||||
| INSERT INTO `courses_table` (`Course_ID`, `Course_Name`, `Academic_Year`, `Faculty`, `Lecturer_User_ID`, `TA_User_ID`, `Course_Code`, `URL`, `Verify_New_Members`) VALUES | ||||
| (10, 'Software Engineering', '2018', 'Computing', 8, 0, 'CSC1234', 'CSC12342018', '1'), | ||||
| (11, 'Project Management', '2019', 'Computing', 8, 0, 'P.M2019', 'P.M20192019', '0'), | ||||
| (11, 'Project Management', '2024', 'Computing', 8, 0, 'CSC1111', 'CSC11112024', '0'), | ||||
| (12, 'Ashly Course Testing', '2020', 'Testing', 8, 0, 'Teecloudy', 'Teecloudy2020', '1'); | ||||
| 
 | ||||
| -- -------------------------------------------------------- | ||||
|  | @ -136,7 +136,7 @@ INSERT INTO `course_students_table` (`Course_ID`, `Student_ID`, `ID`, `Status`) | |||
| (10, '201825800050', 13, 'Joined'), | ||||
| (10, '201825800054', 14, 'Joined'), | ||||
| (12, '201632120150', 15, 'Joined'), | ||||
| (12, '2016321201502', 16, 'Joined'), | ||||
| (12, '201632120150', 16, 'Joined'), | ||||
| (12, '201825800050', 17, 'Joined'); | ||||
| 
 | ||||
| -- -------------------------------------------------------- | ||||
|  | @ -200,7 +200,7 @@ CREATE TABLE `lab_reports_table` ( | |||
| 
 | ||||
| INSERT INTO `lab_reports_table` (`Lab_Report_ID`, `Course_ID`, `Posted_Date`, `Deadline`, `Instructions`, `Title`, `Attachment_link_1`, `Attachment_link_2`, `Attachment_link_3`, `Attachment_link_4`, `Marks`, `Type`) VALUES | ||||
| (1, 10, '2019-01-11 16:52', '2019-02-11 17:00', 'Description of the lab....', 'Reading 1', '700IMPORTANT WORDS.txt', '', '', '', '4', 'Individual'), | ||||
| (2, 10, '2019-01-17 11:12', '2019-01-25 23:59', 'Read this paper http://sunnyday.mit.edu/16.355/budgen-david.pdf', 'Reading 2', '586LRR-Test-caseS.pdf', '', '', '', '6', 'Individual'), | ||||
| (2, 10, '2024-09-29 11:12', '2025-07-30 23:59', 'Read this paper http://sunnyday.mit.edu/16.355/budgen-david.pdf', 'Reading 2', '586LRR-Test-caseS.pdf', '', '', '', '6', 'Individual'), | ||||
| (3, 12, '2020-04-05 02:48', '2020-04-12 ', 'Do this assignment in time for testing', 'First Assignment Testing', '', '', '', '', '3', 'Group'), | ||||
| (4, 12, '2020-04-05 05:36', '2020-04-06 ', 'We are testing to see if the instructor can be able to modify the work', 'Second Assignment Testing', '', '', '', '', '3', 'Individual'), | ||||
| (5, 12, '2020-04-05 05:51', '2020-04-08 ', 'ASQDASDASCDD', 'Third Assignment Testingas', '', '', '', '', '3', 'Individual'), | ||||
|  | @ -235,7 +235,7 @@ CREATE TABLE `lab_report_submissions` ( | |||
| -- | ||||
| 
 | ||||
| INSERT INTO `lab_report_submissions` (`Submission_ID`, `Submission_Date`, `Lab_Report_ID`, `Student_id`, `Course_Group_id`, `Attachment1`, `Notes`, `Attachment2`, `Attachment3`, `Attachment4`, `Marks`, `Status`, `Title`, `Visibility`, `Remarking_Reason`) VALUES | ||||
| (1, '2019-01-17 00:00:00', 1, '201825800050', 0, 'Reading list.txt', '-', '', '', '', 5, 'Marked', 'Reading 1 submission', 'Public', ''), | ||||
| (1, '2019-01-17 00:00:00', 1, '201825800050', 0, 'Reading list.txt', '-', '', '', '', NULL, 'Pending', 'Reading 1 submission', 'Public', ''), | ||||
| (5, '2019-01-21 08:31:00', 2, '201825800050', 0, 'Trial Balance.txt', ' - @2019-01-21 09:35 : Sorry I missed some details from your report', 'Boorka.jpg', '', '', 6, 'Marked', 'Submission x', 'Private', ''), | ||||
| (30, '2020-04-06 23:18:00', 3, '0', 31, '/2016321201502/First Assignment Testing/UR Diagram.pdf', '<br>@2020-04-06 23:19 : ', '', '', '', 3, 'Marked', 'First Assignment Testing', 'Private', ''); | ||||
| 
 | ||||
|  | @ -259,7 +259,11 @@ INSERT INTO `students_data` (`ID`, `Student_ID`, `Passport_Number`) VALUES | |||
| (1, '201825800054', 'LJ7951632'), | ||||
| (2, '201825800050', 'P00581929'), | ||||
| (3, '201632120150', 'FN524516'), | ||||
| (4, '11', '11'); | ||||
| (4, '202400000001', 'NA'), | ||||
| (5,'201932130101',''), | ||||
| (6,'201920781742',''); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| -- -------------------------------------------------------- | ||||
| 
 | ||||
|  | @ -268,7 +272,7 @@ INSERT INTO `students_data` (`ID`, `Student_ID`, `Passport_Number`) VALUES | |||
| -- | ||||
| 
 | ||||
| CREATE TABLE `users_table` ( | ||||
|   `User_ID` int(11) NOT NULL, | ||||
|   `User_ID` int(11) NOT NULL AUTO_INCREMENT, | ||||
|   `Email` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL, | ||||
|   `Password` varchar(250) CHARACTER SET utf8 DEFAULT NULL, | ||||
|   `HashPassword` varchar(250) COLLATE utf8mb4_bin NOT NULL, | ||||
|  | @ -276,7 +280,8 @@ CREATE TABLE `users_table` ( | |||
|   `UserType` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL, | ||||
|   `Student_ID` varchar(500) COLLATE utf8mb4_bin DEFAULT NULL, | ||||
|   `Passport_Number` varchar(50) COLLATE utf8mb4_bin DEFAULT NULL, | ||||
|   `Status` varchar(30) COLLATE utf8mb4_bin NOT NULL DEFAULT 'Active' | ||||
|   `Status` varchar(30) COLLATE utf8mb4_bin NOT NULL DEFAULT 'Active', | ||||
|    PRIMARY KEY (`User_ID`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; | ||||
| 
 | ||||
| -- | ||||
|  | @ -284,16 +289,37 @@ CREATE TABLE `users_table` ( | |||
| -- | ||||
| 
 | ||||
| INSERT INTO `users_table` (`User_ID`, `Email`, `Password`, `HashPassword`, `Full_Name`, `UserType`, `Student_ID`, `Passport_Number`, `Status`) VALUES | ||||
| (3, 'admin@qq.com', '123', '', 'Kamal', 'Admin', '0', NULL, 'Active'), | ||||
| (8, 'lanhui@qq.com', '1234', '', 'Lanhui', 'Lecturer', NULL, '123', 'Active'), | ||||
| (9, 'mohamed@qq.com', '123', '', 'Mohamed', 'Student', '201825800050', 'P00581929', 'Active'), | ||||
| (3, 'admin@qq.com', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', 'Kamal', 'Admin', '0', NULL, 'Active'), | ||||
| (7, 'peter@qq.com', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', 'Peter', 'Lecturer', NULL, '123', 'Active'), | ||||
| (8, 'lanhui@qq.com', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', 'Lanhui', 'Lecturer', NULL, '123', 'Active'), | ||||
| (9, 'mohamed@qq.com', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', 'Mohamed', 'Student', '201825800050', 'P00581929', 'Active'), | ||||
| (10, 'mark@qq.com', '123', '', 'Mark ', 'TA', NULL, '123', 'Active'), | ||||
| (11, 'john@qq.com', '123', '', 'John', 'TA', NULL, '123', 'Active'), | ||||
| (12, 'mehdi@qq.com', '123', '', 'El-mehdi Houzi', 'Student', '201825800054', 'LJ7951632', 'Active'), | ||||
| (17, 'teecloudy@qq.com', '$2y$10$8WqSK7QI.3YCb2yoclqutOxyGxojncUvzhqLcE8zjlSvjBdcIQ18O', '', 'Ashly Tafadzwa Dhani', 'Student', '201632120150', NULL, 'Active'), | ||||
| (18, 'ashly@qq.com', 'Testing2', '', 'Ashly 2 Testing', 'Student', '2016321201502', NULL, 'Active'), | ||||
| (19, '11@11.11', 'dfdf', '760a8f4f392f1f6bc3ecb118365c6cd039b59fdce96122897d5157970d9c9c129bd73b3c402dbeedd8fe94d319df7bd7de0025c22839fec06631a025ec1e0e69', '11', 'Student', '11', '', 'Active'); | ||||
| (19, '11@11.11', 'dfdf', '760a8f4f392f1f6bc3ecb118365c6cd039b59fdce96122897d5157970d9c9c129bd73b3c402dbeedd8fe94d319df7bd7de0025c22839fec06631a025ec1e0e69', '11', 'Student', '11', '', 'Active'), | ||||
| (20,'goodstd@qq.com','$2y$10$RXIjONOK.mw74pSxPrsnGuccQsFq4O4.e71vaxfGHHhtzHREtfqkG','','Good Std','Student','201932130101',NULL,'Active'),(21,'goodstd2@qq.com','$2y$10$kmqrGuZd7hCiiaHFDQr2vObpD7BgEnCKlgQ/EcLHYnsQenMbNKcHy','','Good Std2','Student','201920781742',NULL,'Active'); | ||||
| 
 | ||||
| CREATE TABLE `password_recovery_security_questions` ( | ||||
|   `user_id` int NOT NULL, | ||||
|   `user_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, | ||||
|   `student_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, | ||||
|   `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, | ||||
|   `question1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, | ||||
|   `answer1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, | ||||
|   `question2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, | ||||
|   `answer2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, | ||||
|   PRIMARY KEY (`user_id`), | ||||
|   CONSTRAINT `password_recovery_security_questions_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_table` (`User_ID`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; | ||||
| 
 | ||||
| INSERT INTO `password_recovery_security_questions` VALUES  | ||||
| (3,'Admin',NULL,'admin@qq.com','What is the name of your first pet?','mimi','What was the name of your first school?','zjnu'), | ||||
| (7,'Lecturer',NULL,'peter@qq.com','What was the name of your first best friend?','chen','What is your favorite food?','hotpot'), | ||||
| (8,'Lecturer',NULL,'lanhui@qq.com','What is the name of the town where you were born?','jinhua','What is your favorite movie?','titanic'), | ||||
| (9,'Student','201825800050','mohamed@qq.com','What was the make and model of your first car?','audi','What is the name of your favorite teacher?','chen'), | ||||
| (21,'Student','201920781742','goodstd2@qq.com','What is the name of the town where you were born?','wenzhou','What is your favorite food?','hotpot'); | ||||
| -- | ||||
| -- Indexes for dumped tables | ||||
| -- | ||||
|  | @ -347,12 +373,6 @@ ALTER TABLE `lab_report_submissions` | |||
| ALTER TABLE `students_data` | ||||
|   ADD PRIMARY KEY (`ID`); | ||||
| 
 | ||||
| -- | ||||
| -- Indexes for table `users_table` | ||||
| -- | ||||
| ALTER TABLE `users_table` | ||||
|   ADD PRIMARY KEY (`User_ID`); | ||||
| 
 | ||||
| -- | ||||
| -- AUTO_INCREMENT for dumped tables | ||||
| -- | ||||
|  | @ -410,12 +430,7 @@ ALTER TABLE `students_data` | |||
| -- | ||||
| ALTER TABLE courses_table | ||||
| MODIFY Course_Name varchar(500); | ||||
| -- | ||||
| -- AUTO_INCREMENT for table `users_table` | ||||
| -- | ||||
| ALTER TABLE `users_table` | ||||
|   MODIFY `User_ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=20; | ||||
| COMMIT; | ||||
| 
 | ||||
| 
 | ||||
| /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; | ||||
| /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; | ||||
|  |  | |||
|  | @ -22,10 +22,10 @@ include 'Header.php'; | |||
| 		<input type="hidden" name="form_signup" value="true" /> | ||||
| 
 | ||||
| 		Full Name | ||||
| 		<input type="text" name="fullname" placeholder="Your full name" class="form-control" value="<?php echo $_SESSION['user_fullname']; ?>" required="required" id="full_name"/> <br> | ||||
| 
 | ||||
| 		<input type="text" name="fullname" placeholder="Your full name" class="form-control" value="<?php echo isset($_SESSION['user_fullname_temp']) ? $_SESSION['user_fullname_temp'] : ''; ?>" required="required" id="full_name"/> <br> | ||||
| 		 | ||||
| 		Student ID | ||||
| 		<input type="text" name="user_student_id" placeholder="Entre your student ID" class="form-control" value="<?php echo $_SESSION['user_student_id']; ?>" required="required" id="student_id"> <br> | ||||
| 		<input type="text" name="user_student_id" placeholder="Entre your student ID" class="form-control" value="<?php  echo isset($_SESSION['user_student_id_1']) ? $_SESSION['user_student_id_temp'] : ''; ?>" required="required" id="student_id"> <br> | ||||
| 
 | ||||
| 		Email | ||||
| 		<input type="text" name="email" placeholder="Email" class="form-control" value="<?php echo $_SESSION['user_email']; ?>" required="required" id="email" /> <br> | ||||
|  |  | |||
|  | @ -0,0 +1,37 @@ | |||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.ui import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| from selenium.common.exceptions import NoSuchElementException, UnexpectedAlertPresentException | ||||
| 
 | ||||
| 
 | ||||
| def login(driver, url, username, password): | ||||
|     try: | ||||
|         driver.get(url) | ||||
| 
 | ||||
|         # Fill in the login form | ||||
|         user_input = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "user_name")) | ||||
|         ) | ||||
|         user_input.send_keys(username) | ||||
| 
 | ||||
|         password_input = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "user_password")) | ||||
|         ) | ||||
|         password_input.send_keys(password) | ||||
| 
 | ||||
|         # Click the login button | ||||
|         login_button = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "login_btn")) | ||||
|         ) | ||||
|         login_button.click() | ||||
|     except (NoSuchElementException, UnexpectedAlertPresentException) as e: | ||||
|         return f"Error: {str(e)}" | ||||
| 
 | ||||
| 
 | ||||
| def logout(driver): | ||||
|     logout_button = WebDriverWait(driver, 10).until( | ||||
|         EC.element_to_be_clickable( | ||||
|             (By.XPATH, "//a[contains(@class, 'nav-link') and contains(@href, 'logout.php')]") | ||||
|         ) | ||||
|     ) | ||||
|     logout_button.click() | ||||
|  | @ -0,0 +1,156 @@ | |||
| from helper import login, logout | ||||
| import time | ||||
| import pytest | ||||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.wait import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| from selenium.webdriver.support.ui import Select | ||||
| 
 | ||||
| def test_attempt_recovery_with_unanswered_security_questions(driver, url, restore_database): | ||||
|     # Student goodstd@qq.com with no answered questions | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|      | ||||
|     elem = driver.find_element(By.ID, 'goRecover') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys("goodstd@qq.com") | ||||
|     elem = driver.find_element(By.ID, 'rec') | ||||
|     elem.click() | ||||
|      | ||||
|     wait = WebDriverWait(driver, 10) | ||||
|     alert_elem = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "alert-warning"))) | ||||
|     assert "no security questions found for this user." in alert_elem.text.lower()  | ||||
|   | ||||
|     driver.quit() | ||||
| 
 | ||||
| def test_set_security_questions(driver, url, restore_database): | ||||
|     # Student goodstd@qq.com logs in | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|     login(driver, url, 'goodstd@qq.com', '[123Abc]') | ||||
|     question1 = driver.find_element(By.ID, 'security_question1') | ||||
|     question2 = driver.find_element(By.ID, 'security_question2') | ||||
|     select_question1 = Select(question1) | ||||
|     select_question1.select_by_index(1) | ||||
|     select_question2 = Select(question2) | ||||
|     select_question2.select_by_index(2) | ||||
|     answer1 = driver.find_element(By.ID, 'security_answer1') | ||||
|     answer1.send_keys("mImI") | ||||
|     answer2 = driver.find_element(By.ID, 'security_answer2') | ||||
|     answer2.send_keys("TitaNic") | ||||
|     submit_button = driver.find_element(By.ID, 'submit_recovery') | ||||
|     submit_button.click()  | ||||
|      | ||||
|     # Assertion: Check if password recovery confirmation or success message appears | ||||
|     WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'alertgood'))) | ||||
|     recovery_success = driver.find_element(By.ID, 'alertgood') | ||||
|     assert recovery_success.is_displayed(), "Password recovery failed or confirmation message not displayed." | ||||
|      | ||||
|     logout(driver) | ||||
|      | ||||
|     #Log in Student account | ||||
|     login(driver, url, 'goodstd@qq.com', '[123Abc]') | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     assert 'Student ID' in elems[0].text | ||||
|     assert 'Good Std' in elems[0].text  | ||||
|      | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_password_recover_wrong_answers(driver, url, restore_database): | ||||
|     # Student goodstd2@qq.com recover password --> wrong answers | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|     elem = driver.find_element(By.ID, 'goRecover') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys("goodstd2@qq.com") | ||||
|     elem = driver.find_element(By.ID, 'rec') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'answer1') | ||||
|     elem.send_keys("wrong") | ||||
|     elem = driver.find_element(By.NAME, 'answer2') | ||||
|     elem.send_keys("wrong") | ||||
|     elem = driver.find_element(By.ID, 'sub') | ||||
|     elem.click() | ||||
|      | ||||
|     driver.quit() | ||||
|      | ||||
| def test_recover_password_with_weak_password(driver, url, restore_database): | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|     elem = driver.find_element(By.ID, 'goRecover') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys("goodstd2@qq.com") | ||||
|     elem = driver.find_element(By.ID, 'rec') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'answer1') | ||||
|     elem.send_keys("Wenzhou") | ||||
|     elem = driver.find_element(By.NAME, 'answer2') | ||||
|     elem.send_keys("HotPot") | ||||
|     elem = driver.find_element(By.ID, 'sub') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'new_password') | ||||
|     elem.send_keys("123") | ||||
|     elem = driver.find_element(By.NAME, 'confirm_password') | ||||
|     elem.send_keys("123") | ||||
|     elem = driver.find_element(By.ID, "butt") | ||||
|     elem.click() | ||||
|      | ||||
|     wait = WebDriverWait(driver, 10) | ||||
|     alert_elem = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "alert-danger"))) | ||||
|     assert "password must be at least 8 characters long and include uppercase and lowercase letters, numbers, and special characters." in alert_elem.text.lower()  | ||||
|      | ||||
|     driver.quit() | ||||
| 
 | ||||
| def test_recover_password_successfully(driver, url, restore_database): | ||||
|     # Student goodstd2@qq.com recover password ---> correct answers | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|     elem = driver.find_element(By.ID, 'goRecover') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys("goodstd2@qq.com") | ||||
|     elem = driver.find_element(By.ID, 'rec') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'answer1') | ||||
|     elem.send_keys("wenzhou") | ||||
|     elem = driver.find_element(By.NAME, 'answer2') | ||||
|     elem.send_keys("hotpot") | ||||
|     elem = driver.find_element(By.ID, 'sub') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'new_password') | ||||
|     elem.send_keys("123Abc!!") | ||||
|     elem = driver.find_element(By.NAME, 'confirm_password') | ||||
|     elem.send_keys("123Abc!!") | ||||
|     elem = driver.find_element(By.ID, "butt") | ||||
|     elem.click() | ||||
|      | ||||
|     #Log in Student account | ||||
|     login(driver, url, 'goodstd2@qq.com', '123Abc!!') | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     assert 'Student ID' in elems[0].text | ||||
|     assert 'Good Std2' in elems[0].text     | ||||
|     driver.quit() | ||||
| 
 | ||||
| def test_recovery_invalid_user_cannot_recover(driver, url, restore_database): | ||||
|     # Unrecognizable user cannot recover | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|     elem = driver.find_element(By.ID, 'goRecover') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys("goodstd3@qq.com") | ||||
|     elem = driver.find_element(By.ID, 'rec') | ||||
|     elem.click() | ||||
|      | ||||
|     wait = WebDriverWait(driver, 10) | ||||
|     alert_elem = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "alert-danger"))) | ||||
|     assert "email address is not recognized." in alert_elem.text.lower() | ||||
|     | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,46 @@ | |||
| Sign-Up Automation Test Script | ||||
| Overview | ||||
| This script automates the sign-up process for a web application using Selenium WebDriver. It tests whether form values are retained correctly if the initial sign-up attempt fails and requires modification of the student ID before resubmission. | ||||
| 
 | ||||
| Prerequisites | ||||
| Python 3 | ||||
| Selenium library | ||||
| Chrome WebDriver | ||||
| A running instance of the web application on http://localhost:8080 | ||||
| 
 | ||||
| Configuration | ||||
| Web Application URL: Make sure the web application is running at http://localhost:8080. Adjust the URL in the script if necessary. | ||||
| 
 | ||||
| Update Element Locators: Ensure the IDs used in the script (signup_link, signup_form, full_name, student_id, email, password1, password2, signup_btn) match those in your web application. | ||||
| 
 | ||||
| Run the script: | ||||
| 
 | ||||
| Script Logic | ||||
| 
 | ||||
| Open the Login Page: The script navigates to the login page of the web application. | ||||
| Click the "Sign Up" Link: It waits for the "Sign Up" link to appear and clicks it to navigate to the sign-up page. | ||||
| Fill Out the Sign-Up Form: It fills out the form fields (Full Name, Student ID, Email, Password). | ||||
| Submit the Form: It submits the form and waits for the result. | ||||
| Check for Sign-Up Failure: If sign-up fails, it checks if form values are retained. | ||||
| Modify Student ID: If the form values are retained, it modifies the student ID and resubmits the form. | ||||
| Verify Retained Values: It verifies if other fields retain their values after modifying the student ID. | ||||
| Print Retained Values: If the second attempt is successful, it prints the retained form values. | ||||
| Close the Browser: The browser is closed at the end of the script execution. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| The script provides the following output: | ||||
| 
 | ||||
| Sign-Up Successful: Indicates the sign-up was successful on the first attempt. | ||||
| Sign-Up Failed: Indicates the sign-up failed on the first attempt and checks for retained values. | ||||
| Second Sign-Up Attempt Successful: Indicates the second sign-up attempt was successful and prints the retained values. | ||||
| Second Sign-Up Attempt Failed: Indicates the second sign-up attempt also failed, suggesting further investigation is needed. | ||||
| Notes | ||||
| Form Field IDs: Ensure the IDs used in the script match those in your web application. | ||||
| Password Fields: The script intentionally does not print password fields for security reasons. | ||||
| Adjust Wait Times: Modify the wait times as needed depending on your application's response times. | ||||
| Troubleshooting | ||||
| Element Not Found: Verify the element IDs and update them in the script. | ||||
| WebDriver Errors: Ensure the Chrome WebDriver is installed and matches your Chrome browser version. | ||||
| Connection Errors: Ensure the web application is running and accessible at the specified URL. | ||||
| Contributing | ||||
|  | @ -0,0 +1,88 @@ | |||
| import time  # Import time module for waiting | ||||
| from selenium import webdriver | ||||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.ui import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| 
 | ||||
| # New instance of the Chrome driver | ||||
| driver = webdriver.Chrome() | ||||
| 
 | ||||
| try: | ||||
|     # Step 1: Open the login page | ||||
|     driver.get("http://localhost:8080/lrr/lrr/admin.php")  # Replace with your actual login page URL | ||||
| 
 | ||||
|     # Step 2: Wait for the login page to fully load and locate the "Sign Up" link | ||||
|     sign_up_link = WebDriverWait(driver, 10).until( | ||||
|         EC.presence_of_element_located((By.ID, "signup_link")) | ||||
|     ) | ||||
|      | ||||
|     # Step 3: Click the "Sign Up" link to navigate to the sign-up page | ||||
|     sign_up_link.click() | ||||
| 
 | ||||
|     # Step 4: Wait for the sign-up page to fully load | ||||
|     WebDriverWait(driver, 10).until( | ||||
|         EC.presence_of_element_located((By.ID, "signup_form")) | ||||
|     ) | ||||
| 
 | ||||
|     # Step 5: Fill out the sign-up form | ||||
|     driver.find_element(By.ID, "full_name").send_keys("John Doe") | ||||
|     driver.find_element(By.ID, "student_id").send_keys("12345678") | ||||
|     driver.find_element(By.ID, "email").send_keys("john.doe@example.com") | ||||
|     driver.find_element(By.ID, "password1").send_keys("Password123!") | ||||
|     driver.find_element(By.ID, "password2").send_keys("Password123!") | ||||
| 
 | ||||
|     # Step 6: Submit the sign-up form | ||||
|     driver.find_element(By.ID, "signup_btn").click() | ||||
| 
 | ||||
|     # Step 7: Wait for the sign-up result | ||||
|     WebDriverWait(driver, 10).until( | ||||
|         EC.presence_of_element_located((By.TAG_NAME, "body")) | ||||
|     ) | ||||
| 
 | ||||
|     # Check if sign-up failed | ||||
|     if "alert-danger" in driver.page_source: | ||||
|         print("Sign-up failed. Checking if form values are retained...") | ||||
| 
 | ||||
|         # Wait for a few seconds (adjust as needed) | ||||
|         time.sleep(3) | ||||
| 
 | ||||
|         # Modify the student ID again | ||||
|         driver.find_element(By.ID, "student_id").clear() | ||||
|         driver.find_element(By.ID, "student_id").send_keys("87654321") | ||||
| 
 | ||||
|         # Verify if the other fields retain their values | ||||
|         assert driver.find_element(By.ID, "full_name").get_attribute("value") == "John Doe" | ||||
|         assert driver.find_element(By.ID, "email").get_attribute("value") == "john.doe@example.com" | ||||
|         assert driver.find_element(By.ID, "password1").get_attribute("value") == "" | ||||
|         assert driver.find_element(By.ID, "password2").get_attribute("value") == "" | ||||
| 
 | ||||
|         # Resubmit the form | ||||
|         driver.find_element(By.ID, "signup_btn").click() | ||||
| 
 | ||||
|         # Wait for the result again | ||||
|         WebDriverWait(driver, 10).until( | ||||
|             EC.presence_of_element_located((By.TAG_NAME, "body")) | ||||
|         ) | ||||
| 
 | ||||
|         # Check for success or failure after second attempt | ||||
|         if "alert-danger" in driver.page_source: | ||||
|             print("Second sign-up attempt failed. Further investigation needed.") | ||||
| 
 | ||||
| 
 | ||||
|             # Print the retained values | ||||
|             print("Retained form values after second attempt:") | ||||
|             print("Full Name:", driver.find_element(By.ID, "full_name").get_attribute("value")) | ||||
|             print("Email:", driver.find_element(By.ID, "email").get_attribute("value")) | ||||
|             # Password fields might be intentionally cleared, so they won't be printed here | ||||
|             print("Modified Student ID:", driver.find_element(By.ID, "student_id").get_attribute("value")) | ||||
|              | ||||
|         else: | ||||
|             print("Second sign-up attempt successful!") | ||||
|     else: | ||||
|         print("Sign-up successful!") | ||||
| 
 | ||||
|          | ||||
| 
 | ||||
| finally: | ||||
|     # Close the browser | ||||
|     driver.quit() | ||||
|  | @ -0,0 +1,6 @@ | |||
| Sign-up failed. Checking if form values are retained... | ||||
| Second sign-up attempt failed. Further investigation needed. | ||||
| Retained form values after second attempt: | ||||
| Full Name: John Doe | ||||
| Email: john.doe@example.com | ||||
| Modified Student ID: 87654321 | ||||
|  | @ -0,0 +1,37 @@ | |||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.ui import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| from selenium.common.exceptions import NoSuchElementException, UnexpectedAlertPresentException | ||||
| 
 | ||||
| 
 | ||||
| def login(driver, url, username, password): | ||||
|     try: | ||||
|         driver.get(url) | ||||
| 
 | ||||
|         # Fill in the login form | ||||
|         user_input = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "user_name")) | ||||
|         ) | ||||
|         user_input.send_keys(username) | ||||
| 
 | ||||
|         password_input = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "user_password")) | ||||
|         ) | ||||
|         password_input.send_keys(password) | ||||
| 
 | ||||
|         # Click the login button | ||||
|         login_button = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "login_btn")) | ||||
|         ) | ||||
|         login_button.click() | ||||
|     except (NoSuchElementException, UnexpectedAlertPresentException) as e: | ||||
|         return f"Error: {str(e)}" | ||||
| 
 | ||||
| 
 | ||||
| def logout(driver): | ||||
|     logout_button = WebDriverWait(driver, 10).until( | ||||
|         EC.element_to_be_clickable( | ||||
|             (By.XPATH, "//a[contains(@class, 'nav-link') and contains(@href, 'logout.php')]") | ||||
|         ) | ||||
|     ) | ||||
|     logout_button.click() | ||||
|  | @ -0,0 +1,364 @@ | |||
| from helper import login, logout | ||||
| import time | ||||
| import pytest | ||||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.wait import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| 
 | ||||
| 
 | ||||
| def test_admin_can_create_lecturer_account(driver, url, admin_username, admin_password, restore_database): | ||||
|     # Administrator (admin@qq.com, password 123) logs in | ||||
|     driver.maximize_window() | ||||
|     login(driver, url, admin_username, admin_password) | ||||
| 
 | ||||
|     # Create a Lecturer account for Mr Lan (mrlan@qq.com, password [123Abc!]) | ||||
|     tab = driver.find_element(By.ID, 'tab_ins_accounts') | ||||
|     tab.click() | ||||
|     elem = driver.find_element(By.NAME, 'fullname') | ||||
|     elem.send_keys('Mr Lan') | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys('mrlan@qq.com') | ||||
|     elem = driver.find_element(By.NAME, 'password') | ||||
|     elem.send_keys('123Abc!!') | ||||
|     radio_button = driver.find_element(By.NAME, 'type') | ||||
|     radio_button.click() | ||||
|     button = driver.find_element(By.NAME, 'create_btn') | ||||
|     button.click() | ||||
| 
 | ||||
|     # Log out Admin account | ||||
|     logout(driver) | ||||
| 
 | ||||
|     # Log in Lecturer account | ||||
|     login(driver, url, 'mrlan@qq.com', '123Abc!!') | ||||
|     #elems = driver.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     #assert '(Lecturer)' in elems[0].text | ||||
|     #assert 'Mr Lan' in elems[0].text | ||||
|     wait = WebDriverWait(driver, 10) | ||||
|     wait.until(EC.url_contains('SecurityQuestions.php')) | ||||
|      | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_lecturer_can_create_course(driver, url, restore_database): | ||||
|     # Lecturer lanhui@qq.com logs in | ||||
|     driver.maximize_window() | ||||
|     login(driver, url, 'lanhui@qq.com', '123') | ||||
| 
 | ||||
|     # Create a course called CSC1001 Advanced Software Engineering, 2024 | ||||
|     elem = driver.find_element(By.NAME, 'name') | ||||
|     elem.send_keys('Advanced Software Engineering') | ||||
|     elem = driver.find_element(By.NAME, 'code') | ||||
|     elem.send_keys('CSC1001') | ||||
|     elem = driver.find_element(By.NAME, 'academic') | ||||
|     elem.send_keys('2004') | ||||
|     elem = driver.find_element(By.NAME, 'faculty') | ||||
|     elem.send_keys('School of Computer Science and Technology') | ||||
|     elem = driver.find_element(By.CLASS_NAME, 'btn-primary') | ||||
|     elem.click() | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'btn-default') | ||||
|     last_elem = elems[-1] | ||||
|     assert 'Advanced Software Engineering' in last_elem.text | ||||
|     assert '(CSC1001)' in last_elem.text | ||||
| 
 | ||||
|     # Logout | ||||
|     logout(driver) | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_lecturer_can_post_assignment(driver, url, restore_database): | ||||
|     # Lecturer lanhui@qq.com logs in | ||||
|     driver.maximize_window() | ||||
|     login(driver, url, 'lanhui@qq.com', '123') | ||||
| 
 | ||||
|     # Create an assignment called Take-home quiz 1 for course (CSC1111) - Project Management | ||||
|     elem = WebDriverWait(driver, 10).until( | ||||
|         EC.element_to_be_clickable((By.XPATH, '//div[@class="col-md-8"]/a[1]/div')) | ||||
|     ) | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'deadlinedate') | ||||
|     elem.send_keys('002025/05/30') | ||||
|     elem = driver.find_element(By.NAME, 'deadlinetime') | ||||
|     elem.send_keys('23:59') | ||||
|     elem = driver.find_element(By.NAME, 'title') | ||||
|     elem.send_keys('Take-home quiz 1') | ||||
|     elem = driver.find_element(By.NAME, 'instructions') | ||||
|     elem.send_keys('This is a closed-book quiz.') | ||||
|     elem = driver.find_element(By.NAME, 'marks') | ||||
|     elem.send_keys('10') | ||||
|     radio_button = driver.find_element(By.NAME, 'type') | ||||
|     radio_button.click() | ||||
|     elem = driver.find_element(By.CLASS_NAME, 'btn-primary') | ||||
|     elem.click() | ||||
| 
 | ||||
|     # Check if the assignment has been successfully posted | ||||
|     elem = driver.find_element(By.CLASS_NAME, 'card-title') | ||||
|     assert 'Take-home quiz 1 (10 Marks, Individual)' in elem.text | ||||
|     elem = driver.find_element(By.CLASS_NAME, 'text-muted') | ||||
|     assert 'Deadline: 2025-05-30' in elem.text | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_lecturer_can_add_student_numbers(driver, url, restore_database): | ||||
|     # Lecturer lanhui@qq.com logs in | ||||
|     driver.maximize_window() | ||||
|     login(driver, url, 'lanhui@qq.com', '123') | ||||
| 
 | ||||
|     # Add ASE student numbers | ||||
|     student_numbers = ''' | ||||
|     202420781739 | ||||
|     202420781740 | ||||
|     202420781741 | ||||
|     202420781742 | ||||
|     202420781743 | ||||
|     202420781745 | ||||
|     202420581366 | ||||
|     202420581368 | ||||
|     202420581369 | ||||
|     202420581370 | ||||
|     202420581372 | ||||
|     202420581373 | ||||
|     202420581374 | ||||
|     202420581376 | ||||
|     202420581378 | ||||
|     202420581381 | ||||
|     ''' | ||||
|     elem = driver.find_element(By.ID, 'admin_tab') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'users') | ||||
|     elem.send_keys(student_numbers) | ||||
|     elem = driver.find_element(By.ID, 'register_btn') | ||||
|     elem.click() | ||||
| 
 | ||||
|     elems = driver.find_elements(By.CSS_SELECTOR, 'p') | ||||
|     added = 0 | ||||
|     student_lst = [number.strip() for number in student_numbers.strip().split('\n')] | ||||
|     print(student_lst) | ||||
|     for student_no in student_lst: | ||||
|         for elem in elems: | ||||
|             if student_no in elem.text and 'added' in elem.text: | ||||
|                 added += 1 | ||||
|                 break | ||||
|     assert added == len(student_lst) | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_student_with_valid_student_number_can_sign_up(driver, url, restore_database): | ||||
|     # Student with recognizable student number 202400000001 can sign up an account | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|     elem = driver.find_element(By.ID, 'signup_link') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'fullname') | ||||
|     elem.send_keys('Good Student') | ||||
|     elem = driver.find_element(By.NAME, 'user_student_id') | ||||
|     elem.send_keys('202400000001') | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys('goodstudent@qq.com') | ||||
|     elem = driver.find_element(By.NAME, 'password') | ||||
|     elem.send_keys('[123Abc]') | ||||
|     elem = driver.find_element(By.NAME, 'confirmpassword') | ||||
|     elem.send_keys('[123Abc]') | ||||
|     elem = driver.find_element(By.ID, 'signup_btn') | ||||
|     elem.click() | ||||
|     driver.get(url + 'logout.php') | ||||
| 
 | ||||
|     # Log in Student account | ||||
|     login(driver, url, '202400000001', '[123Abc]') | ||||
|     #elems = driver.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     #assert 'Student ID' in elems[0].text | ||||
|     #assert 'Good Student' in elems[0].text | ||||
|     wait = WebDriverWait(driver, 10)     | ||||
|     wait.until(EC.url_contains('SecurityQuestions.php')) | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_student_with_invalid_student_number_cannot_sign_up(driver, url, restore_database): | ||||
|     # Student with unrecognizable student number cannot sign up an account | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|     elem = driver.find_element(By.ID, 'signup_link') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'fullname') | ||||
|     elem.send_keys('Good Student') | ||||
|     elem = driver.find_element(By.NAME, 'user_student_id') | ||||
|     elem.send_keys('202400000002') | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys('goodstudent@qq.com') | ||||
|     elem = driver.find_element(By.NAME, 'password') | ||||
|     elem.send_keys('[123Abc]') | ||||
|     elem = driver.find_element(By.NAME, 'confirmpassword') | ||||
|     elem.send_keys('[123Abc]') | ||||
|     elem = driver.find_element(By.ID, 'signup_btn') | ||||
|     elem.click() | ||||
| 
 | ||||
|     # Log in Student account | ||||
|     login(driver, url, '202400000002', '[123Abc]') | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     assert not 'Student ID' in elems[0].text | ||||
|     assert not 'Good Student' in elems[0].text | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_student_with_weak_password_cannot_sign_up(driver, url, restore_database): | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
|     weak_password = '123Abc' | ||||
|     elem = driver.find_element(By.ID, 'signup_link') | ||||
|     elem.click() | ||||
|     elem = driver.find_element(By.NAME, 'fullname') | ||||
|     elem.send_keys('Good Student') | ||||
|     elem = driver.find_element(By.NAME, 'user_student_id') | ||||
|     elem.send_keys('202400000001') | ||||
|     elem = driver.find_element(By.NAME, 'email') | ||||
|     elem.send_keys('goodstudent@qq.com') | ||||
|     elem = driver.find_element(By.NAME, 'password') | ||||
|     elem.send_keys(weak_password) | ||||
|     elem = driver.find_element(By.NAME, 'confirmpassword') | ||||
|     elem.send_keys(weak_password) | ||||
|     elem = driver.find_element(By.ID, 'signup_btn') | ||||
|     elem.click() | ||||
| 
 | ||||
|     # Log in Student account | ||||
|     login(driver, url, '202400000001', weak_password) | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     assert not 'Student ID' in elems[0].text | ||||
|     assert not 'Good Student' in elems[0].text | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_student_can_join_course(driver, url, restore_database): | ||||
|     # Student can join (CSC1111) - Project Management | ||||
|     login(driver, url, '201825800050', '123') | ||||
|     driver.maximize_window() | ||||
| 
 | ||||
|     # Search for CSC1111 | ||||
|     elem = driver.find_element(By.NAME, 'search') | ||||
|     elem.send_keys('CSC1111') | ||||
|     elem = driver.find_element(By.CLASS_NAME, 'btn-primary') | ||||
|     elem.click() | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'btn-default') | ||||
|     assert 'CSC1111' in elems[0].text | ||||
| 
 | ||||
|     # Join | ||||
|     elem = driver.find_element(By.CLASS_NAME, 'btn-success') # find the green Join button | ||||
|     elem.click() | ||||
| 
 | ||||
|     # Log out, then log in to check the course-joining status | ||||
|     logout(driver) | ||||
|     login(driver, url, '201825800050', '123') | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'btn-default') | ||||
|     assert 'CSC1111' in elems[0].text | ||||
|     assert 'Project Management' in elems[0].text | ||||
|     assert 'Joined' in elems[0].text | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_student_can_submit_assignment(driver, url, restore_database): | ||||
|     ''' Note: Make sure the fields Posted_Date and Deadline in the second row of lab_reports_table are in the current year''' | ||||
|     # Student can submit assignment for CSC1111 | ||||
|     login(driver, url, '201825800050', '123') | ||||
|     driver.maximize_window() | ||||
| 
 | ||||
|     # Enter into the course and the find the assignment | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'btn-default') | ||||
|     elems[1].click() | ||||
| 
 | ||||
|     elem = driver.find_element(By.XPATH, '//div[@id="menu1"]/div/div/p/a[text()="Submit"]') # find the submit button | ||||
|     elem.click() | ||||
| 
 | ||||
|     # Fill submission title, attach file, and submit | ||||
|     elem = driver.find_element(By.NAME, 'title') | ||||
|     elem.send_keys('Assignment submission from Mohamed') | ||||
|     elem = driver.find_element(By.NAME, 'attachment1') | ||||
|     elem.send_keys('/var/www/html/LRR/test/SeleniumHui/helper.py') # attach a file | ||||
|     elem = driver.find_element(By.XPATH, '//form/button') | ||||
|     elem.click() | ||||
| 
 | ||||
|     # Go the Submitted tab | ||||
|     elem = driver.find_element(By.ID, 'myTab') | ||||
|     elems = elem.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     elems[2].click() | ||||
| 
 | ||||
|     elem = driver.find_element(By.XPATH, '//div[@id="menu3"]/div') | ||||
|     assert 'Reading 2 (6 Marks)' in elem.text | ||||
|     assert 'SUBMITTED' in elem.text | ||||
|     assert 'helper.py' in elem.text | ||||
|      | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_student_can_request_remarking(driver, url, restore_database): | ||||
|     # Student logs in | ||||
|     login(driver, url, '201825800050', '123') | ||||
|     driver.maximize_window() | ||||
| 
 | ||||
|     # Enter into the course | ||||
|     elems = driver.find_elements(By.CLASS_NAME, 'btn-default') | ||||
|     elems[1].click() | ||||
| 
 | ||||
|     # Go the Marked tab | ||||
|     elem = driver.find_element(By.ID, 'myTab') | ||||
|     elems = elem.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     elems[3].click() | ||||
| 
 | ||||
|     # Send remarking request | ||||
|     remarking_buttons = driver.find_elements(By.CLASS_NAME, 'btn-light') | ||||
|     remarking_buttons[0].click() | ||||
|     alert = driver.switch_to.alert | ||||
|     alert.send_keys('I need higher marks, teacher.') | ||||
|     alert.accept() | ||||
| 
 | ||||
|     elem = driver.find_element(By.XPATH, '//div[@id="menu4"]/div/div/p/span') | ||||
|     assert 'Remarking request sent' == elem.text | ||||
|      | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_lecturer_can_mark_assignment(driver, url, restore_database): | ||||
|     # Lecturer lanhui@qq.com logs in | ||||
|     driver.maximize_window() | ||||
|     login(driver, url, 'lanhui@qq.com', '123') | ||||
| 
 | ||||
|     # Enter into the course and the find the assignment | ||||
|     elem = driver.find_element(By.XPATH, '//div[1]/a[3]/div') # course Software Engineering | ||||
|     elem.click() | ||||
| 
 | ||||
|     elem = driver.find_element(By.XPATH, '//div[2]/div[2]/div/a[2]') # View link | ||||
|     elem.click() | ||||
| 
 | ||||
|     elem = driver.find_element(By.CLASS_NAME, 'btn-primary') # Blue Mark button | ||||
|     elem.click() | ||||
| 
 | ||||
|     # Submit mark and comment | ||||
|     elem = driver.find_element(By.NAME, 'marks') | ||||
|     elem.send_keys('1') | ||||
|     elem = driver.find_element(By.NAME, 'feedback') | ||||
|     elem.send_keys('Inadequate') | ||||
|     form = driver.find_element(By.ID, 'submit-form') | ||||
|     form.submit() | ||||
| 
 | ||||
|     elem = driver.find_element(By.ID, 'myTab') | ||||
|     elems = elem.find_elements(By.CLASS_NAME, 'nav-link') | ||||
|     assert 'Marked submissions (1)' == elems[1].text | ||||
|     elems[1].click() | ||||
|     elem = driver.find_element(By.XPATH, "//div[@id='menu2']/div/b") | ||||
|     assert 'Reading 1 submission' in elem.text | ||||
|      | ||||
|     driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_lecturer_cannot_see_tas_not_from_his_course(driver, url, restore_database): | ||||
|     # Lecturer lanhui@qq.com logs in | ||||
|     driver.maximize_window() | ||||
|     login(driver, url, 'peter@qq.com', '123') | ||||
| 
 | ||||
|     elem = driver.find_element(By.ID, 'admin_tab') | ||||
|     elem.click() | ||||
|     tab = driver.find_element(By.ID, 'existing_accounts_tab') | ||||
|     tab.click() | ||||
|     elem = driver.find_element(By.ID, 'tab-existing-accounts') | ||||
|     assert 'No TA' in elem.text | ||||
| 
 | ||||
|     # Logout | ||||
|     logout(driver) | ||||
|     driver.quit() | ||||
|  | @ -0,0 +1,33 @@ | |||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.ui import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| from selenium.common.exceptions import NoSuchElementException, UnexpectedAlertPresentException | ||||
| 
 | ||||
| 
 | ||||
| def login(driver, url, username, password): | ||||
|     try: | ||||
|         driver.get(url) | ||||
| 
 | ||||
|         # Fill in the login form | ||||
|         user_input = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "user_name")) | ||||
|         ) | ||||
|         user_input.send_keys(username) | ||||
| 
 | ||||
|         password_input = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "user_password")) | ||||
|         ) | ||||
|         password_input.send_keys(password) | ||||
| 
 | ||||
|         # Click the login button | ||||
|         login_button = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "login_btn")) | ||||
|         ) | ||||
|         login_button.click() | ||||
| 
 | ||||
|         # Wait for the admin_tab to become clickable | ||||
|         admin_tab = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "admin_tab")) | ||||
|         ) | ||||
|     except (NoSuchElementException, UnexpectedAlertPresentException) as e: | ||||
|         return f"Error: {str(e)}" | ||||
|  | @ -0,0 +1,125 @@ | |||
| import pytest | ||||
| from selenium import webdriver | ||||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.ui import Select | ||||
| from selenium.webdriver.support.ui import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| from selenium.common.exceptions import NoSuchElementException, UnexpectedAlertPresentException | ||||
| from selenium.webdriver.common.keys import Keys | ||||
| 
 | ||||
| # New instance of the Chrome driver | ||||
| driver = webdriver.Chrome() | ||||
| 
 | ||||
| # Open the login page | ||||
| driver.get("http://localhost/lrr/admin.php") | ||||
| 
 | ||||
| # Credentials for login | ||||
| username = "lanhui@qq.com" | ||||
| password = "admin123" | ||||
| 
 | ||||
| def login(driver, username, password): | ||||
|     try: | ||||
|         # Fill in the login form | ||||
|         user_input = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "user_name")) | ||||
|         ) | ||||
|         user_input.send_keys(username) | ||||
| 
 | ||||
|         password_input = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "user_password")) | ||||
|         ) | ||||
|         password_input.send_keys(password) | ||||
| 
 | ||||
|         # Click the login button | ||||
|         login_button = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "login_btn")) | ||||
|         ) | ||||
|         login_button.click() | ||||
| 
 | ||||
|         # Wait for the admin_tab to become clickable | ||||
|         admin_tab = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "admin_tab")) | ||||
|         ) | ||||
| 
 | ||||
|         return True | ||||
| 
 | ||||
|     except (NoSuchElementException, UnexpectedAlertPresentException) as e: | ||||
|         return f"Error: {str(e)}" | ||||
| 
 | ||||
| # Call the login function | ||||
| login_result = login(driver, username, password) | ||||
| 
 | ||||
| # Click on admin_tab after successful login | ||||
| if login_result: | ||||
|     admin_tab = WebDriverWait(driver, 10).until( | ||||
|         EC.element_to_be_clickable((By.ID, "admin_tab")) | ||||
|     ) | ||||
|     admin_tab.click() | ||||
| 
 | ||||
|     # Optionally, wait for the Admin.php page to load | ||||
|     admin_url = "http://localhost/lrr/Admin.php" | ||||
|     WebDriverWait(driver, 15).until( | ||||
|         EC.url_to_be(admin_url) | ||||
|     ) | ||||
| 
 | ||||
| print(login_result) | ||||
| 
 | ||||
| def assign_ta(driver, course_id, ta_name): | ||||
|     try: | ||||
|         # Locate the form and select the TA | ||||
|         ta_form = WebDriverWait(driver, 15).until( | ||||
|             EC.presence_of_element_located((By.XPATH, f"//form[@id='drop_menu_form_{course_id}']")) | ||||
|         ) | ||||
| 
 | ||||
|         ta_dropdown = Select(ta_form.find_element(By.XPATH, ".//select[@name='ta']")) | ||||
|         ta_dropdown.select_by_visible_text(ta_name) | ||||
| 
 | ||||
|         # Submit the form using JavaScript | ||||
|         driver.execute_script("arguments[0].submit();", ta_form) | ||||
| 
 | ||||
|         # Wait for an expected alert and accept it | ||||
|         WebDriverWait(driver, 10).until(EC.alert_is_present()) | ||||
|         alert = driver.switch_to.alert | ||||
|         alert_text = alert.text | ||||
|         alert.accept() | ||||
| 
 | ||||
|         return alert_text | ||||
| 
 | ||||
|     except UnexpectedAlertPresentException as e: | ||||
|         # Unexpected alert, handle it as an error | ||||
|         return f"Error: Unexpected alert - {str(e)}" | ||||
| 
 | ||||
|     except (NoSuchElementException, Exception) as e: | ||||
|         return f"Error: {str(e)}" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # The courses and test cases to test | ||||
| courses_to_test = [ | ||||
|     {"id": 1, "name": "Teecloudy - Ashly Course Testing", "ta_assignments": {"JAMES": "Ta assigned successfully."}}, | ||||
|     {"id": 2, "name": "P.M2019 - Project Management", "ta_assignments": {"JAMES": "The selected TA is already assigned to this course."}}, | ||||
| ] | ||||
| 
 | ||||
| # Execute the tests | ||||
| @pytest.mark.parametrize("course", courses_to_test) | ||||
| def test_assign_ta(course): | ||||
|     for ta_name, expected_result in course["ta_assignments"].items(): | ||||
|         alert_text = assign_ta(driver, course["id"], ta_name)  | ||||
|         # ----- ---- Print the raw strings for debugging ----- ---- ---  | ||||
|         test_case_number = courses_to_test.index(course) + 1 | ||||
|         print(f"Test Case {test_case_number} - {course['name']} -- {ta_name}: Expected Result={expected_result}, Actual Alert Text={alert_text}") | ||||
| 
 | ||||
|         # Determine the result based on the comparison | ||||
|         if expected_result.lower() in alert_text.lower(): | ||||
|             result = "Passed" | ||||
|         else: | ||||
|             result = "Failed" | ||||
| 
 | ||||
|         # Write the result to a test file with test case number --- | ||||
|         with open("test_results.txt", "a") as file: | ||||
|             file.write(f"Test Case {test_case_number} - {course['name']} -- {ta_name}: Result={result}, Expected Result={expected_result}, Actual Alert Text={alert_text}\n") | ||||
| 
 | ||||
|         # Print the result to the console ---  | ||||
|         print(f"Test Case {test_case_number} - {course['name']} -- {ta_name}: Result={result}, Expected Result={expected_result}, Actual Alert Text={alert_text}") | ||||
| 
 | ||||
|         assert result == "Passed", f"Test Case {test_case_number} failed: Result={result}, Expected Result={expected_result}, Actual Alert Text={alert_text}" | ||||
|  | @ -0,0 +1,122 @@ | |||
| import pytest | ||||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.ui import Select | ||||
| from selenium.webdriver.support.ui import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| from selenium.common.exceptions import NoSuchElementException, UnexpectedAlertPresentException | ||||
| from helper import login | ||||
| 
 | ||||
| @pytest.mark.parametrize("course_id, course_name, ta_name", [(1, "Teecloudy - Ashly Course Testing", "Mark")]) | ||||
| def test_assign_a_new_ta_to_a_course(course_id, course_name, ta_name, driver, url, admin_username, admin_password, restore_database): | ||||
|     try: | ||||
|         driver.maximize_window() | ||||
| 
 | ||||
|         login(driver, url, admin_username, admin_password) | ||||
| 
 | ||||
|         admin_tab = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "admin_tab")) | ||||
|         ) | ||||
|         admin_tab.click() | ||||
|          | ||||
|         # Locate the form and select the TA | ||||
|         ta_form = WebDriverWait(driver, 15).until( | ||||
|             EC.presence_of_element_located((By.XPATH, f"//form[@id='drop_menu_form_{course_id}']")) | ||||
|         ) | ||||
| 
 | ||||
|         ta_dropdown = Select(ta_form.find_element(By.XPATH, ".//select[@name='ta']")) | ||||
|         ta_dropdown.select_by_visible_text(ta_name) | ||||
| 
 | ||||
|         # Submit the form using JavaScript | ||||
|         driver.execute_script("arguments[0].submit();", ta_form) | ||||
| 
 | ||||
|         # find table courses | ||||
|         table_courses = WebDriverWait(driver, 10).until( | ||||
|             EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table")) | ||||
|         ) | ||||
|         # find the row with matching course_name | ||||
|         course_row = table_courses.find_element(By.XPATH, f".//tr[td='{course_name}']") | ||||
|         # find the column with TA name | ||||
|         ta_column = course_row.find_element(By.XPATH, ".//td[4]") | ||||
| 
 | ||||
|         # assert the TA name in the column | ||||
|         assert ta_name in ta_column.text, f"Error: TA name {ta_name} not found in the column {ta_column.text}" | ||||
|          | ||||
|     except NoSuchElementException as e: | ||||
|         return f"Error: {str(e)}" | ||||
|     except UnexpectedAlertPresentException as e: | ||||
|         return f"Error: {str(e)}" | ||||
|     except AssertionError as e: | ||||
|         return f"Error: {str(e)}" | ||||
|     except Exception as e: | ||||
|         return f"Error: {str(e)}" | ||||
|     finally: | ||||
|         driver.quit() | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.parametrize("course_id, course_name, ta_name", [(1, "Teecloudy - Ashly Course Testing", "Mark")]) | ||||
| def test_assign_the_same_ta_to_the_same_course_twice(course_id, course_name, ta_name, driver, url, admin_username, admin_password, restore_database): | ||||
|     try: | ||||
|         driver.maximize_window()         | ||||
|         login(driver, url, admin_username, admin_password) | ||||
| 
 | ||||
|         admin_tab = WebDriverWait(driver, 10).until( | ||||
|             EC.element_to_be_clickable((By.ID, "admin_tab")) | ||||
|         ) | ||||
|         admin_tab.click() | ||||
| 
 | ||||
|         # Hui: assign the TA for the first time | ||||
|         # (1) Locate the form and select the TA | ||||
|         ta_form = WebDriverWait(driver, 15).until( | ||||
|             EC.presence_of_element_located((By.XPATH, | ||||
|             f"//form[@id='drop_menu_form_{course_id}']")) ) | ||||
| 
 | ||||
|         ta_dropdown = Select(ta_form.find_element(By.XPATH, ".//select[@name='ta']")) | ||||
|         ta_dropdown.select_by_visible_text(ta_name) | ||||
| 
 | ||||
|         # (2) Submit the form using JavaScript | ||||
|         driver.execute_script("arguments[0].submit();", ta_form) | ||||
| 
 | ||||
|         # (3) Find table courses | ||||
|         table_courses_before = WebDriverWait(driver, 10).until( | ||||
|             EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table")) | ||||
|         ) | ||||
|         # (4) Find the row with matching course_name | ||||
|         course_row_before = table_courses_before.find_element(By.XPATH, f".//tr[td='{course_name}']") | ||||
|         # (5) Find the column with TA name | ||||
|         old_cell_content = course_row_before.find_element(By.XPATH, ".//td[4]").text | ||||
| 
 | ||||
| 
 | ||||
|         # Hui: assign the same TA again | ||||
|         ta_form = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, f"//form[@id='drop_menu_form_{course_id}']"))) | ||||
|         ta_dropdown = Select(ta_form.find_element(By.XPATH, ".//select[@name='ta']")) | ||||
|         ta_dropdown.select_by_visible_text(ta_name)         | ||||
|         driver.execute_script("arguments[0].submit();", ta_form) | ||||
|          | ||||
|         # Wait for an expected alert and accept it | ||||
|         WebDriverWait(driver, 10).until(EC.alert_is_present()) | ||||
|         alert = driver.switch_to.alert | ||||
|         alert_text = alert.text | ||||
|         alert.accept() | ||||
|          | ||||
|         # find table courses | ||||
|         table_courses_after = WebDriverWait(driver, 10).until( | ||||
|             EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table")) | ||||
|         ) | ||||
|         # find the row with matching course_name | ||||
|         course_row_after = table_courses_after.find_element(By.XPATH, f".//tr[td='{course_name}']") | ||||
|         # find the column with TA name | ||||
|         new_cell_content = course_row_after.find_element(By.XPATH, ".//td[4]").text | ||||
| 
 | ||||
|         # assert the TA name in the column | ||||
|         assert old_cell_content == new_cell_content, f"Error: TA name in the column has changed from {old_cell_content} to {new_cell_content}" | ||||
|      | ||||
|     except NoSuchElementException as e: | ||||
|         return f"Error: {str(e)}" | ||||
|     except UnexpectedAlertPresentException as e: | ||||
|         return f"Error: {str(e)}" | ||||
|     except AssertionError as e: | ||||
|        return f"Error: {str(e)}" | ||||
|     except Exception as e: | ||||
|        return f"Error: {str(e)}" | ||||
|     finally: | ||||
|         driver.quit() | ||||
|  | @ -0,0 +1,2 @@ | |||
| Test Case 1 - Teecloudy - Ashly Course Testing -- JAMES: Result=Passed, Expected Result=Ta assigned successfully., Actual Alert Text=TA assigned successfully. | ||||
| Test Case 2 - P.M2019 - Project Management -- DIEGO: Result=Passed, Expected Result=The selected TA is already assigned to this course., Actual Alert Text=The selected TA is already assigned to this course. | ||||
|  | @ -0,0 +1,201 @@ | |||
| # Each time you run the test script reset the database. | ||||
| # For this test script you won't need it since it changes | ||||
| # the Ta's email and name automatically | ||||
| import re | ||||
| import time | ||||
| import pytest | ||||
| 
 | ||||
| from selenium import webdriver | ||||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.wait import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| 
 | ||||
| 
 | ||||
| def test_restore_database(restore_database): | ||||
|     assert restore_database is None | ||||
| 
 | ||||
| 
 | ||||
| def createTA(driver, TA_name, emails, password): | ||||
|     full_name = driver.find_element('name', 'fullname') | ||||
|     full_name.send_keys(TA_name) | ||||
|     email = driver.find_element('name', 'email') | ||||
|     email.send_keys(emails) | ||||
|     pas = driver.find_element('name', 'password') | ||||
|     pas.send_keys(password) | ||||
|     usr_type = driver.find_element('name', 'type') | ||||
|     usr_type.click() | ||||
|     click_create = driver.find_element('name', 'create_btn') | ||||
|     click_create.click() | ||||
| 
 | ||||
| 
 | ||||
| def login_lecturer(driver, url): | ||||
|     # Open the website | ||||
|     driver.get(url) | ||||
|     driver.maximize_window() | ||||
| 
 | ||||
|     username_input = driver.find_element('name', "user") | ||||
| 
 | ||||
|     password_input = driver.find_element('name', "password") | ||||
| 
 | ||||
|     login_button = driver.find_element('id', "login_btn") | ||||
| 
 | ||||
|     # login as a Lecturer | ||||
|     username_input.send_keys("admin@qq.com") | ||||
|     password_input.send_keys("123") | ||||
|     # Click the login button | ||||
|     time.sleep(2) | ||||
|     login_button.click() | ||||
|     admin_tab = driver.find_element('id', 'admin_tab') | ||||
|     admin_tab.click() | ||||
| 
 | ||||
|     cte_instructor = driver.find_element('id', 'tab_ins_accounts') | ||||
|     cte_instructor.click() | ||||
|     time.sleep(2) | ||||
| 
 | ||||
| 
 | ||||
| def test_createTA(driver, url): | ||||
|     driver_open = driver | ||||
|     driver_open.maximize_window() | ||||
|     login_lecturer(driver_open, url) | ||||
|     try: | ||||
|         fullname = "lanhuitest1" | ||||
|         email = "lanhuitest1@qq.com" | ||||
|         password = "new1452345678" | ||||
|         createTA(driver_open, fullname, email,password)  # CREATE A TA  WITH FULLNAME lanhuitest1 email lanhuitest1@qq.com  password new1452345678 | ||||
| 
 | ||||
|         get_output = WebDriverWait(driver_open, 20).until( | ||||
|             EC.element_to_be_clickable((By.ID, "tab_ins_accounts")) | ||||
|         ) | ||||
|         get_output.click() | ||||
|         get_output_msg = driver_open.find_element(By.CLASS_NAME, "alert-warning") | ||||
|         txt_alert = get_output_msg.text | ||||
|         time.sleep(2) | ||||
| 
 | ||||
|         if txt_alert.find("TA user created successfully") == 0: | ||||
|             logout_button = WebDriverWait(driver_open, 20).until( | ||||
|                 EC.element_to_be_clickable( | ||||
|                     (By.XPATH, "//a[contains(@class, 'nav-link') and contains(@href, 'logout.php')]")) | ||||
|             ) | ||||
|             time.sleep(2) | ||||
|             logout_button.click() | ||||
|             time.sleep(2) | ||||
|             username_input = driver_open.find_element('name', "user") | ||||
|             password_input = driver_open.find_element('name', "password") | ||||
|             login_button = driver_open.find_element('id', "login_btn") | ||||
|             # login as the new TA | ||||
|             username_input.send_keys(email)  # login with credentials of the created TA | ||||
|             password_input.send_keys(password) | ||||
|             # Click the login button | ||||
|             time.sleep(2) | ||||
| 
 | ||||
|             login_button.click() | ||||
| 
 | ||||
|             time.sleep(2) | ||||
|         elif txt_alert.find("Email address ") == 0: | ||||
| 
 | ||||
|             time.sleep(2) | ||||
|             driver_open.quit() | ||||
| 
 | ||||
|         else: | ||||
|             driver_open.quit() | ||||
| 
 | ||||
|         time.sleep(2) | ||||
| 
 | ||||
|     finally: | ||||
|         driver_open.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_generate_password(driver, url): | ||||
|     driver_open = driver | ||||
|     login_lecturer(driver_open, url) | ||||
|     try: | ||||
|         fullname = "lanhuitest2" | ||||
|         email = "lanhuitest2@qq.com" | ||||
|         password = "" | ||||
|         createTA(driver_open, fullname, email, | ||||
|                  password)  # CREATE A TA  WITH FULLNAME lanhuitest2 email lanhuitest2@qq.com  password "" | ||||
| 
 | ||||
|         get_output = WebDriverWait(driver_open, 20).until( | ||||
|             EC.element_to_be_clickable((By.ID, "tab_ins_accounts")) | ||||
|         ) | ||||
|         get_output.click() | ||||
|         get_output_msg = driver_open.find_element(By.CLASS_NAME, "alert-warning") | ||||
|         txt_alert = get_output_msg.text | ||||
|         time.sleep(2) | ||||
| 
 | ||||
|         if txt_alert.find("TA user created successfully") == 0: | ||||
|             time.sleep(2) | ||||
|             email_pattern = r"Use email (\S+) as account name" | ||||
|             password_pattern = r" (\S+)\ as password." | ||||
|             email_match = re.search(email_pattern, txt_alert) | ||||
|             password_match = re.search(password_pattern, txt_alert) | ||||
|             if email_match and password_match: | ||||
|                 # Extract email and password from the matches | ||||
|                 email = email_match.group(1) | ||||
|                 password = password_match.group(1) | ||||
|             logout_button = WebDriverWait(driver_open, 20).until( | ||||
|                 EC.element_to_be_clickable( | ||||
|                     (By.XPATH, "//a[contains(@class, 'nav-link') and contains(@href, 'logout.php')]")) | ||||
|             ) | ||||
|             logout_button.click() | ||||
|             time.sleep(2) | ||||
|             username_input = driver_open.find_element('name', "user") | ||||
|             password_input = driver_open.find_element('name', "password") | ||||
|             login_button = driver_open.find_element('id', "login_btn") | ||||
|             # login as the new TA | ||||
|             username_input.send_keys(email)  # login with credentials of the created TA | ||||
|             password_input.send_keys(password) | ||||
|             # Click the login button | ||||
|             time.sleep(2) | ||||
| 
 | ||||
|             login_button.click() | ||||
| 
 | ||||
|             time.sleep(2) | ||||
| 
 | ||||
|         elif txt_alert.find("Email address ") == 0: | ||||
|             time.sleep(2) | ||||
|             driver_open.quit() | ||||
| 
 | ||||
|         else: | ||||
|             driver_open.quit() | ||||
| 
 | ||||
|         time.sleep(2) | ||||
| 
 | ||||
|     finally: | ||||
|         driver_open.quit() | ||||
| 
 | ||||
| 
 | ||||
| def test_existingTA(driver, url, restore_database): | ||||
|     driver_open = driver | ||||
|     login_lecturer(driver, url) | ||||
|     try: | ||||
| # Use email nreyes@example.com as account name and new1452345678 as password. | ||||
|         fullname = "lanhuitest1" | ||||
|         email = "lanhuitest1@qq.com" | ||||
|         password = "new1452345678" | ||||
|         createTA(driver_open, fullname, email, | ||||
|                  password)  # CREATE A TA  WITH FULLNAME lanhuitest1 email lanhuitest1@qq.com  password new1452345678 | ||||
| 
 | ||||
|         get_output = WebDriverWait(driver_open, 20).until( | ||||
|             EC.element_to_be_clickable((By.ID, "tab_ins_accounts")) | ||||
|         ) | ||||
|         get_output.click() | ||||
|         get_output_msg = driver_open.find_element(By.CLASS_NAME, "alert-warning") | ||||
|         txt_alert = get_output_msg.text | ||||
|         time.sleep(2) | ||||
| 
 | ||||
|         if txt_alert.find("TA user created successfully") == 0: | ||||
|             time.sleep(2) | ||||
| 
 | ||||
| 
 | ||||
|         elif txt_alert.find("Email address ") == 0: | ||||
|             time.sleep(2) | ||||
|             driver_open.quit() | ||||
| 
 | ||||
|         else: | ||||
|             driver_open.quit() | ||||
| 
 | ||||
|         time.sleep(2) | ||||
| 
 | ||||
|     finally: | ||||
|         driver_open.quit() | ||||
|  | @ -0,0 +1,77 @@ | |||
| import pytest | ||||
| from selenium import webdriver | ||||
| from selenium.webdriver.common.by import By | ||||
| from selenium.webdriver.support.ui import WebDriverWait | ||||
| from selenium.webdriver.support import expected_conditions as EC | ||||
| from selenium.common.exceptions import NoSuchElementException, TimeoutException | ||||
| import time | ||||
| import traceback | ||||
| 
 | ||||
| driver = webdriver.Chrome() | ||||
| 
 | ||||
| try: | ||||
|     # Navigate to the page with tabs | ||||
|     driver.get("http://localhost:8080/lrr/") | ||||
|     driver.maximize_window() | ||||
|     wait = WebDriverWait(driver, 10) | ||||
| 
 | ||||
|     # Login as a Lecturer | ||||
|     username_input = wait.until(EC.presence_of_element_located((By.NAME, "user"))) | ||||
|     password_input = driver.find_element(By.NAME, "password") | ||||
|     login_button = driver.find_element(By.ID, "login_btn") | ||||
|      | ||||
|     username_input.send_keys("ashly@qq.com") | ||||
|     password_input.send_keys("admin123") | ||||
|     time.sleep(5) | ||||
|     login_button.click() | ||||
| 
 | ||||
|     course_but= driver.find_element(By.XPATH, "(//div[@class='btn btn-default'])[1]")  # Adjust this XPATH as needed | ||||
|      | ||||
|      | ||||
|     # Click on the alert | ||||
|     course_but.click() | ||||
|     time.sleep(5) | ||||
| 
 | ||||
|     marked_tab = wait.until( | ||||
|         EC.element_to_be_clickable((By.XPATH, "//a[text()='Marked']")) | ||||
|     ) | ||||
|     marked_tab.click() | ||||
| 
 | ||||
|     # Wait for the Marked tab content to be present | ||||
|     marked_tab_content = wait.until( | ||||
|         EC.presence_of_element_located((By.XPATH, "//div[@id='menu4' and contains(@class, 'active')]")) | ||||
|     ) | ||||
| 
 | ||||
|     time.sleep(5) | ||||
|     remark_but = wait.until( | ||||
|         EC.presence_of_element_located((By.XPATH, "//button[normalize-space()='Request remarking']")) | ||||
|     )     | ||||
|     remark_but.click() | ||||
|      | ||||
| 
 | ||||
|     time.sleep(2)  | ||||
| 
 | ||||
|     # Switch to the alert | ||||
|     alert = driver.switch_to.alert | ||||
| 
 | ||||
|     # Send keys to the prompt | ||||
|     alert.send_keys("Number 2 was correct") | ||||
| 
 | ||||
|     # Accept the prompt (click OK) | ||||
|     alert.accept() | ||||
| 
 | ||||
|     time.sleep(5) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| except NoSuchElementException as e: | ||||
|     print("NoSuchElementException: Could not find an element.") | ||||
|     traceback.print_exc() | ||||
| except TimeoutException as e: | ||||
|     print("TimeoutException: An element took too long to load.") | ||||
|     traceback.print_exc() | ||||
| except Exception as e: | ||||
|     print(f"An unexpected error occurred: {e}") | ||||
|     traceback.print_exc() | ||||
| finally: | ||||
|     driver.quit() | ||||
|  | @ -0,0 +1,46 @@ | |||
| import os | ||||
| import pytest | ||||
| from selenium import webdriver | ||||
| 
 | ||||
| 
 | ||||
| @pytest.fixture | ||||
| def restore_database(): | ||||
|     ''' Restore the database. | ||||
|         It is useful for making sure that each end-to-end test | ||||
|         starts with the same database. | ||||
|         Benefit: we can reproduce the same test result. | ||||
|     ''' | ||||
| 
 | ||||
|     PASSWORD = 'p-@va9'  # root password | ||||
|     DB_NAME = 'lrr' # database name used for LRR | ||||
| 
 | ||||
|     # commands used to import data to DB_NAME | ||||
|     cmds = [ | ||||
|         f'mysql -u root -p{PASSWORD} -e "DROP DATABASE IF EXISTS {DB_NAME};"',         | ||||
|         f'mysql -u root -p{PASSWORD} -e "CREATE DATABASE {DB_NAME};"', | ||||
|         f'mysql -u root -p{PASSWORD} -e "GRANT ALL PRIVILEGES ON {DB_NAME}.* TO lrr@localhost WITH GRANT OPTION;"', | ||||
|         f'mysql -u root -p{PASSWORD} {DB_NAME} < ../lrr_database.sql'] | ||||
| 
 | ||||
|     for command in cmds: | ||||
|         os.system(command) | ||||
|     return None | ||||
| 
 | ||||
| 
 | ||||
| @pytest.fixture | ||||
| def url(): | ||||
|     return 'http://localhost/LRR/' # URL of LRR | ||||
| 
 | ||||
| 
 | ||||
| @pytest.fixture | ||||
| def driver(): | ||||
|     return  webdriver.Chrome() | ||||
| 
 | ||||
| 
 | ||||
| @pytest.fixture | ||||
| def admin_username(): | ||||
|     return 'admin@qq.com' | ||||
| 
 | ||||
| 
 | ||||
| @pytest.fixture | ||||
| def admin_password(): | ||||
|     return '123' | ||||
		Loading…
	
		Reference in New Issue