https://dexlaos-it.blogspot.com/
Web Apps ระบบสมาชิก (Sign Up, Sign in, Encode Password, Forget Password)
ความสามารถของระบบ
- ตรวจสอบแบบ real-time
- ตรวจสอบการใช้ email ซ้ำ
- ตรวจสอบการใช้ Username ซ้ำ
- บอกสถานะความปลอดภัยของรหัสผ่าน
- เข้ารหัส (Encode) รหัสผ่าน
- ส่งรหัสผ่านให้ทาง email กรณีผู้ใช้ลืมรหัสผ่าน
ทรัพยากรที่ใช้
- Apps Script
- Google Sheet
- Bootstrap 5
- jQuery 3.6
- Font Awesome Icons 6
- SweetAlert2
/** ============== **/ /** code.gs file **/ /** ============== **/ function doGet() { return HtmlService.createTemplateFromFile('index') .evaluate() .addMetaTag('viewport', 'width=device-width, initial-scale=1') .setTitle('Membership System') .setFaviconUrl('https://semicon.github.io/img/logoKC.png') .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL) } /** @Include Files */ function include(filename) { return HtmlService.createHtmlOutputFromFile(filename) .getContent(); } var ss = SpreadsheetApp.getActiveSpreadsheet(); var wsName = "_Your_worksheet_name_" //Chang !!!!!!!!!!!!! /** Record register */ function registForm(fullname,email,username,pwd) { var ws = ss.getSheetByName(wsName); var snRow = ws.getLastRow().toString(); var encodedata = Utilities.base64Encode(pwd, Utilities.Charset.UTF_8); ws.appendRow([snRow, fullname, email, username, encodedata]); //Logger.log(snRow); return true; } /** Check Login */ function checkLogin(username,pwd){ var userinfo = [] var encodeData = Utilities.base64Encode(pwd, Utilities.Charset.UTF_8); var data = ss.getSheetByName(wsName) .getDataRange() .getDisplayValues() .slice(1) .filter(r => r[0] !== ""); data.map(r => { if(r[3] == username && r[4] == encodeData){ userinfo = r[1] } }).join("") if(userinfo == ''){ userinfo = 'null'; } return userinfo; } /** Check Username */ function checkUsername(username) { var ws = ss.getSheetByName(wsName); var data = ws.getDataRange().getDisplayValues() var result = data.filter(r=> r[3]== username) // Logger.log(result) return result } /** Check Email */ function checkEmail(email) { var ws = ss.getSheetByName(wsName); var data = ws.getDataRange().getDisplayValues() var result = data.filter(r=> r[2]== email) //Logger.log(result) return result } /** Send Mail */ function sendEmail(email) { //email = "120@sts.ac.th" var result ='' var ws = ss.getSheetByName(wsName); var data = ws.getDataRange().getDisplayValues() .slice(1) .filter(r => r[0] !== ""); data.map(r => { if(r[2] == email){ result = r var base64data = result[4] var decoded = Utilities.base64Decode(base64data, Utilities.Charset.UTF_8); var pass = Utilities.newBlob(decoded).getDataAsString(); var subject = "แจ้งรหัสผ่านเข้าระบบ" var fname = result[1] var message = "เรียน คุณ"+fname+ "\n รหัสผ่านของท่าน คือ "+pass+ "\n ขอบคุณที่ใช้บริการของเรา"+ "\n https://guruchian.blogspot.com/" MailApp.sendEmail(email, subject, message) } }); var mailx = '' if (result != ''){ mailx = result[2] } return mailx }
/** ================= **/ /** index.html file **/ /** ================= **/ <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Member</title> <!-- font-awesome@6.1.1 --> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" rel="stylesheet"/> <!-- bootstrap@5.1.3 --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> <!-- jquery --> <script src="https://code.jquery.com/jquery-3.6.0.js"></script> <link href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" > <script src="//code.jquery.com/jquery-1.12.4.js"></script> <script src="//code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <!-- animate.css@4.1.1 --> <link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" rel="stylesheet"/> <!-- Custom CSS Styles --> <style> @import url('https://fonts.googleapis.com/css2?family=Charmonman&family=K2D:wght@300;400&display=swap'); body { margin: 5px; background: radial-gradient(rgba(0, 0, 0, 0.25), #999), url(https://pbs.twimg.com/media/CsjHEVFW8AA7uDs.jpg) 50%/cover no-repeat #000; background-blend-mode: luminosity; background-repeat: no-repeat; background-attachment: fixed; background-position: center; font-family: "K2D", monospace; font-size: 1.25rem; } .transparent { background-repeat: no-repeat; background-color:transparent !important; border: none; outline: none; color: #fff; text-decoration: none; font-size: 1.25rem; } .transparent:hover, .transparent:focus, .transparent:active, .transparent:visited { background-repeat: no-repeat; background-color:transparent !important; border: none; outline: none; color: #fff; -webkit-box-shadow: 0 2px 10px 1px rgba(0,0,0,0.5); box-shadow: 0 2px 10px 1px rgba(0,0,0,0.5); text-decoration: none; font-size: 1.25rem; } *::placeholder { color: #ccc !important; } #myProgress { width: 100%; } #my_Bar { width: 100%; height: 25px; font-size:1rem; background-color: #00000000; } #strength { width: 100%; background-color: #00000000; color: #fff; } iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0; } </style> </head> <body translate="no"> <div class="container"> <div class="row"> <div class="col-md-6 offset-md-3"> <!-- ***** Section Login *********************************************** --> <section id="secLogin" style="display:block"> <div class="card mt-5 p-4 bg-light shadow bg-opacity-10"> <div class="card bg-transparent border p-4"> <form name="form0" id="form0" autocomplete="nope"> <div class="row" > <span class="text-center py-3 text-light"> <h4>Account Login</h4> </span> <label class="text-info">Username</label> <div class="input-group mb-3 col-md-12"> <span class="py-2 pe-2"> <i id="userIcon" class="fa-solid fa-user-tie" style="color:#FB48C4;"></i> </span> <input class = "form-control transparent" type="text" id="user_name" name="user_name" placeholder="User name"> </div> <label class="text-info">Password</label> <div class="input-group mb-3 col-md-12"> <span class="py-2 pe-2"> <i id="keyIcon" class="fa-solid fa-key" style="color:#FB48C4;"></i> </span> <input class="form-control transparent" type="password" id="pass" name="pass" placeholder="Password"> </div> <div id="submit-login" class="col-12"> <button id="btn-login" class="btn btn-outline-light float-end">Signin Now</button> </div> </div> </form> </div> <div class="row mt-3"> <div class="col text-center text-light"> <span id="gotoRegist" class="px-2" role="button" tabindex="0">Signup</span> <span id="gotoRepwd" class="px-2" role="button" tabindex="0">Forgot Password ?</span> </div> <p class="text-center text-light mt-3 small">Created by <a href="https://guruchian.blogspot.com/" target="_blank" class="px-2 link-light" role="button" tabindex="0">@Dr.KruChian</a></p> </div> </div> </section> <!-- ***** Section Sing Up *********************************************** --> <section id="secSignup" style="display:none"> <div class="card p-4 bg-light shadow bg-opacity-10"> <div class="mb-2 text-light text-end"> <i id="Exit" class="fa-solid fa-circle-xmark fa-xl"></i> </div> <form name="form1" id="form1" class="p-4 card bg-transparent border" autocomplete="nope"> <div class=" row mb-3 text-center"> <h4 id='demo'></h4> </div> <div class="row" > <!-- Full Name --> <div id="input1" class="mb-3 col-md-12 " style="display:none"> <label class="text-info">Full Name</label> <div id="basic-box1" class="input-group"> <span class="col-form-label pe-1 text-info"> <i id="arrow1" class="fa-solid fa-arrow-right-long" style="color:#ff44ff; display:block"></i> <i id="right1" class="fa-solid fa-check" style="color:#00ff44; display:none"></i> <i id="xmark1"class="fa-solid fa-xmark" style="color:red; display:none"></i> </span> <input type="text" id="fullname" name="fullname" class="form-control transparent" autocomplete="nope" role="presentation" spellcheck="false" placeholder="Must be at least 6 characters"> <button id="btn-1" class="btn btn-outline-light" style="display:none" value="1">OK</button> </div> </div> <!-- Email --> <div id="input2" class="mb-3 col-md-12 " style="display:none"> <label class="text-info">Email</label> <div id="basic-box2" class="input-group "> <span class="col-form-label pe-1 text-info"> <i id="arrow2" class="fa-solid fa-arrow-right-long" style="color:#ff44ff; display:block"></i> <i id="right2" class="fa-solid fa-check" style="color:#00ff44; display:none"></i> <i id="xmark2"class="fa-solid fa-xmark" style="color:red; display:none"></i> </span> <input type="email" id="email" name="email" class="form-control transparent" autocomplete="nope" role="presentation" spellcheck="false" placeholder=""> <button id="btn-2" class="btn btn-outline-light" style="display:none" value="2">OK</button> </div> </div> <!-- Username --> <div id="input3" class="mb-3 col-md-12 " style="display:none"> <label class="text-info">Username</label> <div id="basic-box3" class="input-group "> <span class="col-form-label pe-1 text-info"> <i id="arrow3" class="fa-solid fa-arrow-right-long" style="color:#ff44ff; display:block"></i> <i id="right3" class="fa-solid fa-check" style="color:#00ff44; display:none"></i> <i id="xmark3"class="fa-solid fa-xmark" style="color:red; display:none"></i> </span> <input type="text" id="username" name="username"class="form-control transparent" autocomplete="nope" role="presentation" spellcheck="false" placeholder="Must be at least 8 characters" > <button id="btn-3" class="btn btn-outline-light" style="display:none" value="3">OK</button> </div> </div> <!-- Password --> <div id="input4" class="mb-3 col-md-12 " style="display:none"> <label class="text-info">Password</label> <div id="basic-box4" class="input-group"> <span class="col-form-label pe-1 text-info"> <i id="arrow4" class="fa-solid fa-arrow-right-long" style="color:#ff44ff; display:block"></i> <i id="right4" class="fa-solid fa-check" style="color:#00ff44; display:none"></i> <i id="xmark4"class="fa-solid fa-xmark" style="color:red; display:none"></i> </span> <input type="password" id="pswd1" name="pswd1" class="form-control transparent" autocomplete="off" role="presentation" spellcheck="false" placeholder=""> <button id="btn-4" class="btn btn-outline-light" style="display:none" value="4">OK</button> </div> <div id="myProgress"> <div id="myBar" class="text-center"> <span class="text-center" id="strength"></span> </div> </div> </div> <!-- Confirm password --> <div id="input5" class="mb-3 col-md-12 " style="display:none"> <label class="text-info">Confirm password</label> <div id="basic-box5" class="input-group "> <span class="col-form-label pe-1 text-info"> <i id="arrow5" class="fa-solid fa-arrow-right-long" style="color:#ff44ff; display:block"></i> <i id="right5" class="fa-solid fa-check" style="color:#00ff44; display:none"></i> <i id="xmark5"class="fa-solid fa-xmark" style="color:red; display:none"></i> </span> <input type="password" id="pswd2" name="pswd2" class="form-control transparent" autocomplete="nope" role="presentation" spellcheck="false" placeholder="" > <button id="btn-5" class="btn btn-outline-light" value="5">OK</button> </div> </div> <div id="box-submit"class="col-md-12" style="display:none"> <button id="btn-submit" class="btn btn-outline-light float-end">Signup Now</button> </div> </form> </div> </section> <!-- ***** Modal Forgot password *********************************************** --> <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">Forgot password</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <div id="sendmail-box" class="input-group py-3 mb-3"> <p>Enter your account's verified email address and we'll send you a password.</p> <div class="input-group-text"> <i class="fa-solid fa-envelope"></i> </div> <input type="email" id="sendmail" name="sendmail" class="form-control" autocomplete="off" role="presentation" spellcheck="false" placeholder=""> <button id="btn-sendmail" class="btn btn-outline-secondary">Send</button> </div> </div> </div> </div> </div> </div> </div> </div> <!-- ***** Section Main Page *********************************************** --> <section id="main" style="display:none;"> <?!=include('main')?> </section> <!-- /******************** Other scripts ****************************************/ --> <!-- Include javascript files --> <?!=include('main_js')?> <!-- /-------- Sweetaler 2011 --------/ --> <script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script> </body> </html>/** =================== **/ /** main_js.html file **/ /** =================== **/ <script> /** ****************************************** **/ /** *************** Page Sign Up *************** **/ /** ****************************************** **/ $(document).ready(function() { $("#user_name").focus(); try { $("input").each(function() { $(this).attr("autocomplete", "nope"); $(this).prop("autocomplete", true); }); } catch (e) {} }); /** Text Typing Animation **/ var i = 0; $("#demo").addClass("text-light"); var txt = `Welcome to blog GuruChian!, Let’s begin the adventure!`; var speed = 50; var idElmDiv = {} var idElement = {} function typeWriter() { if (i < txt.length) { let text = txt.charAt(i); document.getElementById("demo").innerHTML += text === "," ? "<br/>": text; i++; setTimeout(typeWriter, speed); } else{ setCursorPosition() } } /** Set Cursor Position **/ function setCursorPosition(){ $("#input1").show(); $("#fullname").focus(); } /** When clicking the "OK" button **/ $("button").click(function() { event.preventDefault(); var idButton = Number(this.value); var idDiv = Number(idButton + 1); if(idButton > 0){ $( this).hide(); $(this).prev("input").prop('disabled', true); $(this).next("input").focus().val(''); $("#input"+idDiv).show(); $( "i[id ='right"+idButton+"']" ).show(); $( "i[id ='arrow"+idButton+"']" ).hide(); $( "i[id ='xmark"+idButton+"']" ).hide(); console.log(idDiv); $('input','#email').focus(); if(idButton == 4){ $("#myProgress").hide(); } } }); /** When clicking the "Exit" button **/ $("#Exit").click(function() { $("#secSignup").hide() $("#secLogin").show() }); /** Check the length of the full name. **/ $( "#fullname" ).keyup(function() { var fInput = this.value; if(fInput.length > 5){ $(this).next().show(); console.log(fInput); } else{ $(this).next().hide(); } }); /** Email Validation in JavaScript **/ $('#email').keyup(function() { $(".error").hide(); var hasError = false; var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/; var emailblockReg = /^([\w-\.]+@(?!gmail.com)(?!yahoo.com)(?!hotmail.com)([\w-]+\.)+[\w-]{2,4})?$/; var emailaddressVal = $("#email").val(); if(emailaddressVal == '') { //$("#email").after('<span class="error">Please enter your email address.</span>'); hasError = true; } else if(!emailReg.test(emailaddressVal)) { //$("#email").after('<span class="error">Enter a valid email address.</span>'); hasError = true; } else if(!emailblockReg.test(emailaddressVal)) { //$("#email").after('<span class="error">No yahoo, gmail or hotmail emails.</span>'); hasError = true } if(hasError == true) { $( "#btn-2" ).hide(); $( "i[id ='xmark2']" ).show(); $( "i[id ='arrow2']" ).hide(); return false; } else{ $( "#btn-2" ).show(); $( "i[id ='xmark2']" ).hide(); $( "i[id ='arrow2']" ).show(); } }); /** Check email registration **/ $("#btn-2").click(function() { event.preventDefault(); var email = $("#email").val(); google.script.run.withSuccessHandler(function(output){ if(output != ""){ $('#input3').hide(); $('input[id = "email"]').prop('disabled', false); $('i[id = "xmark2"]').show(); $('i[id = "right2"]').hide(); //$(this).show(); } }).checkEmail(email) }); /** Check the length of the Username. **/ $( "#username" ).keyup(function() { var uInput = this.value; if(uInput.length >= 8){ $(this).next().show(); console.log(uInput); } else{ $(this).next().hide(); } }); /** Check username registration **/ $("#btn-3").click(function() { event.preventDefault(); var username = $("#username").val(); google.script.run.withSuccessHandler(function(output){ if(output != ""){ $('#input4').hide(); $('input[id = "username"]').prop('disabled', false); $('i[id = "xmark3"]').show(); $('i[id = "right3"]').hide(); //$(this).show(); } }).checkUsername(username) }); /** Password Strength Checker **/ $("#pswd1").keyup(function(){ var strongRegex = new RegExp("^(?=.{14,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$", "g"); var mediumRegex = new RegExp("^(?=.{10,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$", "g"); var enoughRegex = new RegExp("(?=.{8,}).*", "g"); var pwd = $('#pswd1').val(); $("#myBar").show(); if (pwd.length >= 8) { $('#btn-4').show(); $( "i[id ='xmark4']" ).hide(); $( "i[id ='arrow4']" ).show(); } else{ $( "i[id ='xmark4']" ).show(); $( "i[id ='arrow4']" ).hide(); $('#btn-4').hide(); } if (pwd.length == 0) { $("#strength").html("Type Password!"); $("#myBar").css("width","100%"); $("#myBar").css("background","#00000000"); } else if (false == enoughRegex.test(pwd)) { $("#strength").html("More Characters!"); $("#myBar").css("width","100%"); $("#myBar").css("background","#00000000"); } else if (strongRegex.test(pwd)) { $("#strength").html("Strong!"); $("#myBar").css("width","100%"); $("#myBar").css("background","#00ff00"); } else if (mediumRegex.test(pwd)) { $("#strength").html("Medium!"); $("#myBar").css("width","65%"); $("#myBar").css("background","#ffc300"); } else { $("#strength").html("Weak!"); $("#myBar").css("width","40%"); $("#myBar").css("background","#ff0000"); } }); /** Check for matching passwords. **/ $("#btn-5").click(function() { event.preventDefault(); var pwd1 = $("#pswd1").val(); var pwd2 = $("#pswd2").val(); if(pwd1.length < 8 || pwd2.length < 8 || pwd1 != pwd2) { $(this).show(); $("#input4").show(); $('input[name ^= "pswd"]').prop('disabled', false); $('input[name ^= "pswd"]').val(""); $("#input5").hide(); $("i[id ='right4']").hide(); $("i[id ='arrow4']").show(); $("#strength").html("Type Password!"); $("#myBar").css("width","100%"); $("#myBar").css("background","#00000000"); } else { $("#box-submit").show(); } }); /** Record to Spreadsheet **/ $("#btn-submit").click(function(){ event.preventDefault(); var fullname = $("#fullname").val(); var email = $("#email").val(); var username = $("#username").val(); var pwd = $("#pswd1").val(); google.script.run.withSuccessHandler(function(output){ if(output == true){ $("#form1").trigger("reset"); $("input").prop('disabled', false); $('i[id ^= "right"]').hide(); $('i[id ^= "arrow"]').show(); $('div').hide(); } }).registForm(fullname,email,username,pwd); console.log(fullname,email,username,pwd) }); /** ****************************************** **/ /** *************** Page Login *************** **/ /** ****************************************** **/ /** When clicking the "Signup" button **/ $("#gotoRegist").click(function() { $("#secSignup").show() $("#secLogin").hide() $("#demo").html("") i=0 typeWriter() $("#demo").addClass("text-info"); }); /** When clicking the "Forgot password" button **/ $("#gotoRepwd").click(function() { $("#exampleModal").modal("show"); }); /*************** Login Script **********************/ $("#btn-login").click(function(){ event.preventDefault(); var username = $("#user_name").val(); var pwd = $("#pass").val(); google.script.run.withSuccessHandler(function(output){ if(output != 'null'){ var msg = output; Swal.fire({ title: 'ยินดีต้อนรับ !', html: '<h5>'+output+'</h5>', showClass: { popup: 'animate__animated animate__fadeInDown' }, hideClass: { popup: 'animate__animated animate__fadeOutUp' } }); $("#main").show(); $("#secLogin").hide(); } else if(output == 'null'){ Swal.fire({ title: 'ขออภัย !', html: '<h5>ข้อมูลไม่ถูกต้อง</h5>', showClass: { popup: 'animate__animated animate__fadeInDown' }, hideClass: { popup: 'animate__animated animate__fadeOutUp' } }); } }).checkLogin(username,pwd); }); /** Send an email requesting a new password. **/ $("#btn-sendmail").click(function() { event.preventDefault(); var email = $("#sendmail").val(); google.script.run.withSuccessHandler(function(output){ $("#exampleModal").modal("hide"); if(output != ""){ $("#sendmail").val(""); Swal.fire({ title: 'ดำเนินการเรียบร้อย !', html: '<h5>เราส่งรหัสผ่านของท่านไปที่ '+output+'</h5>', showClass: { popup: 'animate__animated animate__fadeInDown' }, hideClass: { popup: 'animate__animated animate__fadeOutUp' } }); } else{ $("#sendmail").val(""); Swal.fire({ title: 'ขออภัย !', html: '<h5>ไม่พบข้อมูลของท่าน</h5>', showClass: { popup: 'animate__animated animate__fadeInDown' }, hideClass: { popup: 'animate__animated animate__fadeOutUp' } }); } }).sendEmail(email) }); </script>/** ================ **/ /** main.html file **/ /** ================ **/ <iframe src="https://guruchian.blogspot.com/" loading="lazy"></iframe>

.png)