diff --git a/README.md b/README.md
index c90c36d..5edea66 100644
--- a/README.md
+++ b/README.md
@@ -15,3 +15,6 @@ this is all off the top of my head so if you try to run it got help you
- luaossl
i think thats it
+
+# icons
+the icons in the `icons/` folder are by [Gabriele Malaspina](https://www.figma.com/community/file/1136337054881623512/iconcino-v2-0-0-free-icons-cc0-1-0-license)
diff --git a/app.lua b/app.lua
index 535c5e8..174d765 100644
--- a/app.lua
+++ b/app.lua
@@ -11,14 +11,21 @@ local util = require("util")
app:enable("etlua")
app.layout = require "views.base"
+local function inject_constants(req)
+ req.constants = constants
+end
+
local function inject_methods(req)
req.avatar_url = util.get_user_avatar_url
req.ntob = function(_, v)
return util.ntob(v)
end
req.PermissionLevelString = constants.PermissionLevelString
+
+ util.pop_infobox(req)
end
+app:before_filter(inject_constants)
app:before_filter(inject_methods)
app:include("apps.users", {path = "/user"})
diff --git a/apps/threads.lua b/apps/threads.lua
index 004ba86..417f8ad 100644
--- a/apps/threads.lua
+++ b/apps/threads.lua
@@ -14,7 +14,7 @@ local POSTS_PER_PAGE = 10
app:get("thread_create", "/create", function(self)
local user = util.get_logged_in_user(self)
if not user then
- self.session.flash = {error = "You must be logged in to perform this action."}
+ util.inject_err_infobox(self, "You must be logged in to perform this action.")
return {redirect_to = self:url_for("user_login")}
end
local all_topics = db.query("select * from topics limit 25;")
@@ -30,7 +30,7 @@ end)
app:post("thread_create", "/create", function(self)
local user = util.get_logged_in_user(self)
if not user then
- self.session.flash = {error = "You must be logged in to perform this action."}
+ util.inject_err_infobox(self, "You must be logged in to perform this action.")
return {redirect_to = self:url_for("user_login")}
end
local topic = Topics:find(self.params.topic_id)
diff --git a/apps/users.lua b/apps/users.lua
index 1d98165..0d11dde 100644
--- a/apps/users.lua
+++ b/apps/users.lua
@@ -66,11 +66,6 @@ app:get("user", "/:username", function(self)
return {status = 404}
end
- if self.session.flash ~= nil and self.session.flash.just_logged_in then
- self.just_logged_in = true
- self.session.flash = {}
- end
-
local me = util.get_logged_in_user_or_transient(self)
self.user = user
self.me = me
@@ -110,7 +105,7 @@ app:post("user_delete", "/:username/delete", function(self)
-- i might make a separate route for it later, but guesting users is possible
local me = util.get_logged_in_user(self)
if me == nil then
- self.session.flash = {error = "You must be logged in to perform this action."}
+ util.inject_err_infobox(self, "You must be logged in to perform this action.")
return {redirect_to = self:url_for("user_login")}
end
local target_user = Users:find({username = self.params.username})
@@ -120,29 +115,25 @@ app:post("user_delete", "/:username/delete", function(self)
end
if not authenticate_user(target_user, self.params.password) then
- self.session.flash = {error = "The password you entered is incorrect."}
+ util.inject_err_infobox(self, "The password you entered is incorrect.")
return {redirect_to = self:url_for("user_delete_confirm", {username = me.username})}
end
util.transfer_and_delete_user(target_user)
- self.session.flash = {error = "Your account has been added to the deletion queue."}
+ util.inject_infobox(self, "Your account has been added to the deletion queue.")
return {redirect_to = self:url_for("user_signup")}
end)
app:get("user_delete_confirm", "/:username/delete_confirm", function(self)
local me = util.get_logged_in_user(self)
if me == nil then
- self.session.flash = {error = "You must be logged in to perform this action."}
+ -- util.inject_err_infobox(self, "You must be logged in to perform this action.")
return {redirect_to = self:url_for("user_login")}
end
local target_user = Users:find({username = self.params.username})
if me.id ~= target_user.id then
return {redirect_to = self:url_for("user", {username = self.params.username})}
end
- if self.session.flash then
- self.err = self.session.flash.error
- self.session.flash = {}
- end
self.me = target_user
self.page_title = "confirm deletion"
@@ -152,7 +143,7 @@ end)
app:post("user_clear_avatar", "/:username/clear_avatar", function(self)
local me = util.get_logged_in_user(self)
if me == nil then
- self.session.flash = {error = "You must be logged in to perform this action."}
+ util.inject_err_infobox(self, "You must be logged in to perform this action.")
return {redirect_to = self:url_for("user_login")}
end
local target_user = Users:find({username = self.params.username})
@@ -162,14 +153,14 @@ app:post("user_clear_avatar", "/:username/clear_avatar", function(self)
target_user:update({
avatar_id = db.NULL,
})
- self.session.flash = {success = true, msg = "Avatar cleared."}
+ util.inject_infobox(self, "Avatar cleared.")
return {redirect_to = self:url_for("user_settings", {username = self.params.username})}
end)
app:post("user_set_avatar", "/:username/set_avatar", function(self)
local me = util.get_logged_in_user(self)
if me == nil then
- self.session.flash = {error = "You must be logged in to perform this action."}
+ util.inject_err_infobox(self, "You must be logged in to perform this action.")
return {redirect_to = self:url_for("user_login")}
end
local target_user = Users:find({username = self.params.username})
@@ -178,7 +169,7 @@ app:post("user_set_avatar", "/:username/set_avatar", function(self)
end
local file = self.params.avatar
if not file then
- self.session.flash = {error = "Something went wrong. Try again later."}
+ util.inject_warn_infobox(self, "Something went wrong. Try again later.")
return {redirect_to = self:url_for("user_settings", {username = self.params.username})}
end
local time = os.time()
@@ -187,11 +178,11 @@ app:post("user_set_avatar", "/:username/set_avatar", function(self)
local save_path = "static" .. proxied_filename
local res = util.validate_and_create_image(file.content, save_path)
if not res then
- self.session.flash = {error = "Something went wrong. Try again later."}
+ util.inject_warn_infobox(self, "Something went wrong. Try again later.")
return {redirect_to = self:url_for("user_settings", {username = self.params.username})}
end
- self.session.flash = {success = true, msg = "Avatar updated."}
+ util.inject_infobox(self, "Avatar updated.")
local avatar = Avatars:create({
file_path = proxied_filename,
uploaded_at = time,
@@ -207,22 +198,13 @@ end)
app:get("user_settings", "/:username/settings", function(self)
local me = util.get_logged_in_user(self)
if me == nil then
- self.session.flash = {error = "You must be logged in to perform this action."}
+ util.inject_err_infobox(self, "You must be logged in to perform this action.")
return {redirect_to = self:url_for("user_login")}
end
local target_user = Users:find({username = self.params.username})
if me.id ~= target_user.id then
return {redirect_to = self:url_for("user", {username = self.params.username})}
end
- if self.session.flash then
- local flash = self.session.flash
- self.session.flash = nil
- if flash.success then
- self.flash_msg = flash.msg
- elseif flash.error then
- self.flash_msg = flash.error
- end
- end
self.me = target_user
self.page_title = "settings"
@@ -232,7 +214,7 @@ end)
app:post("user_settings", "/:username/settings", function(self)
local me = util.get_logged_in_user(self)
if me == nil then
- self.session.flash = {error = "You must be logged in to perform this action."}
+ util.inject_err_infobox(self, "You must be logged in to perform this action.")
return {redirect_to = self:url_for("user_login")}
end
local target_user = Users:find({username = self.params.username})
@@ -245,10 +227,7 @@ app:post("user_settings", "/:username/settings", function(self)
target_user:update({
status = status,
})
- self.session.flash = {
- success = true,
- msg = "Settings updated."
- }
+ util.inject_infobox(self, "Status updated.")
return {redirect_to = self:url_for("user_settings", {username = self.params.username})}
end)
@@ -260,11 +239,6 @@ app:get("user_login", "/login", function(self)
end
end
- if self.session.flash then
- self.err = self.session.flash.error
- self.session.flash = {}
- end
-
self.page_title = "log in"
return {render = "user.login"}
@@ -281,19 +255,19 @@ app:post("user_login", "/login", function(self)
local password = self.params.password
local user = Users:find({username = username})
if not user then
- self.session.flash = {error = "Invalid username or password"}
+ util.inject_err_infobox(self, "Invalid username or password")
return {redirect_to = self:url_for("user_login")}
end
if user.permission == constants.PermissionLevel.SYSTEM then
- self.session.flash = {error = "Invalid username or password"}
+ util.inject_err_infobox(self, "Invalid username or password")
return {redirect_to = self:url_for("user_login")}
end
if not authenticate_user(user, password) then
- self.session.flash = {error = "Invalid username or password"}
+ util.inject_err_infobox(self, "Invalid username or password")
return {redirect_to = self:url_for("user_login")}
end
local session = create_session(user.id)
- self.session.flash = {just_logged_in = true}
+ util.inject_infobox(self, "Logged in successfully.")
self.session.session_key = session.key
return {redirect_to = self:url_for("user", {username = username})}
end)
@@ -305,10 +279,6 @@ app:get("user_signup", "/signup", function(self)
return {redirect_to = self:url_for("user", {username = user.username})}
end
end
- if self.session.flash then
- self.err = self.session.flash.error
- self.session.flash = {}
- end
self.page_title = "sign up"
@@ -328,22 +298,22 @@ app:post("user_signup", "/signup", function(self)
local password2 = self.params.password2
local user = Users:find({username = username})
if user then
- self.session.flash = {error = "Username '" .. username .. "' is already taken."}
+ util.inject_err_infobox(self, "Username '" .. username .. "' is already taken.")
return {redirect_to = self:url_for("user_signup")}
end
if not validate_username(username) then
- self.session.flash = {error = "Username must be 3-20 characters with only upper and lowercase letters, hyphens, and underscores."}
+ util.inject_err_infobox(self, "Username must be 3-20 characters with only upper and lowercase letters, hyphens, and underscores.")
return {redirect_to = self:url_for("user_signup")}
end
-
+
if not validate_password(password) then
- self.session.flash = {error = "Password must be 10+ chars with: 1 uppercase, 1 lowercase, 1 number, 1 special char, and no spaces."}
+ util.inject_err_infobox(self, "Password must be 10+ chars with: 1 uppercase, 1 lowercase, 1 number, 1 special char, and no spaces.")
return {redirect_to = self:url_for("user_signup")}
end
-
+
if password ~= password2 then
- self.session.flash = {error = "Passwords do not match."}
+ util.inject_err_infobox(self, "Passwords do not match.")
return {redirect_to = self:url_for("user_signup")}
end
@@ -354,7 +324,7 @@ app:post("user_signup", "/signup", function(self)
})
local session = create_session(new_user.id)
- self.session.flash = {just_logged_in = true}
+ util.inject_infobox(self, "Siged up successfully.")
self.session.session_key = session.key
return {redirect_to = self:url_for("user", {username = username})}
end)
diff --git a/constants.lua b/constants.lua
index 3cf0658..e949217 100644
--- a/constants.lua
+++ b/constants.lua
@@ -16,6 +16,26 @@ Constants.PermissionLevelString = {
[Constants.PermissionLevel.ADMIN] = "Administrator",
}
+Constants.InfoboxKind = {
+ INFO = 0,
+ LOCK = 1,
+ WARN = 2,
+ ERROR = 3,
+}
+
+Constants.InfoboxIcons = {
+ [Constants.InfoboxKind.INFO] = "svg-icons.info",
+ [Constants.InfoboxKind.LOCK] = "svg-icons.lock",
+ [Constants.InfoboxKind.WARN] = "svg-icons.warn",
+ [Constants.InfoboxKind.ERROR] = "svg-icons.error",
+}
+Constants.InfoboxHTMLClass = {
+ [Constants.InfoboxKind.INFO] = "",
+ [Constants.InfoboxKind.LOCK] = "warn",
+ [Constants.InfoboxKind.WARN] = "warn",
+ [Constants.InfoboxKind.ERROR] = "critical",
+}
+
Constants.BCRYPT_ROUNDS = 10
return Constants
diff --git a/sass/style.scss b/sass/style.scss
index 7c3cbd6..05aaae3 100644
--- a/sass/style.scss
+++ b/sass/style.scss
@@ -253,3 +253,27 @@ input[type="text"], input[type="password"] {
box-sizing: border-box;
background-color: $lighter;
}
+
+.infobox {
+ border: 2px solid black;
+ background-color: $accent_color;
+ padding: 20px 15px;
+
+ &.critical {
+ background-color: rgb(237, 129, 129);
+ }
+
+ &.warn {
+ background-color: #fbfb8d;
+ }
+}
+
+.infobox > span {
+ display: flex;
+ align-items: center;
+}
+
+.infobox-icon-container {
+ min-width: 60px;
+ padding-right: 15px;
+}
diff --git a/static/style.css b/static/style.css
index d47f189..f13b69a 100644
--- a/static/style.css
+++ b/static/style.css
@@ -245,3 +245,25 @@ input[type=text], input[type=password] {
box-sizing: border-box;
background-color: rgb(229.84, 231.92, 227.28);
}
+
+.infobox {
+ border: 2px solid black;
+ background-color: #c1ceb1;
+ padding: 20px 15px;
+}
+.infobox.critical {
+ background-color: rgb(237, 129, 129);
+}
+.infobox.warn {
+ background-color: #fbfb8d;
+}
+
+.infobox > span {
+ display: flex;
+ align-items: center;
+}
+
+.infobox-icon-container {
+ min-width: 60px;
+ padding-right: 15px;
+}
diff --git a/svg-icons/error.etlua b/svg-icons/error.etlua
new file mode 100644
index 0000000..c9ea78a
--- /dev/null
+++ b/svg-icons/error.etlua
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/svg-icons/info.etlua b/svg-icons/info.etlua
new file mode 100644
index 0000000..fece45b
--- /dev/null
+++ b/svg-icons/info.etlua
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/svg-icons/lock.etlua b/svg-icons/lock.etlua
new file mode 100644
index 0000000..d628b13
--- /dev/null
+++ b/svg-icons/lock.etlua
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/svg-icons/warn.etlua b/svg-icons/warn.etlua
new file mode 100644
index 0000000..d4b2c93
--- /dev/null
+++ b/svg-icons/warn.etlua
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/util.lua b/util.lua
index e4e3f04..044b8b0 100644
--- a/util.lua
+++ b/util.lua
@@ -2,6 +2,7 @@ local util = {}
local magick = require("magick")
local db = require("lapis.db")
local html_escape = require("lapis.html").escape
+local constants = require("constants")
local Avatars = require("models").Avatars
local Users = require("models").Users
@@ -147,4 +148,37 @@ function util.transfer_and_delete_user(user)
db.query("COMMIT")
end
+function util.pop_infobox(req)
+ print("1")
+ if not req.session.infobox then return end
+ print("2")
+ req.infobox = req.session.infobox
+ req.session.infobox = nil
+end
+
+function util.inject_infobox(req, message, kind)
+ kind = kind or constants.InfoboxKind.INFO
+ local ib = {
+ msg = message,
+ kind = kind,
+ }
+ req.session.infobox = ib
+end
+
+function util.inject_err_infobox(req, message)
+ local ib = {
+ msg = message,
+ kind = constants.InfoboxKind.ERROR,
+ }
+ req.session.infobox = ib
+end
+
+function util.inject_warn_infobox(req, message)
+ local ib = {
+ msg = message,
+ kind = constants.InfoboxKind.WARN,
+ }
+ req.session.infobox = ib
+end
+
return util
diff --git a/views/common/infobox.etlua b/views/common/infobox.etlua
new file mode 100644
index 0000000..b5c851e
--- /dev/null
+++ b/views/common/infobox.etlua
@@ -0,0 +1,13 @@
+<%
+ local class = "infobox " .. constants.InfoboxHTMLClass[kind]
+ local icon = constants.InfoboxIcons[kind]
+%>
+
+
+
+
+ <% render(icon) %>
+
+ <%= msg %>
+
+
diff --git a/views/threads/thread.etlua b/views/threads/thread.etlua
index 3b33158..f4d5344 100644
--- a/views/threads/thread.etlua
+++ b/views/threads/thread.etlua
@@ -1,4 +1,5 @@
<% render("views.common.topnav") -%>
+<% local is_locked = ntob(thread.is_locked) %>
-<% if not me:is_guest() then %>
+<% if is_locked then -%>
+ <% render("views.common.infobox", {kind = constants.InfoboxKind.LOCK, msg = "This thread is locked."}) %>
+<% end -%>
+<% if not me:is_guest() and not is_locked then %>
Respond to "<%= thread.title %>"
<% end %>
diff --git a/views/user/delete_confirm.etlua b/views/user/delete_confirm.etlua
index 2f447fd..66114b9 100644
--- a/views/user/delete_confirm.etlua
+++ b/views/user/delete_confirm.etlua
@@ -4,8 +4,8 @@
This cannot be undone. This will not delete your posts, only anonymize them.
If you are sure, please type your password below.
- <% if err then %>
-
<%= err %>
+ <% if infobox then %>
+ <% render("views.common.infobox", infobox) %>
<% end %>