Skip to content

Commit e067006

Browse files
Merge pull request #593 from madeofpendletonwool/mobile-app
Mobile app
2 parents eb96016 + 7b9371b commit e067006

File tree

98 files changed

+10331
-3646
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+10331
-3646
lines changed

database_functions/migration_definitions.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,6 +1958,95 @@ def migration_018_gpodder_sync_timestamp(conn, db_type: str):
19581958
cursor.close()
19591959

19601960

1961+
@register_migration("019", "fix_encryption_key_storage", "Convert EncryptionKey from binary to text format for consistency", requires=["001"])
1962+
def migration_019_fix_encryption_key_storage(conn, db_type: str):
1963+
"""Convert EncryptionKey storage from binary to text format"""
1964+
cursor = conn.cursor()
1965+
1966+
try:
1967+
if db_type == "postgresql":
1968+
# First, get the current encryption key value as bytes
1969+
cursor.execute('SELECT encryptionkey FROM "AppSettings" WHERE appsettingsid = 1')
1970+
result = cursor.fetchone()
1971+
1972+
if result and result[0]:
1973+
# Convert bytes to string
1974+
key_bytes = result[0]
1975+
if isinstance(key_bytes, bytes):
1976+
key_string = key_bytes.decode('utf-8')
1977+
else:
1978+
key_string = str(key_bytes)
1979+
1980+
# Drop and recreate column as TEXT
1981+
cursor.execute('ALTER TABLE "AppSettings" DROP COLUMN encryptionkey')
1982+
cursor.execute('ALTER TABLE "AppSettings" ADD COLUMN encryptionkey TEXT')
1983+
1984+
# Insert the key back as text
1985+
cursor.execute('UPDATE "AppSettings" SET encryptionkey = %s WHERE appsettingsid = 1', (key_string,))
1986+
logger.info("Converted PostgreSQL encryptionkey from BYTEA to TEXT")
1987+
else:
1988+
# No existing key, just change the column type
1989+
cursor.execute('ALTER TABLE "AppSettings" DROP COLUMN encryptionkey')
1990+
cursor.execute('ALTER TABLE "AppSettings" ADD COLUMN encryptionkey TEXT')
1991+
logger.info("Changed PostgreSQL encryptionkey column to TEXT (no existing data)")
1992+
1993+
else: # MySQL
1994+
# First, get the current encryption key value
1995+
cursor.execute('SELECT EncryptionKey FROM AppSettings WHERE AppSettingsID = 1')
1996+
result = cursor.fetchone()
1997+
1998+
if result and result[0]:
1999+
# Convert binary to string
2000+
key_data = result[0]
2001+
if isinstance(key_data, bytes):
2002+
# Remove null padding and decode
2003+
key_string = key_data.rstrip(b'\x00').decode('utf-8')
2004+
else:
2005+
key_string = str(key_data)
2006+
2007+
# Change column type and update value
2008+
cursor.execute('ALTER TABLE AppSettings MODIFY EncryptionKey VARCHAR(255)')
2009+
cursor.execute('UPDATE AppSettings SET EncryptionKey = %s WHERE AppSettingsID = 1', (key_string,))
2010+
logger.info("Converted MySQL EncryptionKey from BINARY to VARCHAR")
2011+
else:
2012+
# No existing key, just change the column type
2013+
cursor.execute('ALTER TABLE AppSettings MODIFY EncryptionKey VARCHAR(255)')
2014+
logger.info("Changed MySQL EncryptionKey column to VARCHAR (no existing data)")
2015+
2016+
logger.info("Encryption key storage migration completed successfully")
2017+
2018+
except Exception as e:
2019+
logger.error(f"Error in encryption key migration: {e}")
2020+
raise
2021+
finally:
2022+
cursor.close()
2023+
2024+
2025+
@register_migration("020", "add_default_gpodder_device", "Add DefaultGpodderDevice column to Users table for tracking user's selected GPodder device", requires=["001"])
2026+
def migration_020_add_default_gpodder_device(conn, db_type: str):
2027+
"""Add DefaultGpodderDevice column to Users table"""
2028+
cursor = conn.cursor()
2029+
2030+
try:
2031+
if db_type == "postgresql":
2032+
# Add defaultgpodderdevice column to Users table
2033+
safe_execute_sql(cursor, 'ALTER TABLE "Users" ADD COLUMN defaultgpodderdevice VARCHAR(255)')
2034+
logger.info("Added defaultgpodderdevice column to Users table (PostgreSQL)")
2035+
2036+
else: # MySQL
2037+
# Add DefaultGpodderDevice column to Users table
2038+
safe_execute_sql(cursor, 'ALTER TABLE Users ADD COLUMN DefaultGpodderDevice VARCHAR(255)')
2039+
logger.info("Added DefaultGpodderDevice column to Users table (MySQL)")
2040+
2041+
logger.info("Default GPodder device column migration completed successfully")
2042+
2043+
except Exception as e:
2044+
logger.error(f"Error in default GPodder device migration: {e}")
2045+
raise
2046+
finally:
2047+
cursor.close()
2048+
2049+
19612050
def register_all_migrations():
19622051
"""Register all migrations with the migration manager"""
19632052
# Migrations are auto-registered via decorators

dockerfile

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ COPY ./gpodder-api/config ./config
3838
COPY ./gpodder-api/internal ./internal
3939

4040
# Build the application
41-
RUN CGO_ENABLED=0 GOOS=linux go build -o gpodder-api ./cmd/server/
41+
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o gpodder-api ./cmd/server/
4242

4343
# Python builder stage for database setup
4444
FROM python:3.11-alpine AS python-builder
@@ -90,19 +90,28 @@ ENV OPENSSL_LIB_DIR=/usr/lib
9090
ENV OPENSSL_INCLUDE_DIR=/usr/include
9191

9292
# Build the Rust API
93-
RUN cargo build --release
93+
RUN cargo build --release && strip target/release/pinepods-api
9494

9595
# Final stage for setting up runtime environment
9696
FROM alpine
9797
# Metadata
9898
LABEL maintainer="Collin Pendleton <collinp@collinpendleton.com>"
99-
# Install runtime dependencies (removed python3, py3-pip, cronie, and openrc)
100-
RUN apk add --no-cache tzdata nginx openssl bash mariadb-client postgresql-client curl ffmpeg supervisor wget jq
99+
# Install runtime dependencies
100+
RUN apk add --no-cache tzdata nginx openssl bash mariadb-client postgresql-client curl ffmpeg wget jq mariadb-connector-c-dev
101+
101102

102103
# Download and install latest yt-dlp binary
103104
RUN LATEST_VERSION=$(curl -s https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest | jq -r .tag_name) && \
104105
wget -O /usr/local/bin/yt-dlp "https://github.com/yt-dlp/yt-dlp/releases/download/${LATEST_VERSION}/yt-dlp_linux" && \
105106
chmod +x /usr/local/bin/yt-dlp
107+
108+
# Download and install Horust (x86_64)
109+
RUN wget -O /tmp/horust.tar.gz "https://github.com/FedericoPonzi/Horust/releases/download/v0.1.7/horust-x86_64-unknown-linux-musl.tar.gz" && \
110+
cd /tmp && tar -xzf horust.tar.gz && \
111+
mv horust /usr/local/bin/ && \
112+
chmod +x /usr/local/bin/horust && \
113+
rm -f /tmp/horust.tar.gz
114+
106115
ENV TZ=UTC
107116
# Copy compiled database setup binary (replaces Python dependency)
108117
COPY --from=python-builder /build/dist/pinepods-db-setup /usr/local/bin/
@@ -119,7 +128,7 @@ COPY startup/startup.sh /startup.sh
119128
RUN chmod +x /startup.sh
120129
# Copy Pinepods runtime files
121130
RUN mkdir -p /pinepods
122-
RUN mkdir -p /var/log/supervisor/
131+
RUN mkdir -p /var/log/pinepods/ && mkdir -p /etc/horust/services/
123132
COPY startup/ /pinepods/startup/
124133
# Legacy cron scripts removed - background tasks now handled by internal Rust scheduler
125134
COPY clients/ /pinepods/clients/

dockerfile-arm

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,43 @@ FROM rust:alpine AS builder
33
# Install build dependencies
44
RUN apk update && apk upgrade && \
55
apk add --no-cache musl-dev libffi-dev zlib-dev jpeg-dev
6-
# Install wasm target and build tools
7-
RUN rustup target add wasm32-unknown-unknown && \
8-
cargo install wasm-bindgen-cli
96
RUN apk update && apk upgrade
107
# Add the Edge Community repository
118
RUN echo "@edge http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
129
# Update the package index
1310
RUN apk update
1411
# Install the desired package from the edge community repository
1512
RUN apk add trunk@edge
13+
# Install wasm target and build tools
14+
RUN rustup target add wasm32-unknown-unknown && \
15+
cargo install wasm-bindgen-cli
1616
# Add application files to the builder stage
1717
COPY ./web/Cargo.lock ./web/Cargo.toml ./web/dev-info.md ./web/index.html ./web/tailwind.config.js ./web/Trunk.toml /app/
1818
COPY ./web/src /app/src
1919
COPY ./web/static /app/static
2020
WORKDIR /app
21-
# Initialize trunk first
22-
RUN cd /tmp && \
23-
echo "" > dummy.rs && \
24-
trunk build dummy.rs || true
25-
RUN cargo install --locked wasm-bindgen-cli
2621
# Build the Yew application in release mode
2722
RUN RUSTFLAGS="--cfg=web_sys_unstable_apis --cfg getrandom_backend=\"wasm_js\"" trunk build --features server_build --release
2823

24+
# Go builder stage for the gpodder API
25+
FROM golang:alpine AS go-builder
26+
WORKDIR /gpodder-api
27+
28+
# Install build dependencies
29+
RUN apk add --no-cache git
30+
31+
# Copy go module files first for better layer caching
32+
COPY ./gpodder-api/go.mod ./gpodder-api/go.sum ./
33+
RUN go mod download
34+
35+
# Copy the rest of the source code
36+
COPY ./gpodder-api/cmd ./cmd
37+
COPY ./gpodder-api/config ./config
38+
COPY ./gpodder-api/internal ./internal
39+
40+
# Build the application
41+
RUN CGO_ENABLED=0 GOOS=linux go build -o gpodder-api ./cmd/server/
42+
2943
# Python builder stage for database setup
3044
FROM python:3.11-alpine AS python-builder
3145
WORKDIR /build
@@ -59,64 +73,85 @@ RUN pyinstaller --onefile \
5973
--console \
6074
startup/setup_database_new.py
6175

76+
# Rust API builder stage
77+
FROM rust:alpine AS rust-api-builder
78+
WORKDIR /rust-api
79+
80+
# Install build dependencies
81+
RUN apk add --no-cache musl-dev pkgconfig openssl-dev openssl-libs-static
82+
83+
# Copy Rust API files
84+
COPY ./rust-api/Cargo.toml ./rust-api/Cargo.lock ./
85+
COPY ./rust-api/src ./src
86+
87+
# Set environment for static linking
88+
ENV OPENSSL_STATIC=1
89+
ENV OPENSSL_LIB_DIR=/usr/lib
90+
ENV OPENSSL_INCLUDE_DIR=/usr/include
91+
92+
# Build the Rust API
93+
RUN cargo build --release
94+
6295
# Final stage for setting up runtime environment
6396
FROM alpine
6497
# Metadata
6598
LABEL maintainer="Collin Pendleton <collinp@collinpendleton.com>"
6699

67-
# Install runtime dependencies (removed Python)
68-
RUN apk update && apk upgrade && \
69-
apk add --no-cache nginx tzdata openssl bash mariadb-client curl ffmpeg supervisor wget jq && \
70-
rm -rf /var/cache/apk/*
100+
# Install runtime dependencies
101+
RUN apk add --no-cache tzdata nginx openssl bash mariadb-client postgresql-client curl ffmpeg wget jq
102+
71103

72104
# Download and install latest yt-dlp binary for ARM64
73105
RUN LATEST_VERSION=$(curl -s https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest | jq -r .tag_name) && \
74106
wget -O /usr/local/bin/yt-dlp "https://github.com/yt-dlp/yt-dlp/releases/download/${LATEST_VERSION}/yt-dlp_linux_aarch64" && \
75107
chmod +x /usr/local/bin/yt-dlp
76108

77-
ENV TZ=UTC
78-
# Set environment variables
79-
ENV APP_ROOT=/pinepods
109+
# Download and install Horust (aarch64)
110+
RUN wget -O /tmp/horust.tar.gz "https://github.com/FedericoPonzi/Horust/releases/download/v0.1.7/horust-aarch64-unknown-linux-gnu.tar.gz" && \
111+
cd /tmp && tar -xzf horust.tar.gz && \
112+
mv horust /usr/local/bin/ && \
113+
chmod +x /usr/local/bin/horust && \
114+
rm -f /tmp/horust.tar.gz
80115

116+
ENV TZ=UTC
81117
# Copy compiled database setup binary (replaces Python dependency)
82118
COPY --from=python-builder /build/dist/pinepods-db-setup /usr/local/bin/
83-
84-
# Copy wait-for-it script
85-
COPY wait-for-it/wait-for-it.sh /wait-for-it.sh
86-
RUN chmod +x /wait-for-it.sh
87-
88-
# Copy built files from the builder stage
119+
# Copy built files from the builder stage to the Nginx serving directory
89120
COPY --from=builder /app/dist /var/www/html/
90-
91-
# Set up application directories and files
121+
# Copy Go API binary from the go-builder stage
122+
COPY --from=go-builder /gpodder-api/gpodder-api /usr/local/bin/
123+
# Copy Rust API binary from the rust-api-builder stage
124+
COPY --from=rust-api-builder /rust-api/target/release/pinepods-api /usr/local/bin/
125+
# Move to the root directory to execute the startup script
92126
WORKDIR /
127+
# Copy startup scripts
93128
COPY startup/startup.sh /startup.sh
94129
RUN chmod +x /startup.sh
95-
96-
RUN mkdir -p /pinepods /var/log/supervisor/
130+
# Copy Pinepods runtime files
131+
RUN mkdir -p /pinepods
132+
RUN mkdir -p /var/log/pinepods/ && mkdir -p /etc/horust/services/
97133
COPY startup/ /pinepods/startup/
134+
# Legacy cron scripts removed - background tasks now handled by internal Rust scheduler
98135
COPY clients/ /pinepods/clients/
99136
COPY database_functions/ /pinepods/database_functions/
100-
# Legacy cron scripts removed - background tasks now handled by internal Rust scheduler
101137
RUN chmod +x /pinepods/startup/startup.sh
102-
103-
# Clean things up
104-
RUN rm -rf \
105-
/var/cache/apk/* \
106-
/root/.cache \
107-
/tmp/* \
108-
/var/tmp/* \
109-
/usr/share/man \
110-
/usr/share/doc
111-
112-
# Define and set the version
138+
ENV APP_ROOT=/pinepods
139+
# Define the build argument
113140
ARG PINEPODS_VERSION
141+
# Write the Pinepods version to the current_version file
114142
RUN echo "${PINEPODS_VERSION}" > /pinepods/current_version
143+
# Configure Nginx
144+
COPY startup/nginx.conf /etc/nginx/nginx.conf
145+
146+
# Copy script to start gpodder API
147+
COPY ./gpodder-api/start-gpodder.sh /usr/local/bin/
148+
RUN chmod +x /usr/local/bin/start-gpodder.sh
115149

116150
RUN cp /usr/share/zoneinfo/UTC /etc/localtime && \
117151
echo "UTC" > /etc/timezone
118152

119-
# Configure Nginx
120-
COPY startup/nginx.conf /etc/nginx/nginx.conf
153+
# Expose ports
154+
EXPOSE 8080 8000
121155

156+
# Start everything using the startup script
122157
ENTRYPOINT ["bash", "/startup.sh"]

0 commit comments

Comments
 (0)