mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
Reintroduce TFE duration metadata: DB columns, form fields, controllers, views, and migration
Add 'unsafe-eval' to CSP script-src directives (htmx requires Function())
This commit is contained in:
@@ -83,21 +83,6 @@ chown -R www-data:xamxam /var/www/xamxam/storage/cache
|
||||
chmod -R 2775 /var/www/xamxam/storage/cache
|
||||
ok "Cache dirs: created and owned by www-data:xamxam"
|
||||
|
||||
# ── Step 1b: htpasswd file ──────────────────────────────────────────────────────
|
||||
printf "\n📋 Step 1b: Checking htpasswd file...\n"
|
||||
echo "--------------------------------------"
|
||||
|
||||
if [ -f "/etc/nginx/.htpasswd-xamxam" ]; then
|
||||
ok "htpasswd file exists: /etc/nginx/.htpasswd-xamxam"
|
||||
elif [ -f "/etc/nginx/.htpasswd-posterg" ]; then
|
||||
cp /etc/nginx/.htpasswd-posterg /etc/nginx/.htpasswd-xamxam
|
||||
chmod 644 /etc/nginx/.htpasswd-xamxam
|
||||
ok "Migrated .htpasswd-posterg → .htpasswd-xamxam"
|
||||
else
|
||||
warn "No htpasswd file found — admin panel will return 403 until one is created"
|
||||
warn "Run: sudo htpasswd -c /etc/nginx/.htpasswd-xamxam <username>"
|
||||
fi
|
||||
|
||||
# ── Step 2: Nginx config ──────────────────────────────────────────────────────
|
||||
printf "\n📋 Step 2: Deploying nginx configuration...\n"
|
||||
echo "--------------------------------------------"
|
||||
|
||||
95
scripts/fix-banner-path-view.php
Executable file
95
scripts/fix-banner-path-view.php
Executable file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* One-shot repair: fix v_theses_full / v_theses_public after migration 040
|
||||
* accidentally included the already-dropped banner_path column.
|
||||
*
|
||||
* Run from project root: php scripts/fix-banner-path-view.php
|
||||
*
|
||||
* This re-executes the view portion of migration 040 (with the fix applied)
|
||||
* so the views no longer reference t.banner_path.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../bootstrap.php';
|
||||
|
||||
$db = \App\Database::getInstance();
|
||||
$pdo = $db->getPdo();
|
||||
|
||||
echo "Dropping broken views...\n";
|
||||
$pdo->exec('DROP VIEW IF EXISTS v_theses_public');
|
||||
$pdo->exec('DROP VIEW IF EXISTS v_theses_full');
|
||||
|
||||
echo "Recreating v_theses_full (without banner_path)...\n";
|
||||
$pdo->exec("
|
||||
CREATE VIEW IF NOT EXISTS v_theses_full AS
|
||||
SELECT
|
||||
t.id,
|
||||
t.identifier,
|
||||
t.title,
|
||||
t.subtitle,
|
||||
t.year,
|
||||
t.is_doctoral,
|
||||
t.objet,
|
||||
o.name as orientation,
|
||||
ap.name as ap_program,
|
||||
ft.name as finality_type,
|
||||
t.synopsis,
|
||||
t.context_note,
|
||||
t.duration_value,
|
||||
t.duration_unit,
|
||||
at.name as access_type,
|
||||
lt.name as license_type,
|
||||
t.license_id,
|
||||
t.license_custom,
|
||||
t.access_type_id,
|
||||
t.jury_points,
|
||||
t.submitted_at,
|
||||
t.defense_date,
|
||||
t.published_at,
|
||||
t.is_published,
|
||||
t.baiu_link,
|
||||
t.exemplaire_baiu,
|
||||
t.exemplaire_erg,
|
||||
t.cc2r,
|
||||
t.remarks,
|
||||
t.jury_note_added,
|
||||
t.contact_visible,
|
||||
GROUP_CONCAT(DISTINCT a.name ORDER BY a.name ASC) as authors,
|
||||
GROUP_CONCAT(DISTINCT s.name) as supervisors,
|
||||
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'president' THEN s.name END) as jury_president,
|
||||
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 0 THEN s.name END) as jury_promoteurs,
|
||||
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 1 THEN s.name END) as jury_promoteurs_ulb,
|
||||
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 0 THEN s.name END) as jury_lecteurs_internes,
|
||||
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 1 THEN s.name END) as jury_lecteurs_externes,
|
||||
GROUP_CONCAT(DISTINCT l.name) as languages,
|
||||
GROUP_CONCAT(DISTINCT fmt.name) as formats,
|
||||
GROUP_CONCAT(DISTINCT tg.name) as keywords,
|
||||
-- First author's email and contact-visibility flag
|
||||
(SELECT a2.email FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_email,
|
||||
(SELECT a2.show_contact FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_show_contact
|
||||
FROM theses t
|
||||
LEFT JOIN orientations o ON t.orientation_id = o.id
|
||||
LEFT JOIN ap_programs ap ON t.ap_program_id = ap.id
|
||||
LEFT JOIN finality_types ft ON t.finality_id = ft.id
|
||||
LEFT JOIN access_types at ON t.access_type_id = at.id
|
||||
LEFT JOIN license_types lt ON t.license_id = lt.id
|
||||
LEFT JOIN thesis_authors ta ON t.id = ta.thesis_id
|
||||
LEFT JOIN authors a ON ta.author_id = a.id
|
||||
LEFT JOIN thesis_supervisors ts ON t.id = ts.thesis_id
|
||||
LEFT JOIN supervisors s ON ts.supervisor_id = s.id
|
||||
LEFT JOIN thesis_languages tl ON t.id = tl.thesis_id
|
||||
LEFT JOIN languages l ON tl.language_id = l.id
|
||||
LEFT JOIN thesis_formats tf ON t.id = tf.thesis_id
|
||||
LEFT JOIN format_types fmt ON tf.format_id = fmt.id
|
||||
LEFT JOIN thesis_tags tt ON t.id = tt.thesis_id
|
||||
LEFT JOIN tags tg ON tt.tag_id = tg.id
|
||||
GROUP BY t.id;
|
||||
");
|
||||
|
||||
echo "Recreating v_theses_public...\n";
|
||||
$pdo->exec("
|
||||
CREATE VIEW IF NOT EXISTS v_theses_public AS
|
||||
SELECT * FROM v_theses_full
|
||||
WHERE is_published = 1
|
||||
");
|
||||
|
||||
echo "Done. Views recreated without banner_path.\n";
|
||||
@@ -1,199 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Manage admin users for XAMXAM nginx basic authentication
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
PASSWORD_FILE="/etc/nginx/.htpasswd-xamxam"
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Error: This script must be run as root (use sudo)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if htpasswd is available
|
||||
if ! command -v htpasswd &> /dev/null; then
|
||||
echo -e "${YELLOW}Installing apache2-utils...${NC}"
|
||||
apt-get update -qq
|
||||
apt-get install -y apache2-utils
|
||||
fi
|
||||
|
||||
show_menu() {
|
||||
echo ""
|
||||
echo -e "${BLUE}════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE} XAMXAM Admin User Management${NC}"
|
||||
echo -e "${BLUE}════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
echo "1. List all users"
|
||||
echo "2. Add new user"
|
||||
echo "3. Change user password"
|
||||
echo "4. Delete user"
|
||||
echo "5. Reset all (create new password file)"
|
||||
echo "6. Exit"
|
||||
echo ""
|
||||
echo -n "Choose an option [1-6]: "
|
||||
}
|
||||
|
||||
list_users() {
|
||||
echo ""
|
||||
if [ ! -f "$PASSWORD_FILE" ]; then
|
||||
echo -e "${YELLOW}No password file found.${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Current admin users:${NC}"
|
||||
echo "────────────────────────"
|
||||
cut -d: -f1 "$PASSWORD_FILE" | nl
|
||||
echo ""
|
||||
}
|
||||
|
||||
add_user() {
|
||||
echo ""
|
||||
echo -n "Enter new username: "
|
||||
read -r USERNAME
|
||||
|
||||
if [ -z "$USERNAME" ]; then
|
||||
echo -e "${RED}Username cannot be empty${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if user already exists
|
||||
if [ -f "$PASSWORD_FILE" ] && grep -q "^${USERNAME}:" "$PASSWORD_FILE"; then
|
||||
echo -e "${YELLOW}User '$USERNAME' already exists. Use option 3 to change password.${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
# Add user (use -c only if file doesn't exist)
|
||||
if [ ! -f "$PASSWORD_FILE" ]; then
|
||||
htpasswd -c "$PASSWORD_FILE" "$USERNAME"
|
||||
else
|
||||
htpasswd "$PASSWORD_FILE" "$USERNAME"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✓ User '$USERNAME' added successfully${NC}"
|
||||
}
|
||||
|
||||
change_password() {
|
||||
list_users
|
||||
echo -n "Enter username to change password: "
|
||||
read -r USERNAME
|
||||
|
||||
if [ -z "$USERNAME" ]; then
|
||||
echo -e "${RED}Username cannot be empty${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f "$PASSWORD_FILE" ]; then
|
||||
echo -e "${RED}Password file not found${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! grep -q "^${USERNAME}:" "$PASSWORD_FILE"; then
|
||||
echo -e "${RED}User '$USERNAME' not found${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
htpasswd "$PASSWORD_FILE" "$USERNAME"
|
||||
echo -e "${GREEN}✓ Password changed for user '$USERNAME'${NC}"
|
||||
}
|
||||
|
||||
delete_user() {
|
||||
list_users
|
||||
echo -n "Enter username to delete: "
|
||||
read -r USERNAME
|
||||
|
||||
if [ -z "$USERNAME" ]; then
|
||||
echo -e "${RED}Username cannot be empty${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ! -f "$PASSWORD_FILE" ]; then
|
||||
echo -e "${RED}Password file not found${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! grep -q "^${USERNAME}:" "$PASSWORD_FILE"; then
|
||||
echo -e "${RED}User '$USERNAME' not found${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -n "Are you sure you want to delete user '$USERNAME'? [y/N] "
|
||||
read -r CONFIRM
|
||||
|
||||
if [ "$CONFIRM" = "y" ] || [ "$CONFIRM" = "Y" ]; then
|
||||
htpasswd -D "$PASSWORD_FILE" "$USERNAME"
|
||||
echo -e "${GREEN}✓ User '$USERNAME' deleted${NC}"
|
||||
else
|
||||
echo "Cancelled"
|
||||
fi
|
||||
}
|
||||
|
||||
reset_all() {
|
||||
echo ""
|
||||
echo -e "${YELLOW}WARNING: This will delete ALL existing users!${NC}"
|
||||
echo -n "Are you sure? [y/N] "
|
||||
read -r CONFIRM
|
||||
|
||||
if [ "$CONFIRM" != "y" ] && [ "$CONFIRM" != "Y" ]; then
|
||||
echo "Cancelled"
|
||||
return
|
||||
fi
|
||||
|
||||
# Backup existing file
|
||||
if [ -f "$PASSWORD_FILE" ]; then
|
||||
BACKUP="${PASSWORD_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
cp "$PASSWORD_FILE" "$BACKUP"
|
||||
echo -e "${GREEN}✓ Backed up to: $BACKUP${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -n "Enter new username: "
|
||||
read -r USERNAME
|
||||
|
||||
if [ -z "$USERNAME" ]; then
|
||||
echo -e "${RED}Username cannot be empty${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
htpasswd -c "$PASSWORD_FILE" "$USERNAME"
|
||||
echo -e "${GREEN}✓ Password file reset with user '$USERNAME'${NC}"
|
||||
}
|
||||
|
||||
# Main loop
|
||||
while true; do
|
||||
show_menu
|
||||
read -r CHOICE
|
||||
|
||||
case $CHOICE in
|
||||
1)
|
||||
list_users
|
||||
;;
|
||||
2)
|
||||
add_user
|
||||
;;
|
||||
3)
|
||||
change_password
|
||||
;;
|
||||
4)
|
||||
delete_user
|
||||
;;
|
||||
5)
|
||||
reset_all
|
||||
;;
|
||||
6)
|
||||
echo ""
|
||||
echo "Goodbye!"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Invalid option${NC}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
Reference in New Issue
Block a user