Compare commits
	
		
			53 Commits 
		
	
	
		
			Bug352-Nei
			...
			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 | |
| 
							
							
								
									
								
								 | 
						64ffc3af1c | |
| 
							
							
								
									
								
								 | 
						9f03d380cd | |
| 
							
							
								
									
								
								 | 
						c1f95ce017 | |
| 
							
							
								
									
								
								 | 
						adc9daef98 | |
| 
							
							
								
								 | 
						fc8ad0c0a9 | 
| 
						 | 
				
			
			@ -1,2 +1,5 @@
 | 
			
		|||
.vscode
 | 
			
		||||
.DS_Store
 | 
			
		||||
venv/
 | 
			
		||||
__pycache__/
 | 
			
		||||
*.pyc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								Admin.php
								
								
								
								
							
							
						
						
									
										42
									
								
								Admin.php
								
								
								
								
							| 
						 | 
				
			
			@ -30,7 +30,7 @@ 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">
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +66,7 @@ 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="" />
 | 
			
		||||
			<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
 | 
			
		||||
| 
						 | 
				
			
			@ -93,10 +93,6 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
 | 
			
		|||
			    echo  '<hr><div class="alert alert-warning" role="alert">' . $_SESSION['info_Admin_Users'] . '</div>';
 | 
			
		||||
			    $_SESSION['info_Admin_Users'] = null;
 | 
			
		||||
			}
 | 
			
		||||
			if (isset($_SESSION['info_Admin_Users'])) {
 | 
			
		||||
			    echo  '<hr><div class="alert alert-warning" role="alert">' . $_SESSION['info_Admin_Users'] . '</div>';
 | 
			
		||||
			    $_SESSION['info_Admin_Users'] = null;
 | 
			
		||||
			}
 | 
			
		||||
			?>
 | 
			
		||||
 | 
			
		||||
		    </form>
 | 
			
		||||
| 
						 | 
				
			
			@ -117,10 +113,21 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
 | 
			
		|||
			<?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)"
 | 
			
		||||
			    );
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -131,6 +138,7 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
 | 
			
		|||
			    );
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			$num_rows = 0;
 | 
			
		||||
			while ($row = mysqli_fetch_assoc($result)) {
 | 
			
		||||
			    $pass =  $row['Password'];
 | 
			
		||||
			    $btn = "<button class='btn btn-warning' onclick=\"updatePassword(" . $row['User_ID'] . ",'$pass')\">Reset</button>";
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +151,10 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
 | 
			
		|||
			    }
 | 
			
		||||
 | 
			
		||||
			    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>
 | 
			
		||||
| 
						 | 
				
			
			@ -227,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);
 | 
			
		||||
?>
 | 
			
		||||
							
								
								
									
										191
									
								
								Script.php
								
								
								
								
							
							
						
						
									
										191
									
								
								Script.php
								
								
								
								
							| 
						 | 
				
			
			@ -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,7 +364,7 @@ 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"]);
 | 
			
		||||
| 
						 | 
				
			
			@ -283,17 +384,15 @@ if (!empty($_POST["form_createlecturrer"])){
 | 
			
		|||
        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) {
 | 
			
		||||
    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");
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
      alert("Error: " . $sql . "<br>" . $con->error);
 | 
			
		||||
        header("Location: Admin.php?tacreated");
 | 
			
		||||
    } catch (Exception $ex) {
 | 
			
		||||
        echo "$ex";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ### FUNCTION TO GENERATE INITIAL PASSWORDS ###//
 | 
			
		||||
| 
						 | 
				
			
			@ -713,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;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
| 
						 | 
				
			
			@ -285,15 +290,36 @@ 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', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', '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'),
 | 
			
		||||
(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,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()
 | 
			
		||||
		Loading…
	
		Reference in New Issue