فهرست منبع

新功能 忘记密码发送重置密码邮件

visuddhinanda 4 سال پیش
والد
کامیت
f41988de2b
4فایلهای تغییر یافته به همراه520 افزوده شده و 0 حذف شده
  1. 43 0
      app/api/user.php
  2. 220 0
      app/db/user.php
  3. 244 0
      app/ucenter/forgot_pwd.php
  4. 13 0
      app/ucenter/reset_pwd_letter.html

+ 43 - 0
app/api/user.php

@@ -0,0 +1,43 @@
+<?php
+require_once "../db/user.php";
+require_once "../redis/function.php";
+require_once "../public/function.php";
+
+$model = new User(redis_connect());
+
+switch ($_REQUEST["_method"]) {
+	case 'index':
+		# get
+		$model->index();
+		break;
+	case 'list':
+		# post
+		$model->list();
+		break;
+	case 'create':
+		# post
+		$model->create();
+		break;
+	case 'show':
+		# get
+		$model->show();
+		break;	
+	case 'update':
+		# post
+		$model->update();
+		break;	
+	case 'delete':
+		# get
+		$model->delete();
+		break;
+	case 'reset_email':
+		# get
+		$model->reset_password_send_email();
+		break;	
+	default:
+		# code...
+		break;
+}
+
+
+?>

+ 220 - 0
app/db/user.php

@@ -0,0 +1,220 @@
+<?php
+require_once "../path.php";
+require_once "../db/table.php";
+require_once "../public/function.php";
+// Require Composer's autoloader.
+require_once '../../vendor/autoload.php';
+require_once '../config.php';
+
+// Using Medoo namespace.
+use Medoo\Medoo;
+
+// Require Composer's autoloader.
+use PHPMailer\PHPMailer\PHPMailer;
+use PHPMailer\PHPMailer\SMTP;
+use PHPMailer\PHPMailer\Exception;
+/*
+CREATE TABLE likes (
+    id            INTEGER      PRIMARY KEY AUTOINCREMENT,
+    like_type     VARCHAR (16) NOT NULL,
+    resource_type VARCHAR (32) NOT NULL,
+    resource_id   CHAR (36)    NOT NULL,
+    user_id       INTEGER      NOT NULL,
+    created_at    TIMESTAMP DEFAULT CURRENT_TIMESTAMP     NOT NULL //只做初始化,更新时不自动更新
+);
+*/
+class User extends Table
+{
+    function __construct($redis=false) {
+		parent::__construct(_FILE_DB_USERINFO_, "user", "", "",$redis);
+    }
+
+	public function  index(){
+		$where["like_type"] = "like";
+		$where["resource_type"] = $_GET["type"];
+		$where["resource_id"] = explode($_GET["id"],",");
+		echo json_encode($this->_index(["resource_id","user_id"],$where), JSON_UNESCAPED_UNICODE);
+	}
+	
+	public function  list(){
+		if(!isset($_COOKIE["userid"])){
+			$userId = $_COOKIE["userid"];
+		}
+
+		$json = file_get_contents('php://input');
+		$data = json_decode($json,true);
+		foreach ($data as $key => $value) {
+			# code...
+			$data[$key]['like']=$this->medoo->count($this->table,[
+											'like_type'=>$value['like_type'],
+											'resource_type'=>$value['resource_type'],
+											'resource_id'=>$value['resource_id'],
+											  ]);
+		}
+		if(isset($_COOKIE["userid"])){
+			$userId = $_COOKIE["userid"];
+			foreach ($data as $key => $value) {
+				# code...
+				$data[$key]['me']=$this->medoo->count($this->table,[
+												'like_type'=>$value['like_type'],
+												'resource_type'=>$value['resource_type'],
+												'resource_id'=>$value['resource_id'],
+												'user_id'=>$userId,
+												]);
+			}
+		}
+
+		$this->result["ok"]=true;
+		$this->result["message"]="";
+		$this->result["data"]=$data;
+		echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+
+	}
+
+
+	public function  create(){
+		if(!isset($_COOKIE["userid"])){
+			return;
+		}
+		$json = file_get_contents('php://input');
+		$data = json_decode($json,true);
+		$data["user_id"] = $_COOKIE["userid"];
+		$isExist = $this->medoo->has("likes",$data);
+		if(!$isExist){
+			echo json_encode($this->_create($data,["like_type","resource_type","resource_id","user_id"]), JSON_UNESCAPED_UNICODE);
+		}
+		else{
+			$this->result["ok"]=false;
+			$this->result["message"]="is exist";
+			echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+		}
+	}
+	
+	public function  delete(){
+		if(!isset($_COOKIE["userid"])){
+			return;
+		}
+		$where["like_type"] = $_GET["like_type"];
+		$where["resource_type"] = $_GET["resource_type"];
+		$where["resource_id"] = $_GET["resource_id"];
+		$where["user_id"] = $_COOKIE["userid"];
+		$row = $this->_delete($where);
+		if($row["data"]>0){
+			$this->result["data"] = $where;
+		}else{
+			$this->result["ok"]=false;
+			$this->result["message"]="no delete";			
+		}
+		echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+	}
+
+	#发送密码重置邮件
+	public function reset_password_send_email(){
+		$email = $_GET["email"];
+		$isExist = $this->medoo->has($this->table,["email"=>$email]);
+		if($isExist){
+			$resetToken = UUID::v4();
+			$ok = $this->_update(["reset_password_token"=>$resetToken],["reset_password_token"],["email"=>$email]);
+			if($ok){
+				#send email
+				$resetLink="https://www.wikipali.org/ucenter/reset.php?token=".$resetToken;
+				$resetString="https://www.wikipali.org/ucenter/reset.php?token=".$resetToken;
+		
+					// 打开文件并读取数据
+				$irow=0;
+				$strSubject = "";
+				$strBody = "";
+				if(($fp=fopen("../ucenter/reset_pwd_letter.html", "r"))!==FALSE){
+					while(($data=fgets($fp))!==FALSE){
+						$irow++;
+						if($irow==1){
+							$strSubject = $data; 
+						}else{
+							$strBody .= $data; 
+						}
+					}
+					fclose($fp);
+				}
+				else{
+					$this->result["ok"] = false;
+					$this->result["message"] = "can not load email file.";
+					echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+					return;
+				}
+		
+				$strBody = str_replace("%resetLink%",$resetLink,$strBody);
+				$strBody = str_replace("%resetString%",$resetString,$strBody);
+		
+				//TODO sendmail
+		
+				//Create an instance; passing `true` enables exceptions
+				$mail = new PHPMailer(true);
+		
+				try {
+					//Server settings
+					$mail->SMTPDebug = SMTP::DEBUG_OFF;                      //Enable verbose debug output
+					$mail->isSMTP();                                            //Send using SMTP
+					$mail->Host       = Email["Host"];                     //Set the SMTP server to send through
+					$mail->SMTPAuth   = Email["SMTPAuth"];                                   //Enable SMTP authentication
+					$mail->Username   = Email["Username"];                     //SMTP username
+					$mail->Password   = Email["Password"];                               //SMTP password
+					$mail->SMTPSecure = Email["SMTPSecure"];            //Enable implicit TLS encryption
+					$mail->Port       = Email["Port"];                                    //TCP port to connect to 465; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
+		
+					//Recipients
+					$mail->setFrom(Email["From"], Email["Sender"]);
+					$mail->addAddress($email);     //Add a recipient Name is optional
+		
+					//Content
+					$mail->isHTML(true);                                  //Set email format to HTML
+					$mail->Subject = $strSubject;
+					$mail->Body    = $strBody;
+					$mail->AltBody = $strBody;
+		
+					$mail->send();
+					#邮件发送成功,修改数据库
+					$this->_update(["reset_password_sent_at"=>Medoo::raw('datetime(<now>)')],["reset_password_sent_at"],["email"=>$email]);
+					//邮件地址脱敏
+					$show_email = mb_substr($email,0,2,"UTF-8") . "****" . strstr($email,"@");
+					$this->result["message"] = 'Message has been sent to your email : ' . $show_email;
+					echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+					return;
+
+				} catch (Exception $e) {
+					$this->result["ok"] = false;
+					$this->result["message"] = "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
+					echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+					return;
+				}
+			}else{
+				echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+				return;
+			}
+		}else{
+			$this->result["ok"]=false;
+			$this->result["message"]="invalid email";
+			echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+		}
+	}
+
+	#重置密码
+	public function reset_password($username,$password,$token){
+		$isExist = $this->medoo->has($this->table,["user_name"=>$username,"token"=>$token]);
+		if($isExist){
+			#reset password
+			$ok = $this->_update(["password"=>$password],"password",["user_name"=>$username]);
+			if($ok){
+				echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+				
+			}else{
+				echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+			}
+		}else{
+			$this->result["ok"]=false;
+			$this->result["message"]="invalid token";
+			echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
+		}
+	}
+}
+
+?>

+ 244 - 0
app/ucenter/forgot_pwd.php

@@ -0,0 +1,244 @@
+<?php
+#忘记
+require_once '../path.php';
+require_once "../public/load_lang.php";
+require_once "../public/function.php";
+
+?>
+
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+		<meta name="viewport" content="width=device-width, initial-scale=1.0">
+		<link type="text/css" rel="stylesheet" href="../studio/css/font.css"/>
+		<link type="text/css" rel="stylesheet" href="../studio/css/style.css"/>
+		<link type="text/css" rel="stylesheet" href="../studio/css/color_day.css" id="colorchange" />
+		<title>wikipali reset password</title>
+		<script src="../public/js/comm.js"></script>
+		<script src="../studio/js/jquery-3.3.1.min.js"></script>
+		<script src="../studio/js/fixedsticky.js"></script>
+		<style>
+		#login_body{
+			display: flex;
+			padding: 2em;
+			margin: auto;
+		}
+		#login_left {
+			padding-right: 12em;
+			padding-top: 5em;
+		}
+		.title{
+			font-size: 150%;
+			margin-top: 1em;
+			margin-bottom: 0.5em;
+		}
+		#login_form{
+			padding: 2em 0 1em 0;
+		}
+		#tool_bar {
+			padding: 1em;
+			display: flex;
+			justify-content: space-between;
+		}
+		#login_shortcut {
+			display: flex;
+			flex-direction: column;
+			padding: 2em 0;
+		}
+		#login_shortcut button{
+			height:3em;
+		}
+		#button_area{
+			text-align: right;
+				padding: 1em 0;
+		}
+		.form_help{
+			font-weight: 400;
+			color: var(--bookx);
+		}
+		.login_form input{
+			margin-top:2em;
+			padding:0.5em 0.5em;
+		}
+		.login_form select{
+			margin-top:2em;
+			padding:0.5em 0.5em;
+		}
+		.login_form input[type="submit"]{
+			margin-top:2em;
+			padding:0.1em 0.5em;
+		}
+
+		.form_error{
+			color:var(--error-text);
+		}
+		#login_form_div{
+			width:30em;
+		}
+
+		#ucenter_body {
+			display: flex;
+			flex-direction: column;
+			margin: 0;
+			padding: 0;
+			background-color: var(--tool-bg-color3);
+			color: var(--btn-color);
+		}
+		.icon_big {
+			height: 2em;
+			width: 2em;
+			fill: var(--btn-color);
+			transition: all 0.2s ease;
+		}
+		.form_field_name{
+			position: absolute;
+			margin-left: 7px;
+			margin-top: 2em;
+			color: var(--btn-border-line-color);
+			-webkit-transition-duration: 0.4s;
+			-moz-transition-duration: 0.4s;
+			transition-duration: 0.4s;
+			transform: translateY(0.5em);
+		}
+		.viewswitch_on {
+			position: absolute;
+			margin-left: 7px;
+			margin-top: 1.5em;
+			color: var(--bookx);
+			-webkit-transition-duration: 0.4s;
+			-moz-transition-duration: 0.4s;
+			transition-duration: 0.4s;
+			transform: translateY(-15px);
+		}
+
+		</style>
+
+		<script>
+
+		function login_init(){
+			$("input").focus(function(){
+				let name = $(this).attr("name");
+				var objNave = document.getElementById("tip_"+name);
+				objNave.className = "viewswitch_on";
+			});
+			$(".form_field_name").click(function(){
+				let id = $(this).attr("id");
+				var objNave = document.getElementById(id);
+				objNave.className = "viewswitch_on";
+				let arrId=id.split("_");
+				document.getElementById('input_'+arrId[1]).focus();
+			});
+
+		}
+		</script>
+	<link type="text/css" rel="stylesheet" href="mobile.css" media="screen and (max-width:800px)">
+	</head>
+	<body id="ucenter_body" onload="login_init()">
+
+	<div id="tool_bar">
+	</div>
+<div id="login_body" >
+
+	<div id="login_left">
+		<div  >
+			<svg  style="height: 8em;width: 25em;">
+				<use xlink:href="../public/images/svg/wikipali_login_page.svg#logo_login"></use>
+			</svg>
+		</div>
+		<div style="    padding: 1em 0 0 3.5em;font-weight: 400;">
+		<?php echo $_local->gui->pali_literature_platform; ?>
+		<ul style="padding-left: 1.2em;">
+			<li><?php echo $_local->gui->online_dict_db; ?></li>
+			<li><?php echo $_local->gui->user_data_share; ?></li>
+			<li><?php echo $_local->gui->cooperate_edit; ?></li>
+		</ul>
+		</div>
+	</div>
+	<div id="login_right">
+		<div id = "login_form_div" class="fun_block" >
+
+			<div class="title">
+			忘记密码?
+			</div>
+			<div class="login_new">
+				<span class="form_help"><?php echo $_local->gui->have_account; ?> ?</span><a href="index.php?language=<?php echo $currLanguage; ?>">&nbsp;&nbsp;&nbsp;&nbsp;<?php echo $_local->gui->login; //登入账户 ?></a>
+			</div>
+
+			<div class="login_form" style="    padding: 3em 0 3em 0;">
+			<div class="form_help">
+				我们将向您的注册邮箱发送电子邮件。里面包含了重置密码链接。点击链接后按照提示操作,重置账户密码。
+			</div>
+			<div class="form_help" id="message"> </div>			
+				<form action="../api/user.php" method="get">
+					<div>
+						<div>
+							<span id='tip_email' class='form_field_name'><?php echo $_local->gui->email_address; ?></span>
+							<input id="form_email" type="input" name="email"  value="" />
+						</div>
+						<div id="error_email" class="form_error"> </div>
+						<div class="form_help"></div>
+					</div>
+
+					<input type="hidden" name="_method" value="reset_email" />
+
+
+				</form>
+					<div id="button_area">
+						<button  onclick="submit()" style="background-color: var(--link-hover-color);border-color: var(--link-hover-color);" >
+						<?php echo $_local->gui->continue; ?>
+						</button>
+					</div>				
+			</div>
+		</div>
+	</div>
+</div>
+
+	<script>
+	login_init();
+		function submit(){
+			$.getJSON(
+		"../api/user.php",
+		{
+			_method:"reset_email",
+			email:$("#form_email").val()
+		}
+	).done(function (data) {
+		$("#message").text(data.message);
+		if(data.ok){
+			$("#message").removeClass("form_error");
+		}else{
+			$("#message").addClass("form_error");
+		}
+	}).fail(function(jqXHR, textStatus, errorThrown){
+		$("#message").removeClass("form_error");
+		$("#message").text(textStatus);				
+		switch (textStatus) {
+	
+			case "timeout":
+				break;
+			case "error":
+				switch (jqXHR.status) {
+					case 404:
+						break;
+					case 500:
+						break;				
+					default:
+						break;
+				}
+				break;
+			case "abort":
+				break;
+			case "parsererror":			
+				console.log("delete-parsererror",jqXHR.responseText);
+				break;
+			default:
+				break;
+		}
+		
+	});
+		}
+	</script>
+
+	</body>
+</html>

+ 13 - 0
app/ucenter/reset_pwd_letter.html

@@ -0,0 +1,13 @@
+wikipali reset password
+<p>
+您收到这封邮件是因为系统接到您的账号需要重置密码的申请。<br>
+如果您没有进行过此操作请忽略这个邮件。
+</p>
+<p>
+点击此链接重置您的wikipali账号的密码。
+<a href="%ResetLink%">%ResetString%</a>
+</p>
+<p>
+	此链接包含重置密码所需要的密钥。请勿发给他人。
+	此邮件为系统自动发送,请勿回复。
+</p>