changeset 117:e2deb5236f26

better login
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 04 Dec 2025 21:43:47 -0700
parents 98b2dc732ca0
children 04933d5ba05a
files src/do_login.html.luan src/lib/Shared.luan src/lib/User.luan src/login.html.luan src/login.js.luan src/login_sent.html.luan src/manual_login.html.luan src/manual_login.js.luan src/register.html.luan src/register.js.luan src/register_sent.html.luan
diffstat 11 files changed, 177 insertions(+), 209 deletions(-) [+]
line wrap: on
line diff
--- a/src/do_login.html.luan	Thu Dec 04 12:13:01 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-local ipairs = Luan.ipairs or error()
-local Table = require "luan:Table.luan"
-local concat = Table.concat or error()
-local Html = require "luan:Html.luan"
-local url_encode = Html.url_encode or error()
-local Io = require "luan:Io.luan"
-local Http = require "luan:http/Http.luan"
-local Shared = require "site:/lib/Shared.luan"
-local head = Shared.head or error()
-local header = Shared.header or error()
-local User = require "site:/lib/User.luan"
-local Utils = require "site:/lib/Utils.luan"
-local to_list = Utils.to_list or error()
-
-
-return function()
-	local user_id = Http.request.parameters.user or error()
-	local password = Http.request.parameters.password or error()
-	local user = User.get_by_id(user_id)
-	Io.stdout = Http.response.text_writer()
-%>
-<!doctype html>
-<html lang="en">
-	<head>
-<%		head() %>
-	</head>
-	<body>
-<%		header() %>
-		<div content>
-			<h1>Login / Register</h1>
-<%	if user == nil or user.password ~= password then %>
-			<p>Login failed</p>
-<%
-	else
-		user.login()
-		local spy = Http.request.parameters.spy ~= nil
-		if spy then
-			Http.response.set_cookie("spy","yes")
-		else
-			Http.response.remove_cookie("spy")
-		end
-		local with = Http.request.parameters.with
-		local location
-		if with == nil then
-			location = "/"
-		else
-			with = to_list(with)
-			local t = {}
-			for _, email in ipairs(with) do
-				t[#t+1] = "with="..url_encode(email)
-			end
-			location = "/chat?"..concat(t,"&")
-		end
-%>
-			<script> location = '<%=location%>'; </script>
-<%
-	end
-%>
-		</div>
-	</body>
-</html>
-<%
-end
--- a/src/lib/Shared.luan	Thu Dec 04 12:13:01 2025 -0700
+++ b/src/lib/Shared.luan	Thu Dec 04 21:43:47 2025 -0700
@@ -2,6 +2,8 @@
 local error = Luan.error
 local ipairs = Luan.ipairs or error()
 local parse = Luan.parse or error()
+local String = require "luan:String.luan"
+local contains = String.contains or error()
 local Table = require "luan:Table.luan"
 local concat = Table.concat or error()
 local Time = require "luan:Time.luan"
@@ -9,6 +11,7 @@
 local thread_run = Thread.run or error()
 local Html = require "luan:Html.luan"
 local html_encode = Html.encode or error()
+local url_encode = Html.url_encode or error()
 local Http = require "luan:http/Http.luan"
 local Mail = require "luan:mail/Mail.luan"
 local User = require "site:/lib/User.luan"
@@ -18,6 +21,7 @@
 local chat_search = Chat.search or error()
 local Utils = require "site:/lib/Utils.luan"
 local base_url = Utils.base_url or error()
+local to_list = Utils.to_list or error()
 local Db = require "site:/lib/Db.luan"
 local Post = require "site:/lib/Post.luan"
 local get_post_by_id = Post.get_by_id or error()
@@ -184,4 +188,25 @@
 
 Shared.compressed = {compressed=true}
 
+function Shared.add_with(path)
+	local with = Http.request.parameters.with
+	if with ~= nil then
+		with = to_list(with)
+		local t = {}
+		for _, email in ipairs(with) do
+			t[#t+1] = "with="..url_encode(email)
+		end
+		path = path..(contains(path,"?") and "&" or "?")..concat(t,"&")
+	end
+	return path
+end
+
+function Shared.hidden_with()
+	local with = Http.request.parameters.with
+	with = to_list(with)
+	for _, email in ipairs(with) do %>
+				<input type=hidden name=with value="<%=html_encode(email)%>">
+<%	end
+end
+
 return Shared
--- a/src/lib/User.luan	Thu Dec 04 12:13:01 2025 -0700
+++ b/src/lib/User.luan	Thu Dec 04 21:43:47 2025 -0700
@@ -13,6 +13,7 @@
 local concat = Table.concat or error()
 local Html = require "luan:Html.luan"
 local html_encode = Html.encode or error()
+local url_encode = Html.url_encode or error()
 local Lucene = require "luan:lucene/Lucene.luan"
 local lucene_quote = Lucene.quote or error()
 local Http = require "luan:http/Http.luan"
@@ -117,7 +118,7 @@
 	end
 
 	function user.login_url()
-		return base_url().."/do_login.html?user="..user.id.."&password="..user.password
+		return base_url().."/login.html?email="..url_encode(user.email).."&password="..user.password
 	end
 
 	return user
--- a/src/login.html.luan	Thu Dec 04 12:13:01 2025 -0700
+++ b/src/login.html.luan	Thu Dec 04 21:43:47 2025 -0700
@@ -1,20 +1,18 @@
 local Luan = require "luan:Luan.luan"
 local error = Luan.error
 local ipairs = Luan.ipairs or error()
-local Html = require "luan:Html.luan"
-local html_encode = Html.encode or error()
 local Io = require "luan:Io.luan"
 local Http = require "luan:http/Http.luan"
 local Shared = require "site:/lib/Shared.luan"
 local head = Shared.head or error()
 local header = Shared.header or error()
-local Utils = require "site:/lib/Utils.luan"
-local to_list = Utils.to_list or error()
+local hidden_with = Shared.hidden_with or error()
+local add_with = Shared.add_with or error()
 
 
 return function()
-	local with = Http.request.parameters.with
-	with = to_list(with)
+	local email = Http.request.parameters.email
+	local password = Http.request.parameters.password
 	Io.stdout = Http.response.text_writer()
 %>
 <!doctype html>
@@ -26,26 +24,34 @@
 				width: 300px;
 				max-width: 100%;
 			}
+			[failed] {
+				color: red;
+			}
 		</style>
 	</head>
 	<body>
 <%		header() %>
 		<div content>
-			<h1>Login / Register</h1>
-			<p>A link to login will be emailed to you.</p>
+			<h1>Login</h1>
 			<form page onsubmit="ajaxForm('/login.js',this)" action="javascript:">
-<%	for _, email in ipairs(with) do %>
-				<input type=hidden name=with value="<%=html_encode(email)%>">
-<%	end %>
+<%	if Http.request.parameters.spy ~= nil then %>
+				<input type=hidden name=spy>
+<%	end
+				hidden_with() %>
 				<p>
 					<label prompt>Your email address</label>
-					<input type=email name=email required autofocus>
+					<input type=email name=email required autofocus value="<%= email or "" %>">
+				</p>
+				<p>
+					<label prompt>Password</label>
+					<input name=password type=password required value="<%= password or "" %>">
 				</p>
 				<p>
 					<input type=submit>
 				</p>
+				<p failed></p>
 			</form>
-			<p><a href="manual_login.html">Password Login</a></p>
+			<p><a href="<%= add_with("register.html") %>">Register / Get Password</a></p>
 			<p><a href="about.html">About Luan Chat</a></p>
 		</div>
 	</body>
--- a/src/login.js.luan	Thu Dec 04 12:13:01 2025 -0700
+++ b/src/login.js.luan	Thu Dec 04 21:43:47 2025 -0700
@@ -1,39 +1,38 @@
 local Luan = require "luan:Luan.luan"
 local error = Luan.error
-local ipairs = Luan.ipairs or error()
-local Html = require "luan:Html.luan"
-local url_encode = Html.url_encode or error()
 local Io = require "luan:Io.luan"
 local Http = require "luan:http/Http.luan"
+local User = require "site:/lib/User.luan"
 local Shared = require "site:/lib/Shared.luan"
-local send_mail_async = Shared.send_mail_async or error()
-local Utils = require "site:/lib/Utils.luan"
-local to_list = Utils.to_list or error()
-local User = require "site:/lib/User.luan"
+local add_with = Shared.add_with or error()
 
 
 return function()
 	local email = Http.request.parameters.email or error()
-	local user = User.get_or_create_by_email(email)
-	local url = user.login_url()
-	local with = Http.request.parameters.with
-	with = to_list(with)
-	for _, email in ipairs(with) do
-		url = url.."&with="..url_encode(email)
+	local password = Http.request.parameters.password or error()
+	Io.stdout = Http.response.text_writer()
+	local user = User.get_by_email(email)
+	if user==nil or user.password ~= password then
+%>
+		document.querySelector('[failed]').textContent = 'Login failed';
+<%
+		return
 	end
-	send_mail_async {
-		To = email
-		Subject = "Login"
-		body = `%>
-Here is the link to login:
-
-<%= url %>
-
-Or login with your email and the password: <%=user.password%>
-<%		`
-	}
-	Io.stdout = Http.response.text_writer()
+	user.login()
+	local spy = Http.request.parameters.spy ~= nil
+	if spy then
+		Http.response.set_cookie("spy","yes")
+	else
+		Http.response.remove_cookie("spy")
+	end
+	local with = Http.request.parameters.with
+	local location
+	if with == nil then
+		location = "/"
+	else
+		location = add_with("/chat")
+	end
 %>
-	location = '/login_sent.html';
+	location = '<%=location%>';
 <%
 end
--- a/src/login_sent.html.luan	Thu Dec 04 12:13:01 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-local Io = require "luan:Io.luan"
-local Http = require "luan:http/Http.luan"
-local Shared = require "site:/lib/Shared.luan"
-local head = Shared.head or error()
-local header = Shared.header or error()
-
-
-return function()
-	Io.stdout = Http.response.text_writer()
-%>
-<!doctype html>
-<html lang="en">
-	<head>
-<%		head() %>
-	</head>
-	<body>
-<%		header() %>
-		<div content>
-			<h1>Login / Register</h1>
-			<p>A link to login has been emailed to you.</p>
-		</div>
-	</body>
-</html>
-<%
-end
--- a/src/manual_login.html.luan	Thu Dec 04 12:13:01 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-local ipairs = Luan.ipairs or error()
-local Html = require "luan:Html.luan"
-local html_encode = Html.encode or error()
-local Io = require "luan:Io.luan"
-local Http = require "luan:http/Http.luan"
-local Shared = require "site:/lib/Shared.luan"
-local head = Shared.head or error()
-local header = Shared.header or error()
-local Utils = require "site:/lib/Utils.luan"
-local to_list = Utils.to_list or error()
-
-
-return function()
-	Io.stdout = Http.response.text_writer()
-%>
-<!doctype html>
-<html lang="en">
-	<head>
-<%		head() %>
-		<style>
-			input[name=email] {
-				width: 300px;
-				max-width: 100%;
-			}
-			[failed] {
-				color: red;
-			}
-		</style>
-	</head>
-	<body>
-<%		header() %>
-		<div content>
-			<h1>Password Login</h1>
-			<form page onsubmit="ajaxForm('/manual_login.js',this)" action="javascript:">
-				<p>
-					<label prompt>Your email address</label>
-					<input type=email name=email required autofocus>
-				</p>
-				<p>
-					<label prompt>Password</label>
-					<input name=password required>
-				</p>
-				<p>
-					<input type=submit>
-				</p>
-				<p failed></p>
-			</form>
-		</div>
-	</body>
-</html>
-<%
-end
--- a/src/manual_login.js.luan	Thu Dec 04 12:13:01 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-local Luan = require "luan:Luan.luan"
-local error = Luan.error
-local Io = require "luan:Io.luan"
-local Http = require "luan:http/Http.luan"
-local User = require "site:/lib/User.luan"
-
-
-return function()
-	local email = Http.request.parameters.email or error()
-	local password = Http.request.parameters.password or error()
-	Io.stdout = Http.response.text_writer()
-	local user = User.get_by_email(email)
-	if user==nil or user.password ~= password then
-%>
-		document.querySelector('[failed]').textContent = 'Login failed';
-<%
-		return
-	end
-	user.login()
-%>
-	location = '/';
-<%
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/register.html.luan	Thu Dec 04 21:43:47 2025 -0700
@@ -0,0 +1,47 @@
+local Luan = require "luan:Luan.luan"
+local error = Luan.error
+local Io = require "luan:Io.luan"
+local Http = require "luan:http/Http.luan"
+local Shared = require "site:/lib/Shared.luan"
+local head = Shared.head or error()
+local header = Shared.header or error()
+local hidden_with = Shared.hidden_with or error()
+local add_with = Shared.add_with or error()
+
+
+return function()
+	Io.stdout = Http.response.text_writer()
+%>
+<!doctype html>
+<html lang="en">
+	<head>
+<%		head() %>
+		<style>
+			input[name=email] {
+				width: 300px;
+				max-width: 100%;
+			}
+		</style>
+	</head>
+	<body>
+<%		header() %>
+		<div content>
+			<h1>Register / Get Password</h1>
+			<p>A link to login will be emailed to you.</p>
+			<form page onsubmit="ajaxForm('/register.js',this)" action="javascript:">
+<%				hidden_with() %>
+				<p>
+					<label prompt>Your email address</label>
+					<input type=email name=email required autofocus>
+				</p>
+				<p>
+					<input type=submit>
+				</p>
+			</form>
+			<p><a href="<%= add_with("login.html") %>">Login</a></p>
+			<p><a href="about.html">About Luan Chat</a></p>
+		</div>
+	</body>
+</html>
+<%
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/register.js.luan	Thu Dec 04 21:43:47 2025 -0700
@@ -0,0 +1,32 @@
+local Luan = require "luan:Luan.luan"
+local error = Luan.error
+local Io = require "luan:Io.luan"
+local Http = require "luan:http/Http.luan"
+local Shared = require "site:/lib/Shared.luan"
+local send_mail_async = Shared.send_mail_async or error()
+local add_with = Shared.add_with or error()
+local Utils = require "site:/lib/Utils.luan"
+local to_list = Utils.to_list or error()
+local User = require "site:/lib/User.luan"
+
+
+return function()
+	local email = Http.request.parameters.email or error()
+	local user = User.get_or_create_by_email(email)
+	local url = add_with( user.login_url() )
+	send_mail_async {
+		To = email
+		Subject = "Login"
+		body = `%>
+Here is the link to login:
+
+<%= url %>
+
+Your password: <%=user.password%>
+<%		`
+	}
+	Io.stdout = Http.response.text_writer()
+%>
+	location = '/register_sent.html';
+<%
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/register_sent.html.luan	Thu Dec 04 21:43:47 2025 -0700
@@ -0,0 +1,27 @@
+local Luan = require "luan:Luan.luan"
+local error = Luan.error
+local Io = require "luan:Io.luan"
+local Http = require "luan:http/Http.luan"
+local Shared = require "site:/lib/Shared.luan"
+local head = Shared.head or error()
+local header = Shared.header or error()
+
+
+return function()
+	Io.stdout = Http.response.text_writer()
+%>
+<!doctype html>
+<html lang="en">
+	<head>
+<%		head() %>
+	</head>
+	<body>
+<%		header() %>
+		<div content>
+			<h1>Register / Get Password</h1>
+			<p>A link to login has been emailed to you.</p>
+		</div>
+	</body>
+</html>
+<%
+end