changeset 56:7ce54f6d93f2

add change name
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 28 Nov 2022 22:00:43 -0700
parents c57b84f461ae
children 169ac5fdb320
files src/account.html.luan src/change_name.html.luan src/lib/Db.luan src/lib/Post.luan src/lib/Shared.luan src/lib/User.luan src/new_post.js.luan src/set_name.html.luan
diffstat 8 files changed, 124 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/src/account.html.luan	Mon Nov 28 20:33:47 2022 -0700
+++ b/src/account.html.luan	Mon Nov 28 22:00:43 2022 -0700
@@ -24,7 +24,8 @@
 		<div content>
 			<h1>Your Account</h1>
 
-			<p><a href="/logout.html">logout</a></p>
+			<p><a href="/change_name.html">Change Name</a></p>
+			<p><a href="/logout.html">Logout</a></p>
 		</div>
 <%		footer() %>
 	</body>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/change_name.html.luan	Mon Nov 28 22:00:43 2022 -0700
@@ -0,0 +1,79 @@
+local Luan = require "luan:Luan.luan"
+local error = Luan.error
+local String = require "luan:String.luan"
+local trim = String.trim 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 footer = Shared.footer or error()
+local Forum = require "site:/lib/Forum.luan"
+local forum_title = Forum.title or error()
+local User = require "site:/lib/User.luan"
+local name_regex = User.name_regex
+local Db = require "site:/lib/Db.luan"
+local run_in_transaction = Db.run_in_transaction or error()
+
+
+local function page(contents)
+	Io.stdout = Http.response.text_writer()
+%>
+<!doctype html>
+<html>
+	<head>
+<%		head() %>
+		<title><%=forum_title%> - Change Name</title>
+	</head>
+	<body>
+<%		header() %>
+		<div content>
+			<h1>Change Name</h1>
+<%
+			contents()
+%>
+		</div>
+<%		footer() %>
+	</body>
+</html>
+<%
+end
+
+return function()
+	local user = User.current_required()
+	local name = user.name or error()
+	local error_message = nil
+	if Http.request.method == "POST" then
+		name = Http.request.parameters.name or error()
+		name = trim(name)
+		name_regex.matches(name) or error "invalid name"
+		run_in_transaction( function()
+			user = user.reload()
+			if user.name ~= name and User.get_by_name(name) ~= nil then
+				error_message = "Name already in use"
+			else
+				user.name = name
+				user.save()
+			end
+		end )
+		if error_message == nil then
+			page(function()
+%>
+				<p>Your name has been changed.</p>
+<%
+			end)
+			return
+		end
+	end
+	page(function()
+		if error_message ~= nil then %>
+			<p error>Error: <%= error_message %></p>
+<%		end %>
+			<form method=post>
+				<label>User name for <%= user.email %></label>
+				<input type="text" name="name" value="<%= name or "" %>" autofocus required pattern="[a-zA-Z0-9_-]+">
+				<input type="submit">
+			</form>
+<%
+	end)
+end
--- a/src/lib/Db.luan	Mon Nov 28 20:33:47 2022 -0700
+++ b/src/lib/Db.luan	Mon Nov 28 22:00:43 2022 -0700
@@ -15,7 +15,7 @@
 Db.indexed_fields.user_email = Lucene.type.lowercase
 Db.indexed_fields.user_name = Lucene.type.lowercase
 
-Db.indexed_fields.post_author_name = Lucene.type.string
+Db.indexed_fields.post_author_id = Lucene.type.long
 Db.indexed_fields.post_is_root = Lucene.type.string
 Db.indexed_fields.post_root_id = Lucene.type.long
 
--- a/src/lib/Post.luan	Mon Nov 28 20:33:47 2022 -0700
+++ b/src/lib/Post.luan	Mon Nov 28 22:00:43 2022 -0700
@@ -46,7 +46,7 @@
 		id = doc.id
 		content = doc.content
 		date = doc.date
-		author_name = doc.post_author_name
+		author_id = doc.post_author_id
 		root_id = doc.post_root_id
 		is_root = doc.post_is_root == "true"
 
@@ -63,7 +63,7 @@
 		id = post.id
 		content = post.content or error()
 		date = long(post.date)
-		post_author_name = post.author_name or error()
+		post_author_id = long(post.author_id)
 		post_root_id = long(post.root_id)
 		post_is_root = post.is_root and "true" or nil
 
@@ -76,7 +76,7 @@
 function metatable.__index(post,key)
 	if key == "author" then
 		local User = require "site:/lib/User.luan"
-		return User.get_by_name(post.author_name)
+		return User.get_by_id(post.author_id)
 	end
 	if key == "subject_html" then
 		return post.subject and html_encode(post.subject)
@@ -106,7 +106,7 @@
 	function post.author_is_current()
 		local User = require "site:/lib/User.luan"
 		local user = User.current()
-		return user ~= nil and user.name == post.author_name
+		return user ~= nil and user.id == post.author_id
 	end
 
 	function post.ago(now)
@@ -140,7 +140,7 @@
 		local post = Post.new{
 			subject = subject or error()
 			content = content
-			author_name = author.name
+			author_id = author.id
 			is_root = true
 		}
 		post.root_id = -1
--- a/src/lib/Shared.luan	Mon Nov 28 20:33:47 2022 -0700
+++ b/src/lib/Shared.luan	Mon Nov 28 22:00:43 2022 -0700
@@ -115,14 +115,14 @@
 				<hr>
 				<div author>
 					<img src="/images/profile.png">
-					<a href="/whatever"><%= post.author_name %></a>
+					<a href="/whatever"><%= post.author.name %></a>
 					<span ago date="<%=post.date%>"><% post.ago(now) %> ago</span>
 				</div>
 				<div output>
 					<% bbcode_to_html(post.content) %>
 					<p logged_in>
 						<a href="#">reply</a>
-						<span only_user="<%=html_encode(post.author_name)%>">
+						<span only_user="<%=html_encode(post.author.name)%>">
 							- <a href="javascript:ajax('/edit.js?post=<%=post.id%>')">edit</a>
 							<span delete_opton> - <span delete><%delete_post()%></span> </span>
 						<span>
--- a/src/lib/User.luan	Mon Nov 28 20:33:47 2022 -0700
+++ b/src/lib/User.luan	Mon Nov 28 22:00:43 2022 -0700
@@ -1,11 +1,15 @@
 local Luan = require "luan:Luan.luan"
 local error = Luan.error
 local set_metatable = Luan.set_metatable or error()
+local type = Luan.type or error()
+local to_string = Luan.to_string or error()
 local range = Luan.range or error()
 local set_local_only = Luan.set_local_only or error()
 local get_local_only = Luan.get_local_only or error()
 local String = require "luan:String.luan"
 local sub_string = String.sub or error()
+local to_number = String.to_number or error()
+local regex = String.regex or error()
 local Table = require "luan:Table.luan"
 local concat = Table.concat or error()
 local Math = require "luan:Math.luan"
@@ -14,6 +18,8 @@
 local time_now = Time.now or error()
 local Html = require "luan:Html.luan"
 local html_encode = Html.encode or error()
+local Number = require "luan:Number.luan"
+local long = Number.long or error()
 local Lucene = require "luan:lucene/Lucene.luan"
 local lucene_quote = Lucene.quote or error()
 local Http = require "luan:http/Http.luan"
@@ -23,7 +29,7 @@
 
 local User = {}
 
-local users_by_name = {}
+local users_by_id = {}
 
 local function from_doc(doc)
 	doc.type == "user" or error "wrong type"
@@ -34,7 +40,7 @@
 		name = doc.user_name
 		created = doc.created
 	}
-	set_local_only(users_by_name,user.name,user)
+	set_local_only(users_by_id,user.id,user)
 	return user
 end
 
@@ -72,9 +78,10 @@
 	end
 
 	function user.login()
-		Http.response.set_persistent_cookie("user",user.name)
+		local id = to_string(user.id)
+		Http.response.set_persistent_cookie("user",id)
 		Http.response.set_persistent_cookie("password",user.password)
-		Http.request.cookies.user = user.name or error()
+		Http.request.cookies.user = id
 		Http.request.cookies.password = user.password or error()
 	end
 
@@ -82,31 +89,38 @@
 	return user
 end
 
-function User.get_by_id(id)
+local function get_by_id(id)
+	if type(id) == "string" then
+		id = to_number(id)
+		if id == nil then return nil end
+	end
+	id = long(id)
+	if not Db.is_in_transaction() then
+		local user = get_local_only(users_by_id,id)
+		if user ~= nil then return user end
+	end
 	local doc = Db.get_document("id:"..id)
 	return doc and from_doc(doc)
 end
+User.get_by_id = get_by_id
 
 function User.get_by_email(email)
 	local doc = Db.get_document("user_email:"..lucene_quote(email))
 	return doc and from_doc(doc)
 end
 
-local function get_by_name(name)
-	local user = get_local_only(users_by_name,name)
-	if user ~= nil then return user end
+function User.get_by_name(name)
 	local doc = Db.get_document("user_name:"..lucene_quote(name))
 	return doc and from_doc(doc)
 end
-User.get_by_name = get_by_name
 
 function User.current()
-	local name = Http.request.cookies.user
+	local id = Http.request.cookies.user
 	local password = Http.request.cookies.password
-	if name == nil or password == nil then
+	if id == nil or password == nil then
 		return nil
 	end
-	local user = get_by_name(name)
+	local user = get_by_id(id)
 	if user == nil or user.password ~= password then
 		return nil
 	end
@@ -140,8 +154,10 @@
 function User.get_or_create_by_email(email,change_password)
 	local user = User.get_by_email(email)
 	if user == nil then
-		user = User.new{ email=email, password=new_password() }
-		user.save()
+		run_in_transaction( function()
+			user = User.new{ email=email, password=new_password() }
+			user.save()
+		end )
 	elseif change_password then
 		run_in_transaction( function()
 			user = user.reload()
@@ -152,4 +168,6 @@
 	return user
 end
 
+User.name_regex = regex "^[a-zA-Z0-9_-]+$"
+
 return User
--- a/src/new_post.js.luan	Mon Nov 28 20:33:47 2022 -0700
+++ b/src/new_post.js.luan	Mon Nov 28 22:00:43 2022 -0700
@@ -32,7 +32,7 @@
 	local post = Post.new{
 		root_id = to_number(root_id) or error()
 		content = text
-		author_name = user.name
+		author_id = user.id
 	}
 	Db.run_in_transaction( function()
 		post.save()
--- a/src/set_name.html.luan	Mon Nov 28 20:33:47 2022 -0700
+++ b/src/set_name.html.luan	Mon Nov 28 22:00:43 2022 -0700
@@ -2,7 +2,6 @@
 local error = Luan.error
 local String = require "luan:String.luan"
 local trim = String.trim or error()
-local regex = String.regex or error()
 local Io = require "luan:Io.luan"
 local Http = require "luan:http/Http.luan"
 local Shared = require "site:/lib/Shared.luan"
@@ -12,12 +11,11 @@
 local Forum = require "site:/lib/Forum.luan"
 local forum_title = Forum.title or error()
 local User = require "site:/lib/User.luan"
+local name_regex = User.name_regex
 local Db = require "site:/lib/Db.luan"
 local run_in_transaction = Db.run_in_transaction or error()
 
 
-local name_regex = regex "^[a-zA-Z0-9_-]+$"
-
 local function page(contents)
 	Io.stdout = Http.response.text_writer()
 %>
@@ -80,7 +78,7 @@
 				<input type="hidden" name="password" value="<%= user.password %>" >
 				<label>User name for <%= user.email %></label>
 				<input type="text" name="name" value="<%= name or "" %>" autofocus required pattern="[a-zA-Z0-9_-]+">
-				<input type="submit" value="Set">
+				<input type="submit">
 			</form>
 <%
 	end)