mirror of
https://github.com/rr-/szurubooru.git
synced 2025-07-17 08:26:24 +00:00
Compare commits
3 Commits
fe99cd2b59
...
fb686b591a
Author | SHA1 | Date | |
---|---|---|---|
fb686b591a | |||
ee7e9ef2a3 | |||
013be7aa24 |
@ -1,4 +1,5 @@
|
|||||||
node_modules/*
|
node_modules/*
|
||||||
|
public/
|
||||||
Dockerfile
|
Dockerfile
|
||||||
.dockerignore
|
.dockerignore
|
||||||
**/.gitignore
|
**/.gitignore
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
|
FROM --platform=$BUILDPLATFORM node:lts-alpine as development
|
||||||
|
WORKDIR /opt/app
|
||||||
|
|
||||||
|
RUN apk --no-cache add \
|
||||||
|
dumb-init \
|
||||||
|
nginx \
|
||||||
|
git
|
||||||
|
|
||||||
|
RUN ln -sf /opt/app/nginx.conf.docker /etc/nginx/nginx.conf
|
||||||
|
RUN rm -rf /var/www
|
||||||
|
RUN ln -sf /opt/app/public/ /var/www
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
ARG BUILD_INFO="docker-development"
|
||||||
|
ENV BUILD_INFO=${BUILD_INFO}
|
||||||
|
ENV BACKEND_HOST="server"
|
||||||
|
|
||||||
|
CMD ["/opt/app/docker-start-dev.sh"]
|
||||||
|
VOLUME ["/data"]
|
||||||
|
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM node:lts as builder
|
FROM --platform=$BUILDPLATFORM node:lts as builder
|
||||||
WORKDIR /opt/app
|
WORKDIR /opt/app
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ function makeOutputDirs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function watch() {
|
function watch() {
|
||||||
let wss = new WebSocket.Server({ port: 8080 });
|
let wss = new WebSocket.Server({ port: environment === "development" ? 8081 : 8080 });
|
||||||
const liveReload = !process.argv.includes('--no-live-reload');
|
const liveReload = !process.argv.includes('--no-live-reload');
|
||||||
|
|
||||||
function emitReload() {
|
function emitReload() {
|
||||||
|
17
client/docker-start-dev.sh
Executable file
17
client/docker-start-dev.sh
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/dumb-init /bin/sh
|
||||||
|
|
||||||
|
# Integrate environment variables
|
||||||
|
sed -i "s|__BACKEND__|${BACKEND_HOST}|" \
|
||||||
|
/etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
# Start server
|
||||||
|
nginx &
|
||||||
|
|
||||||
|
# Watch source for changes and build app
|
||||||
|
# FIXME: It's not ergonomic to run `npm i` outside of the build step.
|
||||||
|
# However, the mounting of different directories into the
|
||||||
|
# client container's /opt/app causes node_modules to disappear
|
||||||
|
# (the mounting causes client/Dockerfile's RUN npm install
|
||||||
|
# to silently clobber).
|
||||||
|
# Find a way to move `npm i` into client/Dockerfile.
|
||||||
|
npm i && npm run watch -- --polling
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
# Integrate environment variables
|
# Integrate environment variables
|
||||||
sed -i "s|__BACKEND__|${BACKEND_HOST}|" \
|
sed -i "s|__BACKEND__|${BACKEND_HOST}|" \
|
||||||
/etc/nginx/nginx.conf
|
/etc/nginx/nginx.conf
|
||||||
sed -i "s|__BASEURL__|${BASE_URL:-/}|g" \
|
sed -i "s|__BASEURL__|${BASE_URL:-/}|g" \
|
||||||
/var/www/index.htm \
|
/var/www/index.htm \
|
||||||
/var/www/manifest.json
|
/var/www/manifest.json
|
||||||
|
|
||||||
# Start server
|
# Start server
|
||||||
exec nginx
|
exec nginx
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
const config = require("./config.js");
|
const config = require("./config.js");
|
||||||
|
|
||||||
if (config.environment == "development") {
|
if (config.environment == "development") {
|
||||||
var ws = new WebSocket("ws://" + location.hostname + ":8080");
|
var ws = new WebSocket("ws://" + location.hostname + ":8081");
|
||||||
ws.addEventListener("open", function (event) {
|
ws.addEventListener("open", function (event) {
|
||||||
console.log("Live-reloading websocket connected.");
|
console.log("Live-reloading websocket connected.");
|
||||||
});
|
});
|
||||||
|
54
docker-compose.dev.yml
Normal file
54
docker-compose.dev.yml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
## Docker Compose configuration for dev iteration
|
||||||
|
##
|
||||||
|
## Data is transient by using named vols.
|
||||||
|
## Run: docker-compose -f ./docker-compose.dev.yml up
|
||||||
|
services:
|
||||||
|
|
||||||
|
server:
|
||||||
|
build:
|
||||||
|
context: ./server
|
||||||
|
target: development
|
||||||
|
depends_on:
|
||||||
|
- sql
|
||||||
|
environment:
|
||||||
|
## These should be the names of the dependent containers listed below,
|
||||||
|
## or FQDNs/IP addresses if these services are running outside of Docker
|
||||||
|
POSTGRES_HOST: sql
|
||||||
|
## Credentials for database:
|
||||||
|
POSTGRES_USER:
|
||||||
|
POSTGRES_PASSWORD:
|
||||||
|
## Commented Values are Default:
|
||||||
|
#POSTGRES_DB: defaults to same as POSTGRES_USER
|
||||||
|
#POSTGRES_PORT: 5432
|
||||||
|
#LOG_SQL: 0 (1 for verbose SQL logs)
|
||||||
|
THREADS:
|
||||||
|
volumes:
|
||||||
|
- "data:/data"
|
||||||
|
- "./server/:/opt/app/"
|
||||||
|
|
||||||
|
client:
|
||||||
|
build:
|
||||||
|
context: ./client
|
||||||
|
target: development
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
volumes:
|
||||||
|
- "data:/data:ro"
|
||||||
|
- "./client/:/opt/app/"
|
||||||
|
- "/opt/app/public/"
|
||||||
|
ports:
|
||||||
|
- "${PORT}:80"
|
||||||
|
- "8081:8081"
|
||||||
|
|
||||||
|
sql:
|
||||||
|
image: postgres:11-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER:
|
||||||
|
POSTGRES_PASSWORD:
|
||||||
|
volumes:
|
||||||
|
- "sql:/var/lib/postgresql/data"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
sql:
|
@ -61,7 +61,42 @@ ENTRYPOINT ["pytest", "--tb=short"]
|
|||||||
CMD ["szurubooru/"]
|
CMD ["szurubooru/"]
|
||||||
|
|
||||||
|
|
||||||
|
FROM prereqs as development
|
||||||
|
WORKDIR /opt/app
|
||||||
|
|
||||||
|
ARG PUID=1000
|
||||||
|
ARG PGID=1000
|
||||||
|
|
||||||
|
RUN apk --no-cache add \
|
||||||
|
dumb-init \
|
||||||
|
py3-pip \
|
||||||
|
py3-setuptools \
|
||||||
|
py3-waitress \
|
||||||
|
&& pip3 install --no-cache-dir --disable-pip-version-check \
|
||||||
|
hupper \
|
||||||
|
&& mkdir -p /opt/app /data \
|
||||||
|
&& addgroup -g ${PGID} app \
|
||||||
|
&& adduser -SDH -h /opt/app -g '' -G app -u ${PUID} app \
|
||||||
|
&& chown -R app:app /opt/app /data
|
||||||
|
|
||||||
|
USER app
|
||||||
|
CMD ["/opt/app/docker-start-dev.sh"]
|
||||||
|
|
||||||
|
ARG PORT=6666
|
||||||
|
ENV PORT=${PORT}
|
||||||
|
EXPOSE ${PORT}
|
||||||
|
|
||||||
|
ARG THREADS=4
|
||||||
|
ENV THREADS=${THREADS}
|
||||||
|
|
||||||
|
VOLUME ["/data/"]
|
||||||
|
|
||||||
|
|
||||||
FROM prereqs as release
|
FROM prereqs as release
|
||||||
|
|
||||||
|
COPY ./ /opt/app/
|
||||||
|
RUN rm -rf /opt/app/szurubooru/tests
|
||||||
|
|
||||||
WORKDIR /opt/app
|
WORKDIR /opt/app
|
||||||
|
|
||||||
ARG PUID=1000
|
ARG PUID=1000
|
||||||
|
8
server/docker-start-dev.sh
Executable file
8
server/docker-start-dev.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/dumb-init /bin/sh
|
||||||
|
set -e
|
||||||
|
cd /opt/app
|
||||||
|
|
||||||
|
alembic upgrade head
|
||||||
|
|
||||||
|
echo "Starting szurubooru API on port ${PORT} - Running on ${THREADS} threads"
|
||||||
|
exec hupper -m waitress --port ${PORT} --threads ${THREADS} szurubooru.facade:app
|
@ -13,7 +13,7 @@ from getpass import getpass
|
|||||||
from sys import stderr
|
from sys import stderr
|
||||||
|
|
||||||
from szurubooru import config, db, errors, model
|
from szurubooru import config, db, errors, model
|
||||||
from szurubooru.func import files, images
|
from szurubooru.func import files, images, snapshots
|
||||||
from szurubooru.func import posts as postfuncs
|
from szurubooru.func import posts as postfuncs
|
||||||
from szurubooru.func import users as userfuncs
|
from szurubooru.func import users as userfuncs
|
||||||
|
|
||||||
@ -100,6 +100,48 @@ def regenerate_thumbnails() -> None:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def delete_posts(parameters: list) -> None:
|
||||||
|
verification: str = input("Do you really want to delete all posts with the given ID's [y/n]: ").lower()
|
||||||
|
|
||||||
|
if "y" != verification:
|
||||||
|
return
|
||||||
|
|
||||||
|
def delete_one_post(post_id: int) -> None:
|
||||||
|
print("Deleting post %d" % post_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
post: model.Post = postfuncs.get_post_by_id(post_id)
|
||||||
|
except postfuncs.PostNotFoundError:
|
||||||
|
print("Post with ID %d not found" % post_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
postfuncs.delete(post)
|
||||||
|
snapshots.delete(post, None)
|
||||||
|
|
||||||
|
def delete_multiple_posts(start_id: int, end_id: int) -> None:
|
||||||
|
if start_id > end_id:
|
||||||
|
start_id, end_id = end_id, start_id
|
||||||
|
|
||||||
|
for post_id in range(start_id, end_id + 1):
|
||||||
|
delete_one_post(post_id)
|
||||||
|
|
||||||
|
for parameter in parameters:
|
||||||
|
try:
|
||||||
|
if "-" not in parameter:
|
||||||
|
delete_one_post(int(parameter))
|
||||||
|
continue
|
||||||
|
|
||||||
|
post_range: list = [int(number) for number in parameter.split("-", 2)]
|
||||||
|
delete_multiple_posts(*post_range)
|
||||||
|
except ValueError:
|
||||||
|
print("One of the specified parameters is not a number")
|
||||||
|
return
|
||||||
|
|
||||||
|
db.get_session().commit()
|
||||||
|
|
||||||
|
print("All posts were deleted")
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
parser_top = ArgumentParser(
|
parser_top = ArgumentParser(
|
||||||
description="Collection of CLI commands for an administrator to use",
|
description="Collection of CLI commands for an administrator to use",
|
||||||
@ -129,6 +171,14 @@ def main() -> None:
|
|||||||
help="regenerate the thumbnails for posts if the "
|
help="regenerate the thumbnails for posts if the "
|
||||||
"thumbnail files are missing",
|
"thumbnail files are missing",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--delete-posts",
|
||||||
|
metavar="<post_ids>",
|
||||||
|
nargs='+',
|
||||||
|
help="Delete all posts with the specified ID, separated by a space. "
|
||||||
|
"Multiple posts can be deleted at once by specifying them as follows, "
|
||||||
|
"including the upper and lower limits: 37-47"
|
||||||
|
)
|
||||||
command = parser_top.parse_args()
|
command = parser_top.parse_args()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -140,6 +190,8 @@ def main() -> None:
|
|||||||
reset_filenames()
|
reset_filenames()
|
||||||
elif command.regenerate_thumbnails:
|
elif command.regenerate_thumbnails:
|
||||||
regenerate_thumbnails()
|
regenerate_thumbnails()
|
||||||
|
elif command.delete_posts:
|
||||||
|
delete_posts(command.delete_posts)
|
||||||
except errors.BaseError as e:
|
except errors.BaseError as e:
|
||||||
print(e, file=stderr)
|
print(e, file=stderr)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user