Compare commits
4 Commits
7d761bae2e
...
with-docke
Author | SHA1 | Date | |
---|---|---|---|
ca23415288 | |||
d4ab245297
|
|||
a28572003e
|
|||
511687c8c3
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,3 +6,5 @@ db.*.sqlite
|
||||
static/avatars/*
|
||||
!static/avatars/default.webp
|
||||
secrets.lua
|
||||
|
||||
.first_launch.*
|
||||
|
26
README.md
26
README.md
@ -5,9 +5,9 @@ porous forum
|
||||
Released under [CNPLv7+](https://thufie.lain.haus/NPL.html).
|
||||
Please read the [full terms](./LICENSE.md) for proper wording.
|
||||
|
||||
# installing
|
||||
# installing & first time setup
|
||||
1. first, install OpenResty. instructions for linux can be found [here](https://openresty.org/en/linux-packages.html).
|
||||
2. then, install LuaJIT
|
||||
2. then, install LuaJIT and Lua 5.1 (usually called `lua5.1` in package managers)
|
||||
3. then, install [LuaRocks](https://luarocks.org) (prefer your package manager instead of a local install recommended by the guide)
|
||||
4. add luarocks search dirs to path:
|
||||
|
||||
@ -19,9 +19,27 @@ Please read the [full terms](./LICENSE.md) for proper wording.
|
||||
6. install the dependencies:
|
||||
|
||||
```bash
|
||||
luarocks --local --lua-version 5.1 build --only-deps
|
||||
$ luarocks --local --lua-version 5.1 build --only-deps
|
||||
```
|
||||
7. rest is TBD until a start script is provided
|
||||
7. create a file named `secrets.lua` in the project directory.
|
||||
use the `secrets.lua.example` file as reference, and generate a cryptographically secure random key, for example, with:
|
||||
|
||||
```bash
|
||||
$ openssl rand -hex 32
|
||||
```
|
||||
8. run:
|
||||
|
||||
```bash
|
||||
$ start.sh production
|
||||
```
|
||||
the script will perform some necessary first time setup (and create a hidden file in the folder to ensure it won't do so again). it will create an administrator account and print the credentials to the console; **this will only happen once**. make sure you save them somewhere. the administrator account is the only one that can promote other users to moderator.
|
||||
(note the `production` argument. if called with no arguments, `start.sh` will run in a development environment, which uses a separate database.)
|
||||
|
||||
this app is made with the assumption that it is being reverse-proxied. as such, you may want to change the port to something other than the default `8080`. you can do that in [`config.lua`]([./config.lua]).
|
||||
|
||||
after the first time setup is complete, everything is ready to go. put the app behind your reverse proxy and serve it on the web. the app does not run in https by itself, but the reverse proxy can be set up to do that.
|
||||
|
||||
once you are able to navigate to the forum, you can log in as the administrator account. other people may also sign up, but they are not able to post until manually verified by an administrator or a moderator. the administrator can promote regular users to moderator.
|
||||
|
||||
# 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)
|
||||
|
1
app.lua
1
app.lua
@ -31,6 +31,7 @@ app:before_filter(inject_methods)
|
||||
app:include("apps.users", {path = "/user"})
|
||||
app:include("apps.topics", {path = "/topics"})
|
||||
app:include("apps.threads", {path = "/threads"})
|
||||
app:include("apps.mod", {path = "/mod"})
|
||||
|
||||
app:get("/", function(self)
|
||||
return {redirect_to = self:url_for("all_topics")}
|
||||
|
23
apps/mod.lua
Normal file
23
apps/mod.lua
Normal file
@ -0,0 +1,23 @@
|
||||
local app = require("lapis").Application()
|
||||
|
||||
local util = require("util")
|
||||
|
||||
local models = require("models")
|
||||
local Users = models.Users
|
||||
|
||||
app:get("user_list", "/list", function(self)
|
||||
self.me = util.get_logged_in_user(self)
|
||||
if not self.me then
|
||||
return {redirect_to = self:url_for("all_topics")}
|
||||
end
|
||||
|
||||
if not self.me:is_mod() then
|
||||
return {redirect_to = self:url_for("all_topics")}
|
||||
end
|
||||
|
||||
self.users = Users:select("")
|
||||
|
||||
return {render = "mod.user-list"}
|
||||
end)
|
||||
|
||||
return app
|
@ -151,10 +151,10 @@ app:post("user_clear_avatar", "/:username/clear_avatar", function(self)
|
||||
return {redirect_to = self:url_for("user", {username = self.params.username})}
|
||||
end
|
||||
local old_avatar_id = target_user.avatar_id
|
||||
util.destroy_avatar(old_avatar_id)
|
||||
target_user:update({
|
||||
avatar_id = 1,
|
||||
})
|
||||
util.destroy_avatar(old_avatar_id)
|
||||
util.inject_infobox(self, "Avatar cleared.")
|
||||
return {redirect_to = self:url_for("user_settings", {username = self.params.username})}
|
||||
end)
|
||||
|
@ -2,6 +2,7 @@ local config = require("lapis.config")
|
||||
local secrets = require("secrets")
|
||||
|
||||
config({"development", "production"}, {
|
||||
port = 8080,
|
||||
server = "nginx",
|
||||
code_cache = "off",
|
||||
num_workers = "1",
|
||||
@ -21,4 +22,5 @@ config("production", {
|
||||
sqlite = {
|
||||
database = "db.prod.sqlite"
|
||||
},
|
||||
session_name = "porom_session_s"
|
||||
})
|
||||
|
13
docker-compose.yaml
Normal file
13
docker-compose.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
# Generate a random secret key
|
||||
# export PROD_SECRET_KEY=$(openssl rand -hex 32)
|
||||
# Start the container
|
||||
# docker-compose up
|
||||
version: "3"
|
||||
services:
|
||||
porom:
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
- PROD_SECRET_KEY=${PROD_SECRET_KEY}
|
||||
ports:
|
||||
- "8080:8080"
|
36
dockerfile
Normal file
36
dockerfile
Normal file
@ -0,0 +1,36 @@
|
||||
# HOW TO:
|
||||
#
|
||||
# Generate a random secret key & build the Docker image
|
||||
# ```sh
|
||||
# SECRET_KEY=$(openssl rand -hex 32) docker build --build-arg PROD_SECRET_KEY="$SECRET_KEY" -t porom:latest .
|
||||
# ```
|
||||
#
|
||||
# Then run the container
|
||||
# ```sh
|
||||
# docker run -d -p 8080:8080 --name porom porom:latest
|
||||
# ```
|
||||
#
|
||||
FROM openresty/openresty:alpine-fat
|
||||
COPY ./nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
|
||||
COPY . /usr/local/openresty/nginx/html
|
||||
WORKDIR /usr/local/openresty/nginx/html
|
||||
RUN apk add --no-cache \
|
||||
make \
|
||||
git \
|
||||
make \
|
||||
gcc \
|
||||
g++ \
|
||||
musl-dev \
|
||||
libffi-dev \
|
||||
openssl-dev \
|
||||
sqlite-dev \
|
||||
imagemagick-dev \
|
||||
lua5.1 \
|
||||
lua5.1-dev
|
||||
RUN eval "$(luarocks --lua-version 5.1 path)"
|
||||
RUN luarocks --lua-version 5.1 build --only-deps
|
||||
ARG PROD_SECRET_KEY
|
||||
RUN echo "return { key = \"${PROD_SECRET_KEY}\",}" > /usr/local/openresty/nginx/html/secrets.lua
|
||||
EXPOSE 8080
|
||||
RUN chmod +x /usr/local/openresty/nginx/html/start.sh
|
||||
ENTRYPOINT ["/usr/local/openresty/nginx/html/start.sh", "production"]
|
@ -1,3 +1,3 @@
|
||||
return {
|
||||
key = PROD_SECRET_KEY_HERE,
|
||||
key = "PROD_SECRET_KEY_HERE",
|
||||
}
|
||||
|
28
start.sh
Executable file
28
start.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
start() {
|
||||
lapis serve
|
||||
}
|
||||
|
||||
first_launch() {
|
||||
echo "Setting up for the first time"
|
||||
touch ".first_launch.$LAPIS_ENVIRONMENT"
|
||||
lua5.1 schema.lua
|
||||
lapis migrate
|
||||
lua5.1 create_default_accounts.lua
|
||||
}
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
export LAPIS_ENVIRONMENT="development"
|
||||
echo "WARN: no environment passed, assuming default (development)"
|
||||
else
|
||||
export LAPIS_ENVIRONMENT="$1"
|
||||
fi
|
||||
|
||||
echo "Starting in $LAPIS_ENVIRONMENT"
|
||||
|
||||
if ! [ -f ".first_launch.$LAPIS_ENVIRONMENT" ]; then
|
||||
first_launch
|
||||
fi
|
||||
|
||||
start
|
2
util.lua
2
util.lua
@ -169,9 +169,7 @@ function util.transfer_and_delete_user(user)
|
||||
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
|
||||
|
@ -7,6 +7,10 @@
|
||||
<span>
|
||||
<% if me and me:is_logged_in() then -%>
|
||||
Welcome, <a href="<%= url_for("user", {username = me.username}) %>"><%= me.username %></a>
|
||||
<% if me:is_mod() then %>
|
||||
•
|
||||
<a href="<%= url_for("user_list") %>">User list</a>
|
||||
<% end %>
|
||||
<% else -%>
|
||||
Welcome, guest. Please <a href="<%= url_for("user_signup") %>">sign up</a> or <a href="<%= url_for("user_login") %>">log in</a>
|
||||
<% end -%>
|
||||
|
8
views/mod/user-list.etlua
Normal file
8
views/mod/user-list.etlua
Normal file
@ -0,0 +1,8 @@
|
||||
<div class="darkbg settings-container">
|
||||
<h1>All users</h1>
|
||||
<ul>
|
||||
<% for _, user in ipairs(users) do %>
|
||||
<li><a href="<%= url_for("user", {username = user.username}) %>"><%= user.username %></a></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
Reference in New Issue
Block a user