Add admin panel
This commit is contained in:
		
							parent
							
								
									107f599f27
								
							
						
					
					
						commit
						3a42952593
					
				
							
								
								
									
										71
									
								
								admin/index.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								admin/index.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | ||||
| <?php | ||||
| 
 | ||||
| session_start(); | ||||
| 
 | ||||
| if (!isset($_SESSION['uid'])) { | ||||
| 	header('Location: /admin/login.php'); | ||||
| 	die; | ||||
| } | ||||
| 
 | ||||
| $conn = new mysqli("localhost", "mileslinden", "Daiso@6969", "mileslinden"); | ||||
| 
 | ||||
| $result = $conn->query("SELECT * FROM subscribers"); | ||||
| if (!$result) { | ||||
| 	http_response_code(500); | ||||
| 	die("Error: {$conn->error}"); | ||||
| } | ||||
| 
 | ||||
| $subscribers = []; | ||||
| while ($row = $result->fetch_assoc()) { | ||||
|     $subscribers[] = $row; | ||||
| } | ||||
| ?>
 | ||||
| <!DOCTYPE HTML> | ||||
| <html lang="en"> | ||||
|     <head> | ||||
|         <meta charset="utf-8"> | ||||
|         <title>Miles Linden for San Jose City Council</title> | ||||
|     </head> | ||||
|     <body> | ||||
|         <h1>Admin Panel</h1> | ||||
| 		<div> | ||||
| 			<p><a href="logout.php">Logout</a></p> | ||||
| 			<p><a href="mail.php">Mail All</a></p> | ||||
| 		</div> | ||||
| 		<h2>Subscribers</h2> | ||||
| 		<table cellpadding="5"> | ||||
| 		<thead> | ||||
| 			<tr> | ||||
| 				<th>Name</th> | ||||
| 				<th>Email</th> | ||||
| 				<th>Phone</th> | ||||
| 				<!--<th>Gender</th>--> | ||||
| 				<th>Join Date</th> | ||||
| 				<th>Actions</th> | ||||
| 			</tr> | ||||
| 		</thead> | ||||
| 		<tbody> | ||||
| <?php | ||||
| 	foreach ($subscribers as $row) { | ||||
| ?>
 | ||||
| 			<tr> | ||||
| 				<td><?= htmlspecialchars($row['full_name']) ?></td>
 | ||||
| 				<td> | ||||
| 					<a href="mailto:<?= htmlspecialchars($row['email']) ?>"><?= htmlspecialchars($row['email']) ?></a></td>
 | ||||
| 				<td><?= htmlspecialchars($row['phone']) ?></td>
 | ||||
| 				<!--<td><?= htmlspecialchars($row['gender']) ?></td>-->
 | ||||
| 				<td><?= htmlspecialchars($row['join_date']) ?></td>
 | ||||
| 				<td> | ||||
| 					<form action="/admin/unsubscribe.php" method="POST"> | ||||
| 						<input type="hidden" name="email" value="<?= htmlspecialchars($row['email']) ?>"> | ||||
| 						<button type="submit">Delete</button> | ||||
| 					</form> | ||||
| 				</td> | ||||
| 			</tr> | ||||
| <?php | ||||
| 	} | ||||
| ?>
 | ||||
| 		</tbody> | ||||
| 		</table> | ||||
|     </body> | ||||
| </html> | ||||
							
								
								
									
										34
									
								
								admin/login.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								admin/login.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| <?php | ||||
| 
 | ||||
| session_start(); | ||||
| 
 | ||||
| $token = $_POST['token']; | ||||
| 
 | ||||
| if (!isset($_SESSION['uid'])) { | ||||
| 	if (!isset($token)) { | ||||
| ?>
 | ||||
| <!DOCTYPE HTML> | ||||
| <html> | ||||
| <body> | ||||
| <form action="/admin/login.php" method="POST"> | ||||
| 	<div> | ||||
| 		<p>Enter passcode:</p> | ||||
| 		<input type="password" name="token"> | ||||
| 	</div> | ||||
| 	<div> | ||||
| 		<button type="submit">Login</button> | ||||
| 	</div> | ||||
| </form> | ||||
| </body> | ||||
| </html> | ||||
| <?php | ||||
| 		die; | ||||
| 	} else if ($token !== '1445') { | ||||
| 		http_response_code(403); | ||||
| 		die("Error: incorrect token"); | ||||
| 	} else { | ||||
| 		$_SESSION['uid'] = 1; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| header('Location: /admin'); | ||||
							
								
								
									
										16
									
								
								admin/logout.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								admin/logout.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| <?php | ||||
| 
 | ||||
| session_start(); | ||||
| 
 | ||||
| unset($_SESSION['uid']); | ||||
| 
 | ||||
| ?>
 | ||||
| <!DOCTYPE HTML> | ||||
| <html> | ||||
| <head> | ||||
| 	<meta http-equiv="refresh" content="3; /"> | ||||
| </head> | ||||
| <body> | ||||
| 	<p>Signed out.</p> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										53
									
								
								admin/mail.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								admin/mail.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| <?php | ||||
| 
 | ||||
| session_start(); | ||||
| 
 | ||||
| if (!isset($_SESSION['uid'])) { | ||||
| 	header('Location: /admin/login.php'); | ||||
| 	die; | ||||
| } | ||||
| 
 | ||||
| $message = $_POST['message']; | ||||
| if (!isset($message)) { | ||||
| ?>
 | ||||
| <!DOCTYPE HTML> | ||||
| <html> | ||||
| <body> | ||||
| 	<form action="/admin/mail.php" method="POST"> | ||||
| 		<div> | ||||
| 			<textarea name="message" placeholder="Message..."></textarea> | ||||
| 		</div> | ||||
| 		<div> | ||||
| 			<button type="submit">Send</button> | ||||
| 		</div> | ||||
| 	</form> | ||||
| </body> | ||||
| </html> | ||||
| <?php | ||||
| 	die; | ||||
| } | ||||
| 
 | ||||
| $conn = new mysqli("localhost", "mileslinden", "Daiso@6969", "mileslinden"); | ||||
| 
 | ||||
| $result = $conn->query("SELECT email, full_name FROM subscribers"); | ||||
| if (!$result) { | ||||
|     http_response_code(500); | ||||
|     die(json_encode(['message' => $conn->error])); | ||||
| } | ||||
| $to_emails = []; | ||||
| while ($row = $result->fetch_row()) { | ||||
| 	$to_emails[] = "$row[1] <$row[0]>"; | ||||
| } | ||||
| 
 | ||||
| $to = implode(", ", $to_emails); | ||||
| $headers = [ | ||||
|     'From: Miles Linden <no-reply@mileslinden.com>', | ||||
|     'X-Mailer: PHP/' . phpversion() | ||||
| ]; | ||||
| $message = wordwrap($message, 80, "\r\n"); | ||||
| if (!mail($to, "MILES LINDEN CAMPAIGN ALERT", $message, implode("\r\n", $headers), '-fno-reply@mileslinden.com')) { | ||||
| 	http_response_code(500); | ||||
|     die("Error: failed to send email message."); | ||||
| } | ||||
| 
 | ||||
| die("Sent email successfully."); | ||||
							
								
								
									
										32
									
								
								admin/unsubscribe.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								admin/unsubscribe.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| <?php | ||||
| 
 | ||||
| session_start(); | ||||
| 
 | ||||
| if (!isset($_SESSION['uid'])) { | ||||
| 	header('Location: /admin/login.php'); | ||||
| 	die; | ||||
| } | ||||
| 
 | ||||
| $email = $_POST['email']; | ||||
| if (!isset($email)) { | ||||
| 	http_response_code(400); | ||||
| 	die("Error: no email provided to unsubscribe"); | ||||
| } | ||||
| 
 | ||||
| $conn = new mysqli("localhost", "mileslinden", "Daiso@6969", "mileslinden"); | ||||
| 
 | ||||
| $query = $conn->prepare("DELETE FROM subscribers WHERE email = ?"); | ||||
| if (!$query) { | ||||
| 	http_response_code(500); | ||||
| 	die("Error: {$conn->error}"); | ||||
| } | ||||
| $query->bind_param("s", $email); | ||||
| $query->execute(); | ||||
| 
 | ||||
| if ($query->affected_rows === 0) { | ||||
| 	http_response_code(400); | ||||
| 	die("Error: that email address does not exist"); | ||||
| } else { | ||||
| 	header('Location: /admin'); | ||||
| 	die; | ||||
| } | ||||
| @ -98,6 +98,10 @@ nav a:hover { | ||||
| 	min-width: 250px; | ||||
| } | ||||
| 
 | ||||
| .banner form input.invalid { | ||||
| 	border-bottom-color: red; | ||||
| } | ||||
| 
 | ||||
| .banner input { | ||||
| 	border: none; | ||||
| 	font-size: 32px; | ||||
|  | ||||
| @ -3,8 +3,10 @@ | ||||
| 	<head> | ||||
| 		<meta charset="utf-8"> | ||||
| 		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha512-NhSC1YmyruXifcj/KFRWoC561YpHpc5Jtzgvbuzx5VozKpWvQ+4nXhPdFgmx8xqexRcpAglTj9sIBWINXa8x5w==" crossorigin="anonymous"> | ||||
| 		<link rel="stylesheet" href="css/main.css"> | ||||
| 		<link rel="stylesheet" type="text/css" href="css/main.css"> | ||||
| 		<link rel="fav icon" href="assets/favicon.png"> | ||||
| 		<script src="https://unpkg.com/vue@latest"></script> | ||||
| 		<script src="js/app.js"></script> | ||||
| 		<title>Miles Linden for San Jose City Council</title> | ||||
| 	</head> | ||||
| 	<body> | ||||
|  | ||||
							
								
								
									
										74
									
								
								js/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								js/app.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | ||||
| document.addEventListener('DOMContentLoaded', function () { | ||||
| 	 | ||||
| 	var fullName = document.querySelector('input[name="full_name"]'); | ||||
| 	var email = document.querySelector('input[name="email"]'); | ||||
| 	var phone = document.querySelector('input[name="phone"]'); | ||||
| 	var submit = document.querySelector('button[type="submit"]'); | ||||
| 
 | ||||
| 	const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; | ||||
| 	const phoneRegex = /^(\+?0?1\s?)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/; | ||||
| 	const fullNameRegex = /[^\s.]{2,} [^\s.]{2,}/; | ||||
| 
 | ||||
| 
 | ||||
| 	fullName.addEventListener('input', function (e) { | ||||
| 		if (! fullName.value.toLowerCase().match(fullNameRegex)) { | ||||
| 			fullName.classList.add('invalid'); | ||||
| 		} else { | ||||
| 			fullName.classList.remove('invalid'); | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	email.addEventListener('input', function (e) { | ||||
| 		if (! email.value.toLowerCase().match(emailRegex)) { | ||||
| 			email.classList.add('invalid'); | ||||
| 		} else { | ||||
| 			email.classList.remove('invalid'); | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	phone.addEventListener('input', function (e) { | ||||
| 		if (! phone.value.match(phoneRegex)) { | ||||
| 			phone.classList.add('invalid'); | ||||
| 		} else { | ||||
| 			phone.classList.remove('invalid'); | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	submit.addEventListener('click', function (e) { | ||||
| 		e.preventDefault(); | ||||
| 
 | ||||
| 		if (! fullName.value.toLowerCase().match(fullNameRegex)) { | ||||
| 			alert("Your full name appears invalid."); | ||||
| 			return; | ||||
| 		} | ||||
| 		if (! email.value.toLowerCase().match(emailRegex)) { | ||||
| 			alert("Your email address is invalid."); | ||||
| 			return; | ||||
| 		} | ||||
| 		if (! phone.value.match(phoneRegex)) { | ||||
| 			alert("Your phone number is invalid."); | ||||
| 			return; | ||||
| 		} | ||||
| 		var fd = new FormData(); | ||||
| 		fd.append('full_name', fullName.value); | ||||
| 		fd.append('email', email.value); | ||||
| 		fd.append('phone', phone.value); | ||||
| 		var req = fetch('/subscribe.php', { | ||||
| 			method: 'POST', | ||||
| 			body: fd | ||||
| 		}).then(function (res) { | ||||
| 			if (!res.ok) { | ||||
| 				res.json().then(function (err) { | ||||
| 					document.querySelector('input[name="'+ err.field + '"]').classList.add('invalid'); | ||||
| 					alert(err.message); | ||||
| 				}); | ||||
| 			} else { | ||||
| 				alert("You have subscribed successfully."); | ||||
| 				fullName.value = ""; | ||||
| 				email.value = ""; | ||||
| 				phone.value = ""; | ||||
| 			} | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| }); | ||||
							
								
								
									
										46
									
								
								mail.php
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								mail.php
									
									
									
									
									
								
							| @ -1,46 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| $token = $_POST['token']; | ||||
| $message = $_POST['message']; | ||||
| 
 | ||||
| if ($token !== '1445') { | ||||
|     die("Error: invalid token."); | ||||
| } | ||||
| 
 | ||||
| if (!$message) { | ||||
|     die("Error: invalid message (or lack thereof)"); | ||||
| } | ||||
| 
 | ||||
| $conn = mysql_connect(":/tmp/mysql.sock", "root", ""); | ||||
| if (!$conn) { | ||||
|     die("MySQL connection error: " . mysql_error()); | ||||
| } | ||||
| mysql_select_db("mileslinden", $conn); | ||||
| 
 | ||||
| $result = mysql_query("SELECT * FROM subscribers"); | ||||
| $to_emails = array(); | ||||
| 
 | ||||
| while ($row = mysql_fetch_assoc($result)) { | ||||
|     $to_emails[] = $row["email"]; | ||||
| } | ||||
| 
 | ||||
| $to = implode(", ", $to_emails); | ||||
| $headers = array( | ||||
|     'From: no-reply@mileslinden.com', | ||||
|     'Reply-To: no-reply@mileslinden.com', | ||||
|     'X-Mailer: PHP/' . phpversion() | ||||
| ); | ||||
| if (!mail($to, "MILES LINDEN CAMPAIGN ALERT", $message, implode("\r\n", $headers))) { | ||||
|     die("Error: failed to send email message."); | ||||
| } | ||||
| ?>
 | ||||
| <!DOCTYPE HTML> | ||||
| <html lang="en"> | ||||
|     <head> | ||||
|         <meta charset="utf-8"> | ||||
|         <title>Miles Linden for San Jose City Council</title> | ||||
|     </head> | ||||
|     <body> | ||||
|         <h1>Great success!</h1> | ||||
|     </body> | ||||
| </html> | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| #ini_set('display_errors', 1);
 | ||||
| 
 | ||||
| $email = $_POST['email']; | ||||
| $fname = $_POST['full_name']; | ||||
| $phone = $_POST['phone']; | ||||
| $gender = $_POST['gender']; | ||||
| $gender = isset($_POST['gender']) && $_POST['gender']; | ||||
| 
 | ||||
| $pattern = '/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD'; | ||||
| 
 | ||||
| @ -15,34 +16,35 @@ if (strlen($phone_num) == 11) | ||||
| 	$phone_num = preg_replace("/^1/", '', $phone_num); | ||||
| 
 | ||||
| if (!$email || preg_match($pattern, $email) !== 1 || !$fname || strlen($phone_num) != 10) { | ||||
|     die("Error: An email address, first name, and last name are required."); | ||||
|     http_response_code(400); | ||||
|     die(json_encode([ | ||||
| 	    'field' => 'email', | ||||
| 	    'message' => 'Error: An email address, first name, and last name are required.' | ||||
|     ])); | ||||
| } | ||||
| if ($gender && $gender !== 'm' && $gender !== 'f') { | ||||
|     die("Error: An invalid gender was given."); | ||||
|     http_response_code(400); | ||||
|     die(json_encode([ | ||||
| 	    'field' => 'full_name', | ||||
| 	    'message' => 'Error: An invalid gender was given.' | ||||
|     ])); | ||||
| } | ||||
| 
 | ||||
| $conn = mysql_connect(":/tmp/mysql.sock", "root", ""); | ||||
| if (!$conn) { | ||||
|     die("MySQL connection error: " . mysql_error()); | ||||
| } | ||||
| mysql_select_db("mileslinden", $conn); | ||||
| $conn = new mysqli("localhost", "mileslinden", "Daiso@6969", "mileslinden"); | ||||
| 
 | ||||
| $query = sprintf( | ||||
|     "INSERT INTO subscribers (`email`, `full_name`, `phone`, `gender`, `join_date`) ". | ||||
|     "VALUES ('%s', '%s', '%s', '%s', '%s')", | ||||
|     mysql_real_escape_string($email), | ||||
|     mysql_real_escape_string($fname), | ||||
|     mysql_real_escape_string($phone), | ||||
|     mysql_real_escape_string($gender), | ||||
| $query = $conn->prepare( | ||||
|     "INSERT INTO subscribers (`email`, `full_name`, `phone`, `gender`, `join_date`) VALUES (?, ?, ?, ?, ?)" | ||||
| ); | ||||
| if (!$query) { | ||||
|     http_response_code(500); | ||||
|     die(json_encode(['message' => $conn->error])); | ||||
| } | ||||
| $query->bind_param( | ||||
|     "sssss", | ||||
|     $email, $fname, $phone_num, $gender, | ||||
|     date("Y-m-d H:i:s") | ||||
| ); | ||||
| $res = mysql_query($query); | ||||
| 
 | ||||
| if (!$res) { | ||||
|     die("MySQL query error: " . mysql_error()); | ||||
| } | ||||
| 
 | ||||
| mysql_close($conn); | ||||
| $query->execute(); | ||||
| 
 | ||||
| ?>
 | ||||
| <!DOCTYPE HTML> | ||||
| @ -52,6 +54,6 @@ mysql_close($conn); | ||||
|         <title>Miles Linden for San Jose City Council</title> | ||||
|     </head> | ||||
|     <body> | ||||
|         <h1>You have subscribed successfully!</h1> | ||||
|         <h1>You have subscribed successfully.</h1> | ||||
|     </body> | ||||
| </html> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user