Browse Source

synchro 5/10/2022

pull/3/head
François 2 years ago
parent
commit
94c6f751a1
  1. 10
      bin/.foreign-domain-completion.bash
  2. 55
      bin/cloudOrgas.sh
  3. 6
      bin/createUser.sh
  4. 66
      bin/envoiMails.sh
  5. 163
      bin/foreign-domain.sh
  6. 88
      bin/gestUsers.sh
  7. 17
      bin/indicateurs.sh
  8. 179
      bin/interoGarradin.sh
  9. 24
      bin/restartAllCollabora.sh
  10. 16
      bin/sauve_memory.sh
  11. 2
      bin/sauve_serveur.sh
  12. 161
      bin/scriptSauve.sh
  13. 10
      bin/updateAllOrga.sh
  14. 3
      bin/updateCloud.sh
  15. 70
      bin/updateCloudApp.sh
  16. 71
      bin/verifExistenceMails.sh
  17. 13
      bin/verifPostfixGarradin.sh
  18. 6
      bin/verif_garradin.sh
  19. 4
      config/orgaTmpl/docker-compose.yml
  20. 6
      config/orgaTmpl/init-wiki.sh
  21. 1
      config/orgaTmpl/orga-gen.sh
  22. 19
      config/orgaTmpl/reload.sh
  23. 2
      config/skip-file.txt
  24. 3
      dockers/collabora/docker-compose.yml
  25. 6
      dockers/garradin/Dockerfile
  26. 2
      dockers/garradin/build.sh
  27. 121
      dockers/garradin/config/config.local.tmpl.php
  28. 2
      dockers/garradin/config/factory_cron.sh
  29. 14
      dockers/garradin/config/factory_cron_emails.sh
  30. 6
      dockers/garradin/installPlugins.sh
  31. 979
      dockers/gitea/logo.svg
  32. 8
      dockers/mattermost/docker-compose.yml
  33. 2
      dockers/postfix/Dockerfile
  34. 61
      dockers/proxy/config/nginx.tmpl.conf
  35. 4
      dockers/proxy/proxy-gen.sh
  36. 2
      dockers/sympa/build.sh
  37. 107
      dockers/sympa/filter/filter.sh
  38. 9
      dockers/sympa/reload.sh
  39. 2
      dockers/web/html/assets/html/footer.html
  40. 2
      dockers/web/html/index.html
  41. 2
      dockers/web/html/qui_sommes_nous.html
  42. 16
      dockers/web/web-gen.sh

10
bin/.foreign-domain-completion.bash

@ -45,20 +45,22 @@ _foreign_domain_completions () {
;;
"add")
case "${arg_pos}" in
3)
2)
declare -a availableOrga
availableOrga=($(sed -e "s/\(.*\)[ \t]*#.*$/\1/" -e "s/^[ \t]*\(.*\)-orga$/\1/" -e "/^$/d" "${KAZ_CONF_DIR}/container-orga.list"))
COMPREPLY=($(compgen -W "${availableOrga[*]}" -- "${cur}"))
;;
4)
local availableComposes=$(${KAZ_COMP_DIR}/${opt2}-orga/orga-gen.sh -l)
3)
local availableComposes=$(${KAZ_COMP_DIR}/${opt1}-orga/orga-gen.sh -l)
COMPREPLY=($(compgen -W "${availableComposes[*]}" -- "${cur}"))
;;
esac
;;
"del")
case "${arg_pos}" in
2)
1)
;;
*)
local availableComposes=$(${KAZ_BIN_DIR}/kazList.sh service validate|sed -e "s/\bcollabora\b//" -e "s/ / /")
declare -a availableDomaine
availableDomaine=($(for compose in ${availableComposes[@]} ; do

55
bin/cloudOrgas.sh

@ -1,4 +1,10 @@
#!/bin/bash
# Script de relance des dockers Nextcloud des Orgas
# Permet de lancer la commande d' optimisation des clouds
# Permet de connaitre la version des clouds
# Permet de relancer les dockers en mode a chaud ou à froid ( docker restart ou docker-compose down et up)
# lancer le script san arguments pour optenir de l' aide
#
KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
. $KAZ_ROOT/bin/.commonFunctions.sh
setKazVars
@ -9,11 +15,42 @@ PRG=$(basename $0)
RACINE=$(echo $PRG | awk '{print $1}')
TEMPO_ACTION_STOP=5
TEMPO_ACTION_START=20
TEMPO_ACTION_START=10
LIST_CLOUDS=$(ls /var/lib/docker/volumes/ | grep -i orga | grep -i cloudMain| sed -e 's/-cloudMain$//g' | sed -e 's/^orga_//')
NB_CLOUDS=$(ls /var/lib/docker/volumes/ | grep -i orga | grep -i cloudMain| sed -e 's/-cloudMain$//g' | sed -e 's/^orga_//' | wc -l )
COMPTEUR=$NB_CLOUDS
UpdateApplis() {
echo -e "${NC}"
echo "Mise à jour de toutes les applis installées y compris le cloud Principal"
for CLOUD in ${LIST_CLOUDS}
do
echo -e "${GREEN}${COMPTEUR}/${NB_CLOUDS} : ${CLOUD} "
echo -e "${NC}"
docker exec -ti -u 33 ${CLOUD}-nextcloudServ /var/www/html/occ app:update --all
COMPTEUR=$(expr $COMPTEUR - 1)
done
echo -e "${GREEN} Mise à jour des applis du cloud principal "
echo -e "${NC}"
docker exec -ti -u 33 nextcloudServ /var/www/html/occ app:update --all
}
Optimise_Cloud() {
echo "--------------------------------------------------------"
echo "${NC}Optimisation des cloud"
echo "--------------------------------------------------------"
for CLOUD in ${LIST_CLOUDS}
do
echo -e "$RED${CLOUD} (${COMPTEUR}/${NB_CLOUDS}) "
echo -e "$GREEN execution de :occ db:add-missing-indices"
docker exec -ti -u 33 ${CLOUD}-nextcloudServ /var/www/html/occ db:add-missing-indices
COMPTEUR=$(expr ${COMPTEUR} - 1)
done
echo "${NC}"
}
restart-compose() {
echo "--------------------------------------------------------"
echo "${NC} Arret / Relance de ${NB_CLOUDS} orga(s)"
@ -23,11 +60,11 @@ restart-compose() {
echo "${RED}- ${CLOUD}-orga${NC}($COMPTEUR/$NB_CLOUDS)"
cd /kaz/dockers/$CLOUD-orga
echo -n "${NC}Arrêt ... "
docker-compose down
docker-compose stop cloud
sleep ${TEMPO_ACTION_STOP}
echo "${GREEN}OK"
echo -n "${NC}Démarrage ... "
docker-compose up -d
docker-compose up -d cloud
sleep ${TEMPO_ACTION_START}
echo "${GREEN}OK"
COMPTEUR=$(expr $COMPTEUR - 1)
@ -45,7 +82,7 @@ restart() {
echo "--------------------------------------------------------"
for CLOUD in ${LIST_CLOUDS}
do
echo "${RED}- ${CLOUD}-orga${NC}($COMPTEUR/$NB_CLOUDS)"
echo "${RED} ${CLOUD}-orga ${NC}($COMPTEUR/$NB_CLOUDS)"
echo -n "${NC}Redemarrage ... "
docker restart $CLOUD-nextcloudServ
echo "${GREEN}OK"
@ -82,6 +119,8 @@ usage() {
echo "${PRG} -v -r -t -h
quand :
-v Donne la version des clouds et signale les MàJ
-o Lance la procédure Nextcloud pour optimiser les performances
-u Mets à jour les apllis des clouds
-t Dans le cas d' une mise à jour , redémarre avec tempo tous les dockers des orga ( docker-compose )
-r Redémarre tous les dockers des orga ( docker restart )
-h Cette aide :-)"
@ -90,6 +129,10 @@ quand :
########## Main #################
[ -z "$1" ] && { usage;exit; }
case "$1" in
'-o' )
Optimise_Cloud
exit
;;
'-v' )
version
exit
@ -98,6 +141,10 @@ case "$1" in
restart-compose
exit
;;
'-u' )
UpdateApplis
exit
;;
'-r' )
restart
exit

6
bin/createUser.sh

@ -577,7 +577,9 @@ echo "${DOCK_DIR}/postfix/setup.sh email add ${EMAIL_SOUHAITE} ${PASSWORD}" | te
echo "${DOCK_DIR}/postfix/setup.sh quota set ${EMAIL_SOUHAITE} ${QUOTA}G" | tee -a ${CMD}
#on attend qques secondes que le mail soit bien créé avant de continuer (prob de lecture de la BAL: à investiguer)
echo "sleep 10" | tee -a ${CMD}
#je rallonge à 20s car je vois que le docker sympa ne connait pas toujours l'email kaz créé
echo "on attend 20s pour que la création des emails soit certaine"
echo "sleep 20" | tee -a ${CMD}
NB_SERVICES_BASE=$((NB_SERVICES_BASE+1))
@ -624,7 +626,7 @@ Vous disposez de $((${NB_SERVICES_BASE} + ${NB_SERVICES_DEDIES})) services kaz a
Votre email et identifiant pour tous ces services: ${EMAIL_SOUHAITE}
Le mot de passe: ${PASSWORD}
Nous vous déconseillons de changer votre mot de passe dans l'immédiat (nous sommes en train d'y travailler!).
Changer votre mot de passe de messagerie n’est pas possible dans l'immédiat mais nous sommes en train d'y travailler!
Vous pouvez accéder à votre messagerie :
* soit depuis votre webmail: ${httpProto}://${URL_WEBMAIL}

66
bin/envoiMails.sh

@ -0,0 +1,66 @@
#!/bin/bash
#kan: 09/09/2022
#koi: envoyer un mail à une liste (sans utiliser sympa sur listes.kaz.bzh)
#ki : fab
#on récupère toutes les variables et mdp
# on prend comme source des repertoire le dossier du dessus ( /kaz dans notre cas )
KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
. "${KAZ_ROOT}/bin/.commonFunctions.sh"
setKazVars
SIMULATION=NO
CMD="/tmp/envoiMail_cmds_to_run.sh"
echo "#!/bin/bash" > ${CMD} && chmod +x ${CMD}
#################################################################################################################
MAIL_KAZ="
KAZ, association morbihannaise, propose de \"dégoogliser\" l’internet avec des solutions et services numériques libres alternatifs à ceux des GAFAM. Elle invite les habitants et les élus de Vannes et de sa région à une réunion publique d’information et d’échange :
Le jeudi 22 septembre 2022 à 18 heures
à la Maison des associations, 31 rue Guillaume Le Bartz à Vannes.
Cette invitation est destinée à toute personne sensible aux enjeux du numérique, aux risques pour la démocratie et les libertés, à sa participation au dérèglement climatique et à l’épuisement des ressources de notre planète.
Nous dirons qui nous sommes, quelles sont nos valeurs et quels sont concrètement les solutions et services que nous proposons, leurs conditions d’accès et l’accompagnement utile pour leur prise en main.
Les premières pierres de KAZ ont été posées voilà bientôt deux ans, en pleine pandémie de la COVID, par sept citoyens qui ont voulu répondre à l’appel de Framasoft de dégoogliser l’internet. Ne plus se lamenter sur la puissance des GAFAM, mais proposer des solutions et des services numériques alternatifs à ceux de Google, Amazon, Facebook, Apple et Microsoft en s’appuyant sur les fondamentaux Sobre, Libre, Éthique et Local.
A ce jour, près de 200 particuliers ont ouvert une adresse @kaz.bz, plus de 80 organisations ont souscrit au bouquet de services de KAZ et près de 800 collaborateurs d’organisations utilisatrices des services de KAZ participent peu ou prou au réseau de KAZ.
Beaucoup de services sont gratuits et accessibles sur le site https://kaz.bzh. D’autres demandent l’ouverture d’un compte moyennant une petite participation financière de 10€ par an pour les particuliers et de 30€ par an pour les organisations. Ceci est permis par le bénévolat des membres de la collégiale qui dirigent l’association et administrent les serveurs et les services.
A ce stade, de nombreuses questions se posent à KAZ. Quelle ambition de couverture de ses services auprès des particuliers et des organisations sur son territoire, le Morbihan ? Quel accompagnement dans la prise en main des outils ? Quels nouveaux services seraient utiles ?
Nous serions heureux de votre participation à notre réunion publique du 22 septembre d'une durée totale de 2h :
* Présentation valeurs / contexte (15mn)
* Présentation outils (45mn)
* Questions / Réponses (1h)
En restant à votre disposition,
La Collégiale de KAZ
"
#################################################################################################################
FIC_MAILS="/tmp/fic_mails"
while read EMAIL_CIBLE
do
echo "docker exec -i mailServ mailx -a 'Content-Type: text/plain; charset=\"UTF-8\"' -r contact@kaz.bzh -s \"Invitation rencontre KAZ jeudi 22 septembre à 18h00 à la Maison des assos à Vannes\" ${EMAIL_CIBLE} << EOF
${MAIL_KAZ}
EOF" | tee -a ${CMD}
echo "sleep 2" | tee -a ${CMD}
done < ${FIC_MAILS}
# des commandes à lancer ?
if [ "${SIMULATION}" == "NO" ];then
echo "on exécute"
${CMD}
else
echo "Aucune commande n'a été lancée: Possibilité de le faire à la main. cf ${CMD}"
fi

163
bin/foreign-domain.sh

@ -25,18 +25,37 @@ export SIMU=""
export CHANGE=""
usage(){
echo "Usage: ${PRG} list [sub-domain...]"
echo " ${PRG} [-n] add friend-domain orga [${garHost} ${cloudHost} ${dokuwikiHost} ${wordpressHost} ${matterHost}]"
echo " ${PRG} [-n] del friend-domain"
echo "Usage: ${PRG} list [friend-domain...]"
echo " ${PRG} [-n] add orga [${garHost} ${cloudHost} ${dokuwikiHost} ${wordpressHost} ${matterHost}] [friend-domain...] "
echo " ${PRG} [-n] del [friend-domain...]"
echo " ${PRG} -l"
echo " -l short list"
echo " -renewAll"
echo " -h help"
echo " -n simulation"
exit 1
}
for ARG in $@
do
export CERT_CFG="${KAZ_CONF_PROXY_DIR}/foreign-certificate"
createCert () {
(
fileName="${LETS_DIR}/$1-key.pem"
#[ -f "${fileName}" ] || return
# if [ -f "${fileName}" ]; then
# fileTime=$(stat --format='%Y' "${fileName}")
# current_time=$(date +%s)
# if (( "${fileTime}" > ( "${current_time}" - ( 60 * 60 * 24 * 89 ) ) )); then
# exit
# fi
# fi
printKazMsg "create certificat for $1"
${SIMU} docker exec -i proxyServ bash -c "/opt/certbot/bin/certbot certonly -n --nginx -d $1"
)
}
for ARG in $@; do
case "${ARG}" in
'-h' | '-help' )
usage
@ -45,6 +64,13 @@ do
shift
export SIMU="echo"
;;
'-renewAll')
for i in $("${KAZ_BIN_DIR}/foreign-domain.sh" -l); do
echo "$i"
createCert "$i" |grep failed
done
exit
;;
'-l')
for compose in ${availableComposes[@]} ; do
grep "server_name" "${KAZ_CONF_PROXY_DIR}/${compose}_kaz_name" | sed -e "s/[ \t]*\([^#]*\)#.*/\1/g" -e "/^$/d" -e "s/.*server_name[ \t]\([^ ;]*\).*/\1/"
@ -115,73 +141,88 @@ list () {
done
}
export CERT_CFG="${KAZ_CONF_PROXY_DIR}/foreign-certificate"
createCert () {
(
# fileName="${LETS_DIR}/$1-key.pem"
# if [ -f "${fileName}" ]; then
# fileTime=$(stat --format='%Y' "${fileName}")
# current_time=$(date +%s)
# if (( "${fileTime}" > ( "${current_time}" - ( 60 * 60 * 24 * 89 ) ) )); then
# exit
# fi
# fi
printKazMsg "create certificat for $1"
${SIMU} docker exec -i proxyServ bash -c "/opt/certbot/bin/certbot certonly -n --nginx -d $1"
)
}
########################################
add () {
[ $# -ne 3 ] && usage
badDomaine $1 && echo "bad domaine: ${RED}$1${NC}" && usage
badOrga $2 && echo "bad orga: ${RED}$2${NC} not in ${GREEN}${availableOrga[@]}${NC}" && usage
badCompose $3 && echo "bad compose: ${RED}$3${NC} not in ${GREEN}${availableComposes[@]}${NC}" && usage
# $1 : orga
# $2 : service
# $3 : friend-domain
[ $# -lt 3 ] && usage
badOrga $1 && echo "bad orga: ${RED}$1${NC} not in ${GREEN}${availableOrga[@]}${NC}" && usage
badCompose $2 && echo "bad compose: ${RED}$2${NC} not in ${GREEN}${availableComposes[@]}${NC}" && usage
ORGA=$1
COMPOSE=$2
shift; shift
CLOUD_SERVNAME="${ORGA}-${nextcloudServName}"
CLOUD_CONFIG="${DOCK_VOL}/orga_${ORGA}-cloudConfig/_data/config.php"
createCert $1
# XXX check compose exist in orga ?
previousOrga=$(listOrgaServ | grep $1)
[[ " ${previousOrga}" =~ " $1 => $2 : $3" ]] && echo " - already done" && return
[[ " ${previousOrga}" =~ " $1 " ]] && echo " - ${YELLOW}${BOLD}$(echo "${previousOrga}" | grep -e "$1")${NC} must be deleted before" && return
if [[ -n "${SIMU}" ]] ; then
echo "$1 $2; => ${KAZ_CONF_PROXY_DIR}/$3_kaz_map"
cat <<EOF
=> ${KAZ_CONF_PROXY_DIR}/$3_kaz_name
server_name $1;
# /kaz/bin/kazList.sh service enable ${ORGA}
if [ "${COMPOSE}" = "${cloudHost}" ]; then
if ! [[ "$(docker ps -f name=${CLOUD_SERVNAME} | grep -w ${CLOUD_SERVNAME})" ]]; then
printKazError "${CLOUD_SERVNAME} not running... abort"
exit
fi
fi
for FRIEND in $@; do
badDomaine "${FRIEND}" && echo "bad domaine: ${RED}${FRIEND}${NC}" && usage
done
for FRIEND in $@; do
createCert "${FRIEND}"
if [ "${COMPOSE}" = "${cloudHost}" ]; then
IDX=$(awk 'BEGIN {flag=0; cpt=0} /trusted_domains/ {flag=1} /)/ {if (flag) {print cpt+1; exit 0}} / => / {if (flag && cpt<$1) cpt=$1}' "${CLOUD_CONFIG}")
${SIMU} docker exec -ti -u 33 "${CLOUD_SERVNAME}" /var/www/html/occ config:system:set trusted_domains "${IDX}" --value="${FRIEND}"
fi
previousOrga=$(listOrgaServ | grep "${FRIEND}")
[[ " ${previousOrga}" =~ " ${FRIEND} => ${ORGA} : ${COMPOSE}" ]] && echo " - already done" && continue
[[ " ${previousOrga}" =~ " ${FRIEND} " ]] && echo " - ${YELLOW}${BOLD}$(echo "${previousOrga}" | grep -e "${FRIEND}")${NC} must be deleted before" && return
if [[ -n "${SIMU}" ]] ; then
echo "${FRIEND} ${ORGA}; => ${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_map"
cat <<EOF
=> ${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_name
server_name ${FRIEND};
EOF
else
echo "$1 $2;" >> "${KAZ_CONF_PROXY_DIR}/$3_kaz_map"
cat >> "${KAZ_CONF_PROXY_DIR}/$3_kaz_name" <<EOF
server_name $1;
else
echo "${FRIEND} ${ORGA};" >> "${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_map"
cat >> "${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_name" <<EOF
server_name ${FRIEND};
EOF
fi
echo "${PRG}: $1 added"
CHANGE="add"
fi
echo "${PRG}: ${FRIEND} added"
CHANGE="add"
done
#(cd "${KAZ_COMP_DIR}/${ORGA}-orga"; docker-compose restart)
}
########################################
del () {
[ $# -ne 1 ] && usage
badDomaine $1 && echo "bad domaine: ${RED}$1${NC}" && usage
previous=$(listOrgaServ | grep -e "$1")
[[ ! "${previous}" =~ ^$1 ]] && echo "$1 not found in ${previous}" && return
# XXX if done OK
# XXX del
for compose in ${availableComposes[@]} ; do
if grep -q -e "^[ \t]*$1[ \t]" "${KAZ_CONF_PROXY_DIR}/${compose}_kaz_map" ; then
${SIMU} sed -e "/^[ \t]*$1[ \t]/d" -i "${KAZ_CONF_PROXY_DIR}/${compose}_kaz_map"
fi
if grep -q -e "^[ \t]*server_name $1;" "${KAZ_CONF_PROXY_DIR}/${compose}_kaz_name" ; then
${SIMU} sed -i "${KAZ_CONF_PROXY_DIR}/${compose}_kaz_name" \
-e "/^[ \t]*server_name $1;/d"
fi
[ $# -lt 1 ] && usage
for FRIEND in $@; do
badDomaine "${FRIEND}" && echo "bad domaine: ${RED}${FRIEND}${NC}" && usage
previous=$(listOrgaServ | grep -e "${FRIEND}")
[[ ! "${previous}" =~ ^${FRIEND} ]] && echo "${FRIEND} not found in ${previous}" && continue
# XXX if done OK
for COMPOSE in ${availableComposes[@]} ; do
if grep -q -e "^[ \t]*${FRIEND}[ \t]" "${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_map" ; then
if [ "${COMPOSE}" = "${cloudHost}" ]; then
ORGA="$(grep "${FRIEND}" "${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_map" | sed "s/^${FRIEND}\s*\([^;]*\);/\1/")"
CLOUD_CONFIG="${DOCK_VOL}/orga_${ORGA}-cloudConfig/_data/config.php"
${SIMU} sed -e "/\d*\s*=>\s*'${FRIEND}'/d" -i "${CLOUD_CONFIG}"
fi
${SIMU} sed -e "/^[ \t]*${FRIEND}[ \t]/d" -i "${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_map"
fi
if grep -q -e "^[ \t]*server_name ${FRIEND};" "${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_name" ; then
${SIMU} sed -i "${KAZ_CONF_PROXY_DIR}/${COMPOSE}_kaz_name" \
-e "/^[ \t]*server_name ${FRIEND};/d"
fi
done
echo "${PRG}: ${FRIEND} deleted"
CHANGE="del"
done
echo "${PRG}: $1 deleted"
CHANGE="del"
}
########################################

88
bin/gestUsers.sh

@ -1,17 +1,16 @@
#!/bin/bash
#. $(dirname $0)/../config/dockers.env
#. $(dirname $0)/../secret/SetAllPass.sh
KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
# gestion des utilisateurs de kaz ( mail, cloud général, mattermost )
#KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
KAZ_ROOT=/kaz
. $KAZ_ROOT/bin/.commonFunctions.sh
setKazVars
. $DOCKERS_ENV
. $KAZ_ROOT/secret/SetAllPass.sh
VERSION="1.1"
VERSION="1.2"
PRG=$(basename $0)
IFS='.'
#IFS='.'
RACINE=$(echo $PRG | awk '{print $1}')
IFS=' '
BLINK='\033[0;5m'
@ -67,7 +66,6 @@ Search_Email() {
fi
}
#TODO passer l' authentification sur localhost:8000
Search_Mattermost() {
#Ici $1 est une adresse email
docker exec -ti ${mattermostServName} bin/mmctl --suppress-warnings auth login $httpProto://$URL_AGORA --name local-server --username $mattermost_user --password $mattermost_pass >/dev/null 2>&1
@ -93,11 +91,6 @@ Search_Mattermost() {
}
Recherche_par_fic() {
echo "Menu de recherche et modif par fichier"
Main
}
Info_Email() {
Search_Email
clear
@ -116,19 +109,23 @@ Info_Email() {
echo -e " ${RED} DETAILS DU COMPTE DANS GARRADIN"
echo -e "${GREEN}"
curl -s ${URL_GARRADIN}/api/sql -d "SELECT nom,adresse,code_postal,ville,email,email_secours,admin_orga,nom_orga,quota_disque FROM membres where email='${CHOIX_MAIL}' LIMIT 1;" >/tmp/$CHOIX_MAIL-garradin.json
sed -i -e 's/^[\{]"results"\:\[//g' -e 's/\]\}$//g' /tmp/$CHOIX_MAIL-garradin.json
jq .nom /tmp/$CHOIX_MAIL-garradin.json
jq .adresse /tmp/$CHOIX_MAIL-garradin.json
jq .code_postal /tmp/$CHOIX_MAIL-garradin.json
jq .ville /tmp/$CHOIX_MAIL-garradin.json
echo "Quota : "; jq .quota_disque /tmp/$CHOIX_MAIL-garradin.json
echo "Mail de secours : "; jq .email_secours /tmp/$CHOIX_MAIL-garradin.json
#sed -i -e 's/^[\{]"results"\:\[//g' -e 's/\]\}$//g' /tmp/$CHOIX_MAIL-garradin.json
jq .results[].nom /tmp/$CHOIX_MAIL-garradin.json
jq .results[].adresse /tmp/$CHOIX_MAIL-garradin.json
jq .results[].code_postal /tmp/$CHOIX_MAIL-garradin.json
jq .results[].ville /tmp/$CHOIX_MAIL-garradin.json
echo "Quota : "; jq .results[].quota_disque /tmp/$CHOIX_MAIL-garradin.json
echo "Mail de secours : "; jq .results[].email_secours /tmp/$CHOIX_MAIL-garradin.json
echo "alias :"
echo -n -e "${GREEN}"
grep -i ${CHOIX_MAIL} ${TFILE_EMAILS_ALIAS} | awk {'print $1'} | sed -e 's/\r/ /g'
echo -e ""
echo -e "${NC}------------------------------------------------"
echo -e ""
echo -e "${NC}"
echo "L' adresse apparait dans :"
echo -n -e "${GREEN}"
curl -s ${URL_GARRADIN}/api/sql -d "SELECT * FROM membres where emails_Rattaches like '%$CHOIX_MAIL%' ;" | jq .results[].nom
echo -e "${NC}"
read -p " ---------------------- Appuyer sur une touche pour continuer -------------------------"
clear
}
Search_destroy() {
@ -199,8 +196,12 @@ Search_destroy() {
else
echo -e "Erreur de suppression"
fi
echo -e "${NC}"
echo ""
echo -e "Envoi d'un message dans mattermost pour la suppression du compte"
docker exec -ti mattermostServ bin/mmctl post create kaz:Creation-Comptes --message "Le compte ${REP_SEARCH_DESTROY} est supprimé" >/dev/null 2>&1
MAIL_SUPPR="Suppresion du compte ${REP_SEARCH_DESTROY}"
docker exec -i mailServ mailx -a 'Content-Type: text/plain; charset="UTF-8"' -r contact@${domain} -s "Suppression de mail" contact@${domain} << EOF
${MAIL_SUPPR}
EOF
echo -e "${NC}"
read -p " ---------------------- Appuyer sur une touche pour continuer -------------------------"
Search_destroy
@ -213,7 +214,9 @@ Gest_Password() {
#cree un mdp acceptable par postfix/nc/mattermost
PASSWORD=_`apg -n 1 -m 10 -M NCL -d`-
COMPTE_A_MODIFIER=${CHOIX_MAIL}
MAIL_SECOURS=$(curl -s ${URL_GARRADIN}/api/sql -d "SELECT email_secours FROM membres where email='${COMPTE_A_MODIFIER}' LIMIT 1 ;" | sed -e 's/results//g' -e 's/email_secours//g' -e 's/[\"\:\[\{\}]//g' -e 's/\]//g')
FICMAILSECOURS=$(mktemp /tmp/FICMAILSECOURSXXXXX.json)
curl -s ${URL_GARRADIN}/api/sql -d "SELECT email_secours FROM membres where email='${COMPTE_A_MODIFIER}' LIMIT 1 ;" >$FICMAILSECOURS
MAIL_SECOURS=$(jq .results[].email_secours $FICMAILSECOURS | sed -e 's/\"//g')
if [ "$MAIL_SECOURS" = "" ]
then
ADRESSE_SEC="NON"
@ -225,23 +228,11 @@ Gest_Password() {
# si c' est le cas ça veut dire qu' il faut changer le mot de passe dans le cloud de l' orga
rm -rf /tmp/FICMAILORGA*
EMAIL_ORGA_TROUVE=0
for EMAIL_CHOIX in responsable_email email email_secours email2 email3 email4 email5
do
FICMAILORGA=$(mktemp /tmp/FICMAILORGAXXXXXXXXX.json)
curl -s ${URL_GARRADIN}/api/sql -d "SELECT * FROM membres where $EMAIL_CHOIX='$CHOIX_MAIL' LIMIT 1;" > $FICMAILORGA
sed -i -e 's/^[\{]"results"\:\[//g' -e 's/\]\}$//g' $FICMAILORGA
if [ $(jq .$EMAIL_CHOIX $FICMAILORGA | grep -i @) ]
then
echo -e "${RED} $EMAIL_CHOIX=${GREEN}$(jq .$EMAIL_CHOIX $FICMAILORGA)${NC}"
if [ $EMAIL_CHOIX != "email" ]
then
EMAIL_ORGA_TROUVE=$(expr $EMAIL_ORGA_TROUVE + 1 )
fi
fi
done
EMAIL_ORGA_TROUVE=$(curl -s ${URL_GARRADIN}/api/sql -d "SELECT id FROM membres where emails_Rattaches like '$CHOIX_MAIL' ;" | jq .results[].id | wc -l)
echo "$EMAIL_ORGA_TROUVE"
if [ $EMAIL_ORGA_TROUVE -ge 1 ]
then
echo -e "${RED} L' adresse est dans une orga $(jq .nom_orga $FICMAILORGA) IL EST PREFERABLE DE REPONDRE NON !!! ${NC}"
echo -e "${RED} L' adresse apparait dans plusieurs orga comme mails rattaché IL EST PREFERABLE DE REPONDRE NON !!! ${NC}"
fi
##########################################################################
read -p "ON CONTINUE ? [ o / n ]: " SEARCH_RESET_INPUT
@ -258,12 +249,23 @@ Gest_Password() {
echo -e "$GREEN Compte $RED $(Search_Mattermost $COMPTE_A_MODIFIER) ${NC}"
echo -e "$GREEN Compte Nextcloud $RED ${USER_NEXTCLOUD_MODIF} ${NC}"
echo -e "$GREEN Le mot de passe sera = $RED ${PASSWORD} ${NC}"
docker exec -ti mattermostServ bin/mmctl user change-password $(Search_Mattermost $COMPTE_A_MODIFIER) -p $PASSWORD
curl -H 'OCS-APIREQUEST: true' -X PUT $httpProto://admin:$nextcloud_NEXTCLOUD_ADMIN_PASSWORD@$URL_NC/ocs/v1.php/cloud/users/${USER_NEXTCLOUD_MODIF} -d key=password -d value=${PASSWORD}
docker exec -ti mattermostServ bin/mmctl user change-password $(Search_Mattermost $COMPTE_A_MODIFIER) -p $PASSWORD >/dev/null 2>&1
curl -H 'OCS-APIREQUEST: true' -X PUT $httpProto://admin:$nextcloud_NEXTCLOUD_ADMIN_PASSWORD@$URL_NC/ocs/v1.php/cloud/users/${USER_NEXTCLOUD_MODIF} -d key=password -d value=${PASSWORD} >/dev/null 2>&1
${SETUP_MAIL} email update ${COMPTE_A_MODIFIER} ${PASSWORD}
echo -e "Envoi d'un message dans mattermost pour la modification du mot de passe"
docker exec -ti mattermostServ bin/mmctl post create kaz:Creation-Comptes --message "Le mot de passe du compte ${COMPTE_A_MODIFIER} a été modifié" >/dev/null 2>&1
if [ $ADRESSE_SEC == "OUI" ]
then
echo -e "Mail a expédier a cette adresse : ${GREEN} $MAIL_SECOURS ${NC}"
echo -e "Envoi d'un message à l' adresse de secours : $GREEN${MAIL_SECOURS}${NC}"
MAIL_CHANG="
Hello,
le nouveau mot de passe de ${COMPTE_A_MODIFIER} est : ${PASSWORD}
A bientôt"
docker exec -i mailServ mailx -a 'Content-Type: text/plain; charset="UTF-8"' -r admin@${domain} -s "Modification du compte" $MAIL_SECOURS << EOF
${MAIL_CHANG}
EOF
fi
if [ $ADRESSE_SEC == "NON" ]
then

17
bin/indicateurs.sh

@ -19,12 +19,15 @@ echo "$(date +%Y-%m-%d-%H-%M-%S);" \
"$(find ${DOCK_VOL}/jirafeau_fileData/_data/files/ -name \*count| wc -l)" >> "${FIC_COLLECTE}"
echo "$(date +%Y-%m-%d-%H-%M-%S);" \
"depot-size;" \
"$(du -ks ${DOCK_VOL}/jirafeau_fileData/_data/files/ | awk -F " " '{print $1}')" >> "{$FIC_COLLECTE}"
"$(du -ks ${DOCK_VOL}/jirafeau_fileData/_data/files/ | awk -F " " '{print $1}')" >> "${FIC_COLLECTE}"
#PLACE DISQUE sur serveur
echo "$(date +%Y-%m-%d-%H-%M-%S);" \
"disk-system-size-used;" \
"$(df | grep sda | awk -F " " '{print $3}')" >> "${FIC_COLLECTE}"
echo "$(date +%Y-%m-%d-%H-%M-%S);" \
"disk-system-size-used-human;" \
"$(df -h | grep sda | awk -F " " '{print $3}')" >> "${FIC_COLLECTE}"
#nombre de mails kaz:
echo "$(date +%Y-%m-%d-%H-%M-%S);" \
@ -35,6 +38,10 @@ echo "$(date +%Y-%m-%d-%H-%M-%S);" \
echo "$(date +%Y-%m-%d-%H-%M-%S);" \
"mail_alias;" \
"$(cat ${KAZ_COMP_DIR}/postfix/config/postfix-virtual.cf | wc -l)" >> "${FIC_COLLECTE}"
#Nombre d' orgas
echo "$(date +%Y-%m-%d-%H-%M-%S);" \
"Orgas;" \
"$(ls -l /kaz/dockers/ | grep orga | wc -l)" >> "${FIC_COLLECTE}"
#stats des 2 postfix (mail+sympa)
EXP=$(/usr/bin/hostname -s)
@ -55,10 +62,16 @@ for line in $(ls -lt --time-style=long-iso "${DOCK_VOL}/postfix_mailData/_data/k
done
#pour pister les fuites mémoires
docker stats --no-stream --format "table {{.Name}}\t{{.Container}}\t{{.MemUsage}}" | sort -k 3 -h > "${KAZ_STATE_DIR}/metro/$(date +"%Y%m%d")_docker_kaz.log"
docker stats --no-stream --format "table {{.Name}}\t{{.Container}}\t{{.MemUsage}}" | sort -k 3 -h > "${KAZ_STATE_DIR}/metro/$(date +"%Y%m%d")_docker_memory_kaz.log"
ps aux --sort -rss > "${KAZ_STATE_DIR}/metro/$(date +"%Y%m%d")_ps_kaz.log"
free -hlt > "${KAZ_STATE_DIR}/metro/$(date +"%Y%m%d")_mem_kaz.log"
systemd-cgls --no-pager > "${KAZ_STATE_DIR}/metro/$(date +"%Y%m%d")_cgls_kaz.log"
for i in $(docker container ls --format "{{.ID}}"); do docker inspect -f '{{.State.Pid}} {{.Name}}' $i; done > "${KAZ_STATE_DIR}/metro/$(date +"%Y%m%d")_dockerpid_kaz.log"
#on piste cette saloperie d'ethercalc
#echo $(date +"%Y%m%d") >> "${KAZ_STATE_DIR}/metro/docker_stats_ethercalc.log"
#docker stats --no-stream ethercalcServ ethercalcDB >> "${KAZ_STATE_DIR}/metro/docker_stats_ethercalc.log"
#fab le 04/10/2022
#taille des dockers
docker system df -v > > "${KAZ_STATE_DIR}/metro/$(date +"%Y%m%d")_docker_size_kaz.log"

179
bin/interoGarradin.sh

@ -1,8 +1,7 @@
#!/bin/bash
#. $(dirname $0)/../config/dockers.env
#. $(dirname $0)/../secret/SetAllPass.sh
KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
KAZ_ROOT=/kaz
. $KAZ_ROOT/bin/.commonFunctions.sh
setKazVars
@ -18,7 +17,9 @@ TFILE_INT_GARRAGIN_ACTION=$(mktemp /tmp/XXXXXXXX_INT_GARRAGIN_ACTION.json)
TFILE_INT_GARRAGIN_IDFILE=$(mktemp /tmp/XXXXXXXX_TFILE_INT_GARRAGIN_IDFILE.json)
FILE_CREATEUSER="$KAZ_ROOT/tmp/createUser.txt"
trap "rm -f ${TFILE_INT_GARRAGIN_IDFILE} ${TFILE_INT_GARRAGIN_ACTION} " 0 1 2 3 15
sep=' '
#trap "rm -f ${TFILE_INT_GARRAGIN_IDFILE} ${TFILE_INT_GARRAGIN_ACTION} " 0 1 2 3 15
############################################ Fonctions #######################################################
TEXTE="
@ -51,85 +52,105 @@ TEXTE="
"
Int_Garradin_Action() {
# $1 est une action;
ACTION=$1
OPTION=$2
# on envoie la requête sur le serveur garradin avec la clause à créer
curl -s ${URL_GARRADIN}/api/sql -d "SELECT * from membres where action_auto='${ACTION}';" >>${TFILE_INT_GARRAGIN_ACTION}
REP_ID=$(jq -c '.results[].id ' ${TFILE_INT_GARRAGIN_ACTION})
if [ ! -z "${REP_ID}" ]
# $1 est une action;
ACTION=$1
OPTION=$2
# on envoie la requête sur le serveur garradin avec la clause à créer
# problème de gestion de remontée de données dans la table services_users quand le compte a plus de 2 activités
#curl -s ${URL_GARRADIN}/api/sql -d "SELECT * from membres cross join services_users on membres.id = services_users.id_user where membres.action_auto='${ACTION}';" >>${TFILE_INT_GARRAGIN_ACTION}
curl -s ${URL_GARRADIN}/api/sql -d "SELECT * from membres where action_auto='${ACTION}';" >>${TFILE_INT_GARRAGIN_ACTION}
REP_ID=$(jq -c '.results[].id ' ${TFILE_INT_GARRAGIN_ACTION})
if [ ! -z "${REP_ID}" ]
then
[ "$OPTION" = "silence" ] || echo -e "${RED}Nombre de compte ${ACTION} ${NC}= ${GREEN} $(echo ${REP_ID} | wc -w) ${NC}"
if [ -f "$FILE_CREATEUSER" ]
then
mv $FILE_CREATEUSER $FILE_CREATEUSER.$(date +%d-%m-%Y-%H:%M:%S)
fi
echo "# -------- Fichier généré le $(date +%d-%m-%Y-%H:%M:%S) ----------">${FILE_CREATEUSER}
echo "${TEXTE}" >>${FILE_CREATEUSER}
for VAL_ID in ${REP_ID}
do
jq -c --argjson val "${VAL_ID}" '.results[] | select (.id == $val)' ${TFILE_INT_GARRAGIN_ACTION} > ${TFILE_INT_GARRAGIN_IDFILE}
for VAL_GAR in id_category action_auto nom email email_secours quota_disque admin_orga nom_orga responsable_organisation responsable_email email2 email3 email4 email5 agora cloud wordpress garradin docuwiki id_service
do
eval $VAL_GAR=$(jq .$VAL_GAR ${TFILE_INT_GARRAGIN_IDFILE})
done
#comme tout va bien on continue
# on compte le nom de champs dans la zone nom pour gérer les noms et prénoms composés
# si il y a 3 champs, on associe les 2 premieres valeurs avec un - et on laisse le 3ème identique
# si il y a 4 champs on associe les 1 et le 2 avec un tiret et le 3 et 4 avec un tiret
# on met les champs nom_ok et prenom_ok à blanc
nom_ok=""
prenom_ok=""
# on regarde si le nom de l' orga est renseigné ou si le nom de l' orga est null et l' activité de membre est 7 (membre rattaché)
# si c' est le cas alors le nom est le nom de l' orga et le prénom est forcé à la valeur Organisation
if [[ "$nom_orga" = null ]] || [[ "$nom_orga" != null && "$id_service" = "7" ]]
then
[ "$OPTION" = "silence" ] || echo -e "${NC}Abonné ${GREEN}${nom}${NC}"
#si lactivité est membre rattaché on affiche a quelle orga il est rattaché
if [ "$id_service" = "7" ] && [ "$OPTION" != "silence" ] && [ "$nom_orga" != null ]
then
[ "$OPTION" = "silence" ] || echo -e "${RED}Nombre de compte ${ACTION} ${NC}= ${GREEN} $(echo ${REP_ID} | wc -w) ${NC}"
if [ -f "$FILE_CREATEUSER" ]
then
#[ "$OPTION" = "silence" ] || echo "Le fichier des users existe , je le renomme en $FILE_CREATEUSER.$(date +%d-%m-%Y-%H:%M:%S)"
mv $FILE_CREATEUSER $FILE_CREATEUSER.$(date +%d-%m-%Y-%H:%M:%S)
echo -e "${NC}Orga Rattachée : ${GREEN}${nom_orga}${NC}"
fi
COMPTE_NOM=$(echo $nom | awk -F' ' '{for (i=1; i != NF; i++); print i;}')
case "${COMPTE_NOM}" in
0|1)
echo "Il faut corriger le champ nom (il manque un nom ou prénom) de garradin"
echo "je quitte et supprime le fichier ${FILE_CREATEUSER}"
rm -f $FILE_CREATEUSER
exit
;;
2)
nom_ok=$(echo $nom | awk -F' ' '{print $1}')
prenom_ok=$(echo $nom | awk -F' ' '{print $2}')
;;
*)
nom_ok=
prenom_ok=
for i in ${nom}; do grep -q '^[A-Z]*$' <<<"${i}" && nom_ok="${nom_ok}${sep}${i}" || prenom_ok="${prenom_ok}${sep}${i}"; done
nom_ok="${nom_ok#${sep}}"
prenom_ok="${prenom_ok#${sep}}"
if [ -z "${nom_ok}" ] || [ -z "${prenom_ok}" ]; then
echo "Il faut corriger le champ nom (peut être un nom de famille avec une particule ?) de garradin"
echo "je quitte et supprime le fichier ${FILE_CREATEUSER}"
rm -f $FILE_CREATEUSER
exit
fi
echo "# -------- Fichier généré le $(date +%d-%m-%Y-%H:%M:%S) ----------">${FILE_CREATEUSER}
echo "${TEXTE}" >>${FILE_CREATEUSER}
for VAL_ID in ${REP_ID}
do
jq -c --argjson val "${VAL_ID}" '.results[] | select (.id == $val)' ${TFILE_INT_GARRAGIN_ACTION} > ${TFILE_INT_GARRAGIN_IDFILE}
for VAL_GAR in action_auto nom email email_secours quota_disque admin_orga nom_orga responsable_organisation responsable_email email2 email3 email4 email5 agora cloud wordpress garradin docuwiki
do
eval $VAL_GAR=$(jq .$VAL_GAR ${TFILE_INT_GARRAGIN_IDFILE})
done
#comme tout va bien on continue
# on compte le nom de champs dans la zone nom pour gérer les noms et prénoms composés
# si il y a 3 champs, on associe les 2 premieres valeurs avec un - et on laisse le 3ème identique
# si il y a 4 champs on associe les 1 et le 2 avec un tiret et le 3 et 4 avec un tiret
# on met les champs nom_ok et prenom_ok à blanc
nom_ok=""
prenom_ok=""
# on regarde si le nom de l' orga est renseigné , si c' est le cas ( non null) alors le nom
# est le nom de l' orga et le prénom est forcé à la valeur Organisation
if [ "$nom_orga" = null ]
then
[ "$OPTION" = "silence" ] || echo -e "${NC}Abonné ${GREEN}${nom}${NC}"
COMPTE_NOM=$(echo $nom | awk -F' ' '{for (i=1; i != NF; i++); print i;}')
case "${COMPTE_NOM}" in
2)
nom_ok=$(echo $nom | awk -F' ' '{print $1}')
prenom_ok=$(echo $nom | awk -F' ' '{print $2}')
;;
*)
echo "Il faut corriger le champ nom de garradin, je quitte et supprime le fichier ${FILE_CREATEUSER}"
rm -f $FILE_CREATEUSER
exit
esac
# comme l' orga est à null nom orga est a vide, pas d' admin orga, on met dans l' agora générale
# pas d' équipe agora et de groupe nextcloud spécifique
esac
# comme l' orga est à null nom orga est a vide, pas d' admin orga, on met dans l' agora générale
# pas d' équipe agora et de groupe nextcloud spécifique
nom_orga=" "
admin_orga="N"
nc_base="O"
equipe_agora=" "
groupe_nc_base=" "
else
# L' orga est renseigné dans garradin donc les nom et prenoms sont forcé a nom_orga et Organisation
# un équipe agora portera le nom de l' orga, le compte ne sera pas créé dans le nextcloud général
# et le compte est admin de son orga
[ "$OPTION" = "silence" ] || echo -e "${NC}Orga : ${GREEN}${nom_orga}${NC}"
nom_ok=$nom_orga
prenom_ok=organisation
equipe_agora=$nom_orga
groupe_nc_base=" "
nc_base="N"
admin_orga="O"
fi
# Pour le reste on renomme les null en N ( non ) et les valeurs 1 en O ( Oui)
cloud=$(echo $cloud | sed -e 's/null/N/g' | sed -e 's/1/O/g')
garradin=$(echo $garradin | sed -e 's/null/N/g' | sed -e 's/1/O/g')
wordpress=$(echo $wordpress | sed -e 's/null/N/g' | sed -e 's/1/O/g')
agora=$(echo $agora | sed -e 's/null/N/g' | sed -e 's/1/O/g')
docuwiki=$(echo $docuwiki | sed -e 's/null/N/g' | sed -e 's/1/O/g')
# et enfin on écrit dans le fichier
echo "$nom_ok;$prenom_ok;$email;$email_secours;$nom_orga;$admin_orga;$cloud;$garradin;$wordpress;$agora;$docuwiki;$nc_base;$groupe_nc_base;$equipe_agora;$quota_disque">>${FILE_CREATEUSER}
done
else
echo "Rien à créer"
fi
nom_orga=" "
admin_orga="N"
nc_base="O"
equipe_agora=" "
groupe_nc_base=" "
else
# L' orga est renseigné dans garradin donc les nom et prenoms sont forcé a nom_orga et Organisation
# un équipe agora portera le nom de l' orga, le compte ne sera pas créé dans le nextcloud général
# et le compte est admin de son orga
nom_orga=$(echo $nom_orga | tr [:upper:] [:lower:])
[ "$OPTION" = "silence" ] || echo -e "${NC}Orga : ${GREEN}${nom_orga}${NC}"
nom_ok=$nom_orga
prenom_ok=organisation
equipe_agora=$nom_orga
groupe_nc_base=" "
nc_base="N"
admin_orga="O"
fi
# Pour le reste on renomme les null en N ( non ) et les valeurs 1 en O ( Oui)
cloud=$(echo $cloud | sed -e 's/null/N/g' | sed -e 's/1/O/g')
garradin=$(echo $garradin | sed -e 's/null/N/g' | sed -e 's/1/O/g')
wordpress=$(echo $wordpress | sed -e 's/null/N/g' | sed -e 's/1/O/g')
agora=$(echo $agora | sed -e 's/null/N/g' | sed -e 's/1/O/g')
docuwiki=$(echo $docuwiki | sed -e 's/null/N/g' | sed -e 's/1/O/g')
# et enfin on écrit dans le fichier
echo "$nom_ok;$prenom_ok;$email;$email_secours;$nom_orga;$admin_orga;$cloud;$garradin;$wordpress;$agora;$docuwiki;$nc_base;$groupe_nc_base;$equipe_agora;$quota_disque">>${FILE_CREATEUSER}
done
else
echo "Rien à créer"
fi
}
#Int_Garradin_Action "A créer" "silence"
Int_Garradin_Action "A créer"

24
bin/restartAllCollabora.sh

@ -0,0 +1,24 @@
#!/bin/bash
# kan: 09/06/2022
# ki: françois
# koi: redémarrer tous les collabora en cours pour récupérer de la RAM
KAZ_ROOT=$(cd "$(dirname $0)/.."; pwd)
. "${KAZ_ROOT}/bin/.commonFunctions.sh"
setKazVars
. "${DOCKERS_ENV}"
cd "${KAZ_COMP_DIR}"
for ORGA_DIR in *-orga; do
ORGA=${ORGA_DIR%-orga}
SERV_NAME="${ORGA}-${nextcloudServName}"
[[ "$(docker ps -f name=${SERV_NAME} | grep -w ${SERV_NAME})" ]] || continue
(
echo restart collabora - ${ORGA}
cd "${KAZ_COMP_DIR}/${ORGA_DIR}"
docker-compose stop collabora
docker-compose start collabora
)
done

16
bin/sauve_memory.sh

@ -11,13 +11,23 @@
#calc
docker restart ethercalcDB ethercalcServ
#sympa
docker exec -it sympaServ service sympa restart
#sympa
#docker restart sympaServ
#/kaz/dockers/sympa/reload.sh
# --> bof, ça arrête mal le bazar (4 mails d'ano autour de sympa_msg.pl / bounced.pl / task_manager.pl / bulk.pl / archived.pl)
#sympa
# restart de sympa et relance du script de copie des librairies du filtre de messages
docker exec -it sympaServ service sympa stop
sleep 5
docker exec -it sympaServ service sympa start
/kaz/dockers/sympa/reload.sh
#pour restart cette s.... de collabora
/kaz/bin/restartAllCollabora.sh
#postfix
docker exec -it mailServ supervisorctl restart changedetector
#proxy
docker exec -i proxyServ bash -c "/etc/init.d/nginx reload"

2
bin/sauve_serveur.sh

@ -8,6 +8,8 @@ dpkg --get-selections > $PATH_SAUVE/dpkg_selection
tar -clzf $PATH_SAUVE/etc_sauve.tgz /etc 1> /dev/null 2> /dev/null
tar -clzf $PATH_SAUVE/var_spool.tgz /var/spool 1> /dev/null 2> /dev/null
tar -clzf $PATH_SAUVE/root.tgz /root 1> /dev/null 2> /dev/null
tar -clzf $PATH_SAUVE/kaz.tgz /kaz 1> /dev/null 2> /dev/null
rsync -a /var/spool/cron/crontabs $PATH_SAUVE
#sauve les bases
/kaz/bin/container.sh save

161
bin/scriptSauve.sh

@ -0,0 +1,161 @@
#!/bin/bash
# Didier le 14 Septembre 2022
#
# TODO : Inclure un script post et pre.
#
#####################################################
#KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
KAZ_ROOT="/kaz"
. $KAZ_ROOT/bin/.commonFunctions.sh
setKazVars
. $DOCKERS_ENV
. $KAZ_ROOT/secret/SetAllPass.sh
VERSION="1.0"
PRG=$(basename $0)
RACINE=$(echo $PRG | awk '{print $1}')
IFS=' '
#
#####################################################
MAILSOURCE="sauve@kaz.bzh"
VOLUME_SAUVEGARDES="/mnt/backup-nas1"
#SAUVE_REPO=${VOLUME_SAUVEGARDES}/SauveRepo
SAUVE_REPO=admin@nas-kaz1:/share/Backup/SauveRepo
MAIL_RAPPORT="didier@kaz.bzh;francois@kaz.bzh;fab@kaz.bzh;fanch@kaz.bzh"
#####################################################
SCRIPTLOG="/mnt/disk-nas1/log/${PRG}-$(date +%d-%m-%Y-%H-%M-%S).log"
FICLOG="/var/log/${PRG}.log"
#####################################################
# - la liste des repertoires à sauver séparés par un espace
LISTREPSAUV="/home /var/lib/docker/volumes"
#####################################################
# - Les sauvegardes à garder jour, semaines, mois
NB_BACKUPS_JOUR=15
NB_BACKUPS_SEM=8
NB_BACKUPS_MOIS=12
#####################################################
# Recevoir un mail quand la sauvegarde est OK ?
MAILOK=true
#####################################################
trap 'LogFic "script stoppé sur un SIGTERM ou SIGINT" >&2; exit 2' INT TERM
LogFic() {
[ ! -w ${FICLOG} ] && { echo "Probleme d' ecriture dans $FICLOG" ; exit 1 ;}
echo "$(date +%d-%m-%Y-%H-%M-%S) : $1" >> ${FICLOG}
}
#
ExpMail() {
MAIL_SOURCE=$1
MAIL_SUJET=$2
MAIL_DEST=$3
MAIL_TEXTE=$4
docker exec -i mailServ mailx -a 'Content-Type: text/plain; charset="UTF-8"' -r ${MAIL_SOURCE} -s "${MAIL_SUJET}" ${MAIL_DEST} << EOF
${MAIL_TEXTE}
EOF
}
Sauvegarde() {
#$1 est le repertoire à sauver, on créé le sous repertoire dans le repo
CODE_TMP=""
if [ -r $1 ]
then
echo "Sauvegarde $1" >>${SCRIPTLOG}
#mkdir -p ${SAUVE_REPO}/$1 >/dev/null 2>&1
#rdiff-backup --verbosity 3 $1 ${SAUVE_REPO}/$1 >>${SCRIPTLOG} 2>>${SCRIPTLOG}
rsync -aAHXh --del --stats --exclude 'files_trashbin' $1 ${SAUVE_REPO} >>${SCRIPTLOG} 2>>${SCRIPTLOG}
CODE_TMP=$?
else
LogFic "$1 n' existe pas ou n' est pas accessible en lecture"
CODE_TMP=1
fi
LogFic "Code Retour de la sauvegarde de $1 : ${CODE_TMP}"
BACKUP_EXIT=$(expr ${BACKUP_EXIT} + ${CODE_TMP} )
}
#
Purge() {
echo "Commande prune de rdiff-backup"
PRUNE_EXIT=$?
}
# ****************************************************** Main *******************************************************************
# Création du fichier de log
touch ${FICLOG}
#
LogFic "#########################################################################################################################"
LogFic " *************** ${PRG} Version ${VERSION} ***************"
LogFic "#########################################################################################################################"
# test si les variables importantes sont renseignées et sortie si tel n' est pas le cas
if [ -z "${VOLUME_SAUVEGARDES}" ] || [ -z "${SAUVE_REPO}" ]
then
echo "VOLUME_SAUVEGARDES et SAUVE_REPO à verifier"
LogFic "VOLUME_SAUVEGARDES et SAUVE_REPO à verifier"
LogFic "Sortie du script"
exit 1
fi
#####################################################################################################################################################
################### Mise en commentaire de cette section puisque le repo est en rsync ( voir plus tard comment gérer ça )
# test si le volume de sauvegarde est ok
#grep "${VOLUME_SAUVEGARDES}" /etc/mtab >/dev/null 2>&1
#if [ "$?" -ne "0" ]
#then
# echo "le volume de sauvegarde ${VOLUME_SAUVEGARDES} n' est pas monté"
# LogFic "Erreur de montage du volume ${VOLUME_SAUVEGARDES} de sauvegarde"
# exit 1
#fi
# Test si j' ai le droit d' écrire dans le Repo
# [ ! -w ${SAUVE_REPO} ] && { echo "Verifier le droit d' écriture dans ${SAUVE_REPO}" ; LogFic "Verifier le droit d' écriture dans ${SAUVE_REPO}"; exit 1;}
#####################################################################################################################################################
# Tout se passe bien on continue
LogFic " - Repertoire a sauver : ${LISTREPSAUV}"
#LogFic " - Volume Nfs monté : ${VOLUME_SAUVEGARDES}"
LogFic " - Destination des sauvegardes : ${SAUVE_REPO}"
LogFic " - Rapport par Mail : ${MAIL_RAPPORT}"
#LogFic " - Backups jour : ${NB_BACKUPS_JOUR} , Backups semaines : ${NB_BACKUPS_SEM} , Backups mois : ${NB_BACKUPS_MOIS}"
LogFic "#########################################################################################################################"
LogFic " - Démarrage de la sauvegarde"
LogFic " - Log dans ${SCRIPTLOG}"
BACKUP_EXIT=0
PRUNE_EXIT=0
for REPS in ${LISTREPSAUV}
do
LogFic "Sauvegarde de ${REPS}"
Sauvegarde ${REPS}
done
LogFic "Code retour compilé de toutes les sauvegardes : ${BACKUP_EXIT}"
################################## a gérer plus tard
#LogFic " - Démarrage du nettoyage des sauvegardes"
#Purge
#LogFic " - Code retour du Nettoyage des sauvegardes (0=OK; 1=WARNING, 2=ERROR) : ${PRUNE_EXIT}"
#
########################################################################################
# On teste le code retour de la sauvegarde, on log et on envoie des mails
case "${BACKUP_EXIT}" in
'0' )
IFS=''
MESS_SAUVE_OK="
Salut
La sauvegarde est ok, ce message peut être enlevé avec la variable MAILOK=false
Que la force soit avec toi
Ton esclave des sauvegardes"
LogFic " - la sauvegarde est OK"
[ "$MAILOK" = true ] && ExpMail ${MAILSOURCE} "Sauvegarde Ok" ${MAIL_RAPPORT} ${MESS_SAUVE_OK}
IFS=' '
;;
* )
IFS=''
MESS_SAUVE_ERR="
Salut
La sauvegarde est en Erreur
Le log à consulter est ${SCRIPTLOG}
Code retour de la Sauvegarde ( code Rsync ): ${BACKUP_EXIT}
Ton esclave des sauvegardes"
LogFic " - !!!!! Sauvegarde en Erreur !!!!!"
ExpMail ${MAILSOURCE} "!!!! Sauvegarde en Erreur !!!!" ${MAIL_RAPPORT} ${MESS_SAUVE_ERR}
IFS=' '
;;
esac
LogFic " - Fin de la sauvegarde"

10
bin/updateAllOrga.sh

@ -1,15 +1,13 @@
#!/bin/bash
KAZ_ROOT=$(cd "$(dirname $0)/../.."; pwd)
KAZ_ROOT=$(cd "$(dirname $0)/.."; pwd)
. "${KAZ_ROOT}/bin/.commonFunctions.sh"
setKazVars
cd "${KAZ_COMP_DIR}"
# after update docker-compose
for orga in ./dockers/*-orga
for orga in *-orga
do
${orga}/orga-gen.sh
./bin/container.sh stop "${orga}"
./bin/container.sh start "${orga}"
"${KAZ_ROOT}/bin/container.sh" stop "${orga}"
"${KAZ_ROOT}/bin/container.sh" start "${orga}"
done

3
bin/updateCloud.sh

@ -69,6 +69,9 @@ addVarInConf "mail_sendmailmode" " 'mail_sendmailmode' => 'smtp'," "'installed'
addVarInConf "mail_smtphost" " 'mail_smtphost' => 'smtp.kaz.bzh'," "'installed' => true,"
addVarInConf "mail_smtpmode" " 'mail_smtpmode' => 'smtp'," "'installed' => true,"
addVarInConf "enable_previews" " 'enable_previews' => false," "'installed' => true,"
addVarInConf "trashbin_retention_obligation" " 'trashbin_retention_obligation' => '30, auto'," "'installed' => true,"
#pour supprimer le message "obtenir un compte gratuit" dans le footer
addVarInConf "simpleSignUpLink.shown" " 'simpleSignUpLink.shown' => false," "'installed' => true,"
if ! [[ "$(docker ps -f name=${DockerServName} | grep -w ${DockerServName})" ]]; then
printKazError "DockerServName not running... abort"

70
bin/updateCloudApp.sh

@ -5,15 +5,67 @@ setKazVars
. $DOCKERS_ENV
. $KAZ_ROOT/secret/SetAllPass.sh
LISTE_APPS="tasks calendar contacts bookmarks richdocuments richdocumentscode external drawio rainloop ransomware_protection"
LISTE_APPS="tasks calendar contacts bookmarks mail richdocuments richdocumentscode external drawio rainloop ransomware_protection"
NB_CLOUDS=$(ls /var/lib/docker/volumes/ | grep -i orga | grep -i cloudMain| sed -e 's/-cloudMain$//g' | sed -e 's/^orga_//' | wc -l )
COMPTEUR=${NB_CLOUDS}
echo -e "$NC"
for cloud in $(docker ps | grep -i cloud |awk '{print $12}')
do
echo -e "$RED$cloud "
for app in $(echo $LISTE_APPS)
usage() {
echo "Usage $0 -h -a -l"
echo "-a : met à jour tous les applications"
echo "-l : met à jour ces applications ${LISTE_APPS}"
echo "-h : Cette aide"
exit
}
ToutesApplis() {
echo -e "${NC}"
echo "Mise à jour de toutes les applis installées"
for cloud in $(docker ps | grep -i cloud |awk '{print $12}')
do
echo -e "${COMPTEUR}/${NB_CLOUDS} : ${cloud} "
echo -e "${GREEN}"
docker exec -ti -u 33 ${cloud} /var/www/html/occ app:update --all
echo -e "${NC}"
COMPTEUR=$(expr $COMPTEUR - 1)
done
}
Liste_Apps() {
echo -e "${NC}"
echo "Mise à jour de ${LISTE_APPS}"
for cloud in $(docker ps | grep -i cloud |awk '{print $12}')
do
echo -e "$GREEN $app $NC"
docker exec -ti -u 33 $cloud /var/www/html/occ app:update $app
echo -e "${COMPTEUR}/${NB_CLOUDS} : ${cloud} "
for app in $(echo ${LISTE_APPS})
do
echo -e "${GREEN} ${app} ${NC}"
docker exec -ti -u 33 ${cloud} /var/www/html/occ app:update ${app}
echo -e "${NC}"
done
COMPTEUR=$(expr $COMPTEUR - 1)
done
done
}
################### Main #################
case "$1" in
'-h'|'' )
usage
exit
;;
'-l' )
Liste_Apps
exit
;;
'-a' )
ToutesApplis
exit
;;
'*' )
usage
exit
::
esac

71
bin/verifExistenceMails.sh

@ -0,0 +1,71 @@
#!/bin/bash
#Koi: on vérifie que chaque email possède son répertoire et vice et versa (on supprime sinon)
#Kan: 20/06/2022
#Ki: fab
#on récupère toutes les variables et mdp
# on prend comme source des repertoire le dossier du dessus ( /kaz dans notre cas )
KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
. "${KAZ_ROOT}/bin/.commonFunctions.sh"
setKazVars
cd $(dirname $0)/..
. "${DOCKERS_ENV}"
. "${KAZ_KEY_DIR}/SetAllPass.sh"
DOCK_DIR=$KAZ_COMP_DIR
#on détermine le script appelant, le fichier log et le fichier source, tous issus de la même racine
PRG=$(basename $0)
RACINE=${PRG%.sh}
#DOCK_DIR="/kaz/dockers"
# emails et les alias KAZ déjà créés
TFILE_EMAIL=$(mktemp /tmp/test_email.XXXXXXXXX.TFILE_EMAIL)
#on stocke les emails et les alias KAZ déjà créés
(
${DOCK_DIR}/postfix/setup.sh email list
# ${DOCK_DIR}/postfix/setup.sh alias list | awk '{print $1}'
) > ${TFILE_EMAIL}
#did on supprime le ^M en fin de fichier pour pas faire planter les grep
sed -i -e 's/\r//g' ${TFILE_EMAIL}
rep_email="/var/lib/docker/volumes/postfix_mailData/_data"
#étape n°1: pour chaque répertoire, on vérifie que l'email existe
echo "Début Etape n°1: on liste les répertoires des emails et on vérifie que les emails correspondant existent"
ls -Ifilter -Itmp ${rep_email} | while read fin_email; do
ls ${rep_email}/${fin_email} | while read debut_email; do
email=`echo ${debut_email}@${fin_email}`
#est-ce que l'email existe ?
nb_ligne=$(grep "^${email}$" ${TFILE_EMAIL} | wc -l)
if [ ${nb_ligne} -gt 0 ];then
false
else
#suppression du répertoire
echo rm ${rep_email}/${fin_email}/${debut_email} -rf
fi
done
#si le répertoire domaine est vide, on le supprime
find ${rep_email}/${fin_email} -maxdepth 0 -type d -empty -delete
done
echo "aucune commande n'a été lancée, possible de le faire à la main"
echo "Fin Etape n°1"
#Etape n°2: pour chaque email, on vérifie que le répertoire existe
echo "Début Etape n°2 n°2: on liste les emails et on vérifie que les répertoires correspondant existent"
cat ${TFILE_EMAIL} | while read email; do
debut_email=$(echo ${email} | awk -F '@' '{print $1}')
fin_email=$(echo ${email} | awk -F '@' '{print $2}')
if [ -d ${rep_email}/${fin_email}/${debut_email} ];then
true
else
echo "Attention, le répertoire ${fin_email}/${debut_email} n'existe pas alors que l'email existe!"
fi
done
echo "Fin Etape n°2"

13
bin/verifPostfixGarradin.sh

@ -0,0 +1,13 @@
#!/bin/bash
KAZ_ROOT=$(cd "$(dirname $0)"/..; pwd)
. $KAZ_ROOT/bin/.commonFunctions.sh
setKazVars
. $DOCKERS_ENV
. $KAZ_ROOT/secret/SetAllPass.sh
URL_AGORA=$(echo $matterHost).$(echo $domain)
docker exec -ti ${mattermostServName} bin/mmctl auth login $httpProto://$URL_AGORA --name local-server --username $mattermost_user --password $mattermost_pass >/dev/null 2>&1
MESSAGE_GARRADIN=$( ${KAZ_ROOT}/bin/verif_garradin.sh mono)
docker exec -ti mattermostServ bin/mmctl post create kaz:collegiale --message "$MESSAGE_GARRADIN" >/dev/null 2>&1

6
bin/verif_garradin.sh

@ -72,8 +72,8 @@ do
if [ -z "${TAB_RESU}" ]
then
echo -e "${RED} ${EMAIL_ADRESSES} : Rien dans garradin ${NEUTRE}"
else
echo -e "${NEUTRE} ${EMAIL_ADRESSES} :${TAB_RESU}"
#else
# echo -e "${NEUTRE} ${EMAIL_ADRESSES} :${TAB_RESU}"
fi
fi
fi
@ -85,7 +85,7 @@ echo " -------------------------------------------------------------------------
echo " Recherche si tous les mails de garradin existent dans postfix"
echo " ------------------------------------------------------------------------------"
TAB_MAIL_GARRADIN=$(jq '.results[]' ${FICGARRADIN} | grep -i @kaz.bzh | grep email | sort -u | sed -e 's/.*referent_kaz.*$//g' -e 's/.*email.*://g' -e 's/null.*//g' -e 's/,//g' -e 's/"//g')
TAB_MAIL_GARRADIN=$(jq '.results[].email, .results[].email2, .results[].email3, .results[].email4, .results[].email5' ${FICGARRADIN} | grep -i @${domain} | sort -u | sed -e 's/null.*//g' -e 's/"//g')
for EMAIL_TAB_MAIL_GARRADIN in ${TAB_MAIL_GARRADIN}
do
#EMAIL_TAB_MAIL_GARRADIN=$(echo $EMAIL_TAB_MAIL_GARRADIN | tr -d '[:space:]')

4
config/orgaTmpl/docker-compose.yml

@ -72,7 +72,8 @@ services:
- ../../secret/env-${officeServName}
environment:
- dictionaries=fr_FR en_GB es_ES
- domain=.*${orga}${cloudHost}\.${domain}
#- domain=.*${orga}${cloudHost}\.${domain}
- aliasgroup1=https://.*${orga}${cloudHost}\.${domain}:443
- server_name=${orga}${officeHost}.${domain}
- VIRTUAL_HOST=${orga}${officeHost}.${domain}
- VIRTUAL_PORT=9980
@ -148,6 +149,7 @@ services:
- WORDPRESS_SMTP_FROM_NAME=${orga}
volumes:
- wordpress:/var/www/html
# - ../../config/orgaTmpl/wp:/usr/local/bin/wp:ro
#}}
#{{wiki
dokuwiki:

6
config/orgaTmpl/init-wiki.sh

@ -22,9 +22,9 @@ then
exit
fi
TPL_DIR="${DOCK_VOL}/orga_${ORGA}-dokuwikiLibtpl/_data"
PLG_DIR="${DOCK_VOL}/orga_${ORGA}-dokuwikiPlugins/_data"
CONF_DIR="${DOCK_VOL}/orga_${ORGA}-dokuwikiConf/_data"
TPL_DIR="${DOCK_VOL}/orga_${ORGA}-wikiLibtpl/_data"
PLG_DIR="${DOCK_VOL}/orga_${ORGA}-wikiPlugins/_data"
CONF_DIR="${DOCK_VOL}/orga_${ORGA}-wikiConf/_data"
DNLD_DIR="${KAZ_DNLD_DIR}/dokuwiki"
DockerServName="${ORGA}-${dokuwikiServName}"
WIKI_URL="${httpProto}://${ORGA}-${dokuwikiHost}.${domain}"

1
config/orgaTmpl/orga-gen.sh

@ -53,6 +53,7 @@ do
ln -sf ../../config/dockers.env .env
ln -sf ../../config/orgaTmpl/orga-gen.sh
ln -sf ../../config/orgaTmpl/orga-rm.sh
ln -sf ../../config/orgaTmpl/reload.sh
PWD=$(pwd)
ORGA_DIR=$(basename ${PWD})
else

19
config/orgaTmpl/reload.sh

@ -0,0 +1,19 @@
#!/bin/bash
PRG=$(basename $0)
KAZ_ROOT=$(cd "$(dirname $0)/../.."; pwd)
. "${KAZ_ROOT}/bin/.commonFunctions.sh"
setKazVars
. "${DOCKERS_ENV}"
cd $(dirname $0)
PWD=$(pwd)
ORGA_DIR=$(basename ${PWD})
ORGA=${ORGA_DIR%-orga}
DockerServName="${ORGA}-${dokuwikiServName}"
if [ -f "${DOCK_VOL}/orga_${ORGA}-wikiData/_data/farms/init.sh" ]; then
docker exec -ti ${DockerServName} /dokuwiki/data/farms/init.sh
pkill -KILL lighttpd
fi

2
config/skip-file.txt

@ -85,3 +85,5 @@ dockers/sympa/filter/domainname
bin/DEADJOE
dockers/sympa/reload.sh.non.utilisé
dockers/garradin/input-form_php7.4.diff
dockers/kaz-orga.sav
dockers/garradin/config/config.local.tmpl.php.sav

3
dockers/collabora/docker-compose.yml

@ -16,7 +16,8 @@ services:
- ../../secret/env-${officeServName}
environment:
- dictionaries=fr_FR en_GB es_ES
- domain=.*${cloudHost}\.${domain}
#- domain=${cloudHost}.${domain}
- aliasgroup1=https://${cloudHost}.${domain}:443
- server_name=${officeHost}.${domain}
- VIRTUAL_HOST=${officeHost}.${domain}
- VIRTUAL_PORT=9980

6
dockers/garradin/Dockerfile

@ -3,7 +3,7 @@
FROM php:8.0-apache
# pour upgrader garradin, il suffit de modifier le numéro de version ici
ENV GARRADIN_VERSION 1.1.24
ENV GARRADIN_VERSION 1.1.30
ENV GARRADIN_DOWNLOAD_DIR download/garradin
ENV GARRADIN_DIR /usr/share/garradin
@ -61,13 +61,15 @@ COPY dockers/garradin/input-form_php7.4.diff ${GARRADIN_DIR}/include/lib/Garradi
RUN patch /usr/share/garradin/include/lib/Garradin/Template.php /usr/share/garradin/include/lib/Garradin/input-form_php7.4.diff
COPY dockers/garradin/config/factory_cron.sh ${GARRADIN_DIR}/
COPY dockers/garradin/config/factory_cron_emails.sh ${GARRADIN_DIR}/
COPY dockers/garradin/config/setupWebRights.sh ${GARRADIN_DIR}/
RUN mkdir ${GARRADIN_DIR}/users
#install cron pour factory_cron.sh
RUN apt-get install cron joe rsyslog -y
RUN sed -i '/imklog/s/^/#/' /etc/rsyslog.conf
RUN echo "0 0 * * * cd ${GARRADIN_DIR} && ${GARRADIN_DIR}/factory_cron.sh" >> /var/spool/cron/crontabs/root
RUN echo "0 1 * * * cd ${GARRADIN_DIR} && ${GARRADIN_DIR}/factory_cron.sh" >> /var/spool/cron/crontabs/root
RUN echo "* * * * * cd ${GARRADIN_DIR} && ${GARRADIN_DIR}/factory_cron_emails.sh" >> /var/spool/cron/crontabs/root
RUN chmod 600 /var/spool/cron/crontabs/root
RUN sed -i "/exec/i\service cron start\n" /usr/local/bin/docker-php-entrypoint
RUN ln -sf /usr/local/bin/php /usr/bin/

2
dockers/garradin/build.sh

@ -32,7 +32,7 @@ downloadFile "https://fossil.kd2.org/garradin/uv/garradin-${GAR_VER}.tar.gz"
downloadFile "https://fossil.kd2.org/garradin-plugins/uv/caisse.tar.gz"
#downloadFile "https://fossil.kd2.org/garradin-plugins/uv/dompdf.tar.gz"
downloadFile "https://fossil.kd2.org/garradin-plugins/uv/helloasso.tar.gz"
#downloadFile "https://fossil.kd2.org/garradin-plugins/uv/helloasso.tar.gz"
downloadFile "https://fossil.kd2.org/garradin-plugins/uv/ouvertures.tar.gz"
downloadFile "https://fossil.kd2.org/garradin-plugins/uv/reservations.tar.gz"
downloadFile "https://fossil.kd2.org/garradin-plugins/uv/stock_velos.tar.gz"

121
dockers/garradin/config/config.local.tmpl.php

@ -1,40 +1,120 @@
<?php
namespace Garradin;
if (!preg_match('/^([a-z0-9_\-]+)-garradin\.__DOMAIN__$/', $_SERVER['SERVER_NAME'], $match)) {
die('Accès invalide');
}
/**
* Ce fichier permet de configurer Garradin pour une utilisation
* avec plusieurs associations, mais une seule copie du code source.
* (aussi appel?? installation multi-sites, ferme ou usine)
*
* Voir la doc : https://fossil.kd2.org/garradin/wiki?name=Multi-sites
*
* N'oubliez pas d'installer ??galement le script cron.sh fournit
* pour lancer les rappels automatiques et sauvegardes.
*
* Si cela ne suffit pas ?? vos besoins, contactez-nous : https://garradin.eu/contact
* pour une aide sp??cifique ?? votre installation.
*/
// Nom de domaine parent des associations h??berg??es
// Exemple : si vos associations sont h??berg??es en clubdetennis.garradin.eu,
// indiquer ici 'garradin.eu'
const FACTORY_DOMAIN = "__DOMAIN__";
$user = $match[1];
$user_data_dir = __DIR__ . '/users/' . $user;
// R??pertoire o?? seront stock??es les donn??es des utilisateurs
// Dans ce r??pertoire, un sous-r??pertoire sera cr???? pour chaque compte
// Ainsi 'clubdetennis.garradin.eu' sera dans le r??pertoire courant (__DIR__),
// sous-r??pertoire 'users' et dans celui-ci, sous-r??pertoire 'clubdetennis'
//
// Pour chaque utilisateur il faudra cr??er le sous-r??pertoire en premier lieu
// (eg. mkdir .../users/clubdetennis)
const FACTORY_USER_DIRECTORY = __DIR__ . '/users';
const PREFER_HTTPS = false;
const SMTP_HOST = "__SMTP_HOST__.__DOMAIN__";
const SMTP_USER = null;
const API_USER = "__GARRADIN_API_USER__";
const API_PASSWORD = "__GARRADIN_API_PASSWORD__";
const SMTP_PASSWORD = null;
const SMTP_PORT = 25;
const SMTP_SECURITY = 'NONE';
// Envoyer les erreurs PHP par mail ?? l'adresse de l'administrateur syst??me
// (mettre ?? null pour ne pas recevoir d'erreurs)
const MAIL_ERRORS = 'garradin@kaz.bzh';
const ROOT = __DIR__;
// IMPORTANT !
// Modifier pour indiquer une valeur al??atoire de plus de 30 caract??res
const SECRET_KEY = 'HkXFwmMIMaI1T4X9/BIxKahxa74tQvAj0z1keal/jXj7i2w1ifzvalPSAshAbSg2P/fhmh9TlA3+gD28jg+ljA==';
const ENABLE_UPGRADES = false;
// Quota de stockage de documents (en octets)
// D??finit la taille de stockage disponible pour chaque association pour ses documents
const FILE_STORAGE_QUOTA = 10 * 1024 * 1024 * 1024; // 10 Go
////////////////////////////////////////////////////////////////
// R??glages conseill??s, normalement il n'y a rien ?? modifier ici
// Indiquer que l'on va utiliser cron pour lancer les t??ches ?? ex??cuter (envoi de rappels de cotisation)
const USE_CRON = true;
// Cache partag??
const SHARED_CACHE_ROOT = __DIR__ . '/cache';
// D??sactiver le log des erreurs PHP visible dans l'interface (s??curit??)
const ENABLE_TECH_DETAILS = false;
// D??sactiver les mises ?? jour depuis l'interface web
// Pour ??tre s??r que seul l'admin sys puisse faire des mises ?? jour
const ENABLE_UPGRADES = false;
////////////////////////////////////////////////////////////////
// Code 'magique' qui va configurer Garradin selon les r??glages
$login = null;
// Un sous-domaine ne peut pas faire plus de 63 caract??res
$login_regexp = '([a-z0-9_-]{1,63})';
$domain_regexp = sprintf('/^%s\.%s$/', $login_regexp, preg_quote(FACTORY_DOMAIN, '/'));
//original
//if (isset($_SERVER['SERVER_NAME']) && preg_match($regexp, $_SERVER['SERVER_NAME'], $match)) {
//maj kaz
if (isset($_SERVER['SERVER_NAME']) && preg_match('/^([a-z0-9_\-]+)-garradin\.__DOMAIN__$/', $_SERVER['SERVER_NAME'], $match)) {
$login = $match[1];
}
elseif (PHP_SAPI == 'cli' && !empty($_SERVER['GARRADIN_FACTORY_USER']) && preg_match('/^' . $login_regexp . '$/', $_SERVER['GARRADIN_FACTORY_USER'])) {
$login = $_SERVER['GARRADIN_FACTORY_USER'];
}
else {
// Login invalide ou non fourni
http_response_code(404);
die('<h1>Page non trouv??e</h1>');
}
$user_data_dir = rtrim(FACTORY_USER_DIRECTORY, '/') . '/' . $login;
if (!is_dir($user_data_dir)) {
mkdir($user_data_dir, 0700, true);
mkdir($user_data_dir, 0700, true);
//http_response_code(404);
//die("<h1>Cette association n'existe pas.</h1>");
}
// Définir le dossier où sont stockés les données
// D??finir le dossier o?? sont stock??s les donn??es
define('Garradin\DATA_ROOT', $user_data_dir);
const PREFER_HTTPS = false;
const SMTP_HOST = "__SMTP_HOST__.__DOMAIN__";
const SMTP_USER = null;
const API_USER = "__GARRADIN_API_USER__";
const API_PASSWORD = "__GARRADIN_API_PASSWORD__";
const SMTP_PASSWORD = null;
const SMTP_PORT = 25;
const SMTP_SECURITY = 'NONE';
const ROOT = __DIR__;
const DB_FILE = DATA_ROOT . '/association.sqlite';
const PLUGINS_ROOT = DATA_ROOT . '/plugins';
define('Garradin\WWW_URL', "__HTTP_PROTO__://".$user."-garradin.__DOMAIN__/");
// D??finir l'URL
//original
//define('Garradin\WWW_URL', 'https://' . $login . FACTORY_USER_DIRECTORY . '/');
//maj kaz
define('Garradin\WWW_URL', "__HTTP_PROTO__://".$login."-garradin.__DOMAIN__/");
define('Garradin\WWW_URI', '/');
// Désactiver le log des erreurs visible dans l'interface (sécurité)
define('Garradin\ERRORS_ENABLE_LOG_VIEW', true);
@ -42,7 +122,6 @@ define('Garradin\ERRORS_ENABLE_LOG_VIEW', true);
// Ne pas afficher les erreurs de code
define('Garradin\SHOW_ERRORS', true);
// Envoyer les erreurs par mail à cette adresse
define('Garradin\MAIL_ERRORS', 'garradin@kaz.bzh');
const SECRET_KEY = 'HkXFwmMIMaI1T4X9/BIxKahxa74tQvAj0z1keal/jXj7i2w1ifzvalPSAshAbSg2P/fhmh9TlA3+gD28jg+ljA==';
#add by fab le 21/04/2022
const PDF_COMMAND = 'prince';

2
dockers/garradin/config/factory_cron.sh

@ -7,6 +7,8 @@ FACTORY_USER_DIRECTORY="users"
# Chemin vers le script cron.php de Garradin
GARRADIN_CRON_SCRIPT="scripts/cron.php"
cd /usr/share/garradin
for user in $(cd ${FACTORY_USER_DIRECTORY} && ls -1d */)
do
GARRADIN_FACTORY_USER=$(basename "$user") /usr/bin/php $GARRADIN_CRON_SCRIPT

14
dockers/garradin/config/factory_cron_emails.sh

@ -0,0 +1,14 @@
#!/bin/sh
# Répertoire où sont stockées les données des utilisateurs
# veiller à ce que ce soit le même que dans config.local.php
FACTORY_USER_DIRECTORY="users"
# Chemin vers le script emails.php de Garradin
GARRADIN_CRON_SCRIPT="scripts/emails.php"
for user in $(cd ${FACTORY_USER_DIRECTORY} && ls -1d */)
do
GARRADIN_FACTORY_USER=$(basename "$user") /usr/bin/php $GARRADIN_CRON_SCRIPT
echo $GARRADIN_FACTORY_USER
done

6
dockers/garradin/installPlugins.sh

@ -38,11 +38,13 @@ do
done
if [ -z "${ORGA_SET}" ] ; then
printKazError "\n ${PRG}: no orga (give one of ${GAR_ORGA_LIST})."
exit
ORGA_SET=${GAR_ORGA_LIST}
fi
for ORGA in ${ORGA_SET}; do
if [ ! -d "${DOCK_VOL_GAR_ORGA}/${ORGA}/" ]; then
continue
fi
echo -ne "\n *** ${ORGA} plugins :"
for PLG in ${GAR_PLG_LIST}; do
echo -n " ${PLG}"

979
dockers/gitea/logo.svg

@ -0,0 +1,979 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 640 640"
style="enable-background:new 0 0 640 640"
xml:space="preserve"
width="32"
height="32"
version="1.1"
id="svg8"
sodipodi:docname="logo.svg"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"><metadata
id="metadata14"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs12" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2159"
inkscape:window-height="1675"
id="namedview10"
showgrid="false"
inkscape:zoom="38.229526"
inkscape:cx="16.59547"
inkscape:cy="20.409433"
inkscape:window-x="960"
inkscape:window-y="288"
inkscape:window-maximized="0"
inkscape:current-layer="svg8" /><path
style="fill:#fff"
d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12z"
id="path2" /><path
style="fill:#609926"
d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6zM125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1zm300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1z"
id="path4" /><image
width="169.37718"
height="142.20097"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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
cENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEv
IiB4OnhtcHRrPSJYTVAgQ29yZSA0LjQuMC1FeGl2MiI+CiA8cmRmOlJERiB4bWxuczpyZGY9Imh0
dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogIDxyZGY6RGVzY3Jp
cHRpb24gcmRmOmFib3V0PSIiCiAgICB4bWxuczppcHRjRXh0PSJodHRwOi8vaXB0Yy5vcmcvc3Rk
L0lwdGM0eG1wRXh0LzIwMDgtMDItMjkvIgogICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9i
ZS5jb20veGFwLzEuMC9tbS8iCiAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94
YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgeG1sbnM6cGx1cz0iaHR0cDovL25zLnVz
ZXBsdXMub3JnL2xkZi94bXAvMS4wLyIKICAgIHhtbG5zOkdJTVA9Imh0dHA6Ly93d3cuZ2ltcC5v
cmcveG1wLyIKICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIK
ICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgeG1sbnM6
eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICB4bXBNTTpEb2N1bWVudElEPSJn
aW1wOmRvY2lkOmdpbXA6ZGVhOTA4ZDItYTJkZC00NDhlLWIxNzItM2FjNjRlM2E5ODI5IgogICB4
bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjNkZGQ0M2U0LTk5ZmUtNDYzOC04OGNkLWYwODg0ZDU2
NzgyZiIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjkzYjIyYTZiLWI4Mzkt
NDZjMC05MDc1LTU0NzdjYTk1NGMxYyIKICAgR0lNUDpBUEk9IjIuMCIKICAgR0lNUDpQbGF0Zm9y
bT0iTGludXgiCiAgIEdJTVA6VGltZVN0YW1wPSIxNjU0NDMwNTg2MjYzMzk1IgogICBHSU1QOlZl
cnNpb249IjIuMTAuMjIiCiAgIGRjOkZvcm1hdD0iaW1hZ2UvcG5nIgogICB0aWZmOk9yaWVudGF0
aW9uPSIxIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJTVAgMi4xMCI+CiAgIDxpcHRjRXh0OkxvY2F0
aW9uQ3JlYXRlZD4KICAgIDxyZGY6QmFnLz4KICAgPC9pcHRjRXh0OkxvY2F0aW9uQ3JlYXRlZD4K
ICAgPGlwdGNFeHQ6TG9jYXRpb25TaG93bj4KICAgIDxyZGY6QmFnLz4KICAgPC9pcHRjRXh0Okxv
Y2F0aW9uU2hvd24+CiAgIDxpcHRjRXh0OkFydHdvcmtPck9iamVjdD4KICAgIDxyZGY6QmFnLz4K
ICAgPC9pcHRjRXh0OkFydHdvcmtPck9iamVjdD4KICAgPGlwdGNFeHQ6UmVnaXN0cnlJZD4KICAg
IDxyZGY6QmFnLz4KICAgPC9pcHRjRXh0OlJlZ2lzdHJ5SWQ+CiAgIDx4bXBNTTpIaXN0b3J5Pgog
ICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InNhdmVkIgogICAg
ICBzdEV2dDpjaGFuZ2VkPSIvIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmMwY2Y5
ZmZkLTYwMmItNDI4YS04YjQ1LTIwYmM2MGY2MjhmNiIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2Vu
dD0iR2ltcCAyLjEwIChMaW51eCkiCiAgICAgIHN0RXZ0OndoZW49IiswMTowMCIvPgogICAgIDxy
ZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIK
ICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDowYjE2ZGEzMy05MjU3LTRmYzEtYTBmZS00
MzQxMTBhMjEwMWUiCiAgICAgIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkdpbXAgMi4xMCAoTGludXgp
IgogICAgICBzdEV2dDp3aGVuPSIrMDE6MDAiLz4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFj
dGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0OmNoYW5nZWQ9Ii8iCiAgICAgIHN0RXZ0Omluc3RhbmNl
SUQ9InhtcC5paWQ6NWU3MGZiMTUtMmVlZi00Y2Q3LThmZWQtNzlmMGZiZDdiMjZhIgogICAgICBz
dEV2dDpzb2Z0d2FyZUFnZW50PSJHaW1wIDIuMTAgKExpbnV4KSIKICAgICAgc3RFdnQ6d2hlbj0i
KzAyOjAwIi8+CiAgICA8L3JkZjpTZXE+CiAgIDwveG1wTU06SGlzdG9yeT4KICAgPHBsdXM6SW1h
Z2VTdXBwbGllcj4KICAgIDxyZGY6U2VxLz4KICAgPC9wbHVzOkltYWdlU3VwcGxpZXI+CiAgIDxw
bHVzOkltYWdlQ3JlYXRvcj4KICAgIDxyZGY6U2VxLz4KICAgPC9wbHVzOkltYWdlQ3JlYXRvcj4K
ICAgPHBsdXM6Q29weXJpZ2h0T3duZXI+CiAgICA8cmRmOlNlcS8+CiAgIDwvcGx1czpDb3B5cmln
aHRPd25lcj4KICAgPHBsdXM6TGljZW5zb3I+CiAgICA8cmRmOlNlcS8+CiAgIDwvcGx1czpMaWNl
bnNvcj4KICA8L3JkZjpEZXNjcmlwdGlvbj4KIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0
IGVuZD0idyI/Pkb7dcoAAAAGYktHRADbANkA3uRVBFsAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAH
dElNRQfmBgUMAwZ/A1g/AAAgAElEQVR42uy9eZgcV3X3/62enqVnVBpJlhpJbll2C8Z4DGM8ICNb
ODEOYbUDNptj1hicGAKBF17DQwgYeAOYNYQt8IMshDWscQwBh8TYxvsi24ot22N5ZEkjjdUaLaOe
fbrr/v64dapuVVdvMzU9I/X38zz1dHV1d3V19b3nfu+5555rgcRJAoDjPloAiu7xNgAzAE4GcDmA
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
"
id="image849"
x="413.95416"
y="96.540276"
transform="rotate(26.21162)"
inkscape:transform-center-x="38.617587"
inkscape:transform-center-y="-16.964991" /></svg>

After

Width:  |  Height:  |  Size: 72 KiB

8
dockers/mattermost/docker-compose.yml

@ -3,13 +3,7 @@ version: "3"
services:
app:
build:
context: app
# uncomment following lines for team edition or change UID/GID
args:
- edition=team
- PUID=1000
- PGID=1000
image: mattermost/mattermost-team-edition:7.2
container_name: ${mattermostServName}
restart: ${restartPolicy}
# memory: 1G

2
dockers/postfix/Dockerfile

@ -1,4 +1,4 @@
FROM docker.io/mailserver/docker-mailserver:11.0
FROM docker.io/mailserver/docker-mailserver:11.1
########################################
# APT local cache

61
dockers/proxy/config/nginx.tmpl.conf

@ -11,7 +11,7 @@ http {
########################################
#### autoriser des uploads de 50Mo max
#### pour tous les sites
### sinon placer la variable dans chaque server{}
### sinon placer la variable dans chaque server{}
client_max_body_size 1024M;
add_header Set-Cookie lang="fr";
@ -23,6 +23,7 @@ http {
"~." $ssl_early_data;
default "";
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
@ -44,6 +45,13 @@ http {
ssl_certificate_key /etc/letsencrypt/live/__DOMAIN__/privkey.pem;
include includes/proxy_params;
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# ssl_prefer_server_ciphers off;
# ssl_stapling on;
# ssl_stapling_verify on;
# ssl_trusted_certificate /etc/letsencrypt/live/__DOMAIN__/fullchain.pem;
include includes/allow_ip;
# XXX >>>
# A concerver jusqu'en juin 2021
@ -144,6 +152,8 @@ http {
{{framadate
server {
server_name __DATE_HOST__.__DOMAIN__;
# pb nom en dur
server_name kazdate.__DOMAIN__;
include includes/port;
ssl_certificate /etc/letsencrypt/live/__DOMAIN__/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/__DOMAIN__/privkey.pem;
@ -232,8 +242,6 @@ http {
#### mattermost
{{mattermost
# proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:10m max_size=2g inactive=120m use_temp_path=off;
server {
server_name __MATTER_HOST__.__DOMAIN__;
include includes/port;
@ -243,24 +251,23 @@ http {
include includes/allow_ip;
ssl_ecdh_curve prime256v1:secp384r1:secp521r1;
# client_max_body_size 50M;
add_header X-Early-Data $tls1_3_early_data;
# test add_header X-Early-Data $tls1_3_early_data;
location ~ /api/v[0-9]+/(users/)?websocket$ {
proxy_pass http://__MATTER_HOST__.__DOMAIN__:8000;
proxy_http_version 1.1;
# test proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Connection "upgrade";
#test proxy_set_header Connection $connection_upgrade;
client_body_timeout 60;
send_timeout 300;
lingering_timeout 5;
proxy_connect_timeout 90;
proxy_send_timeout 300;
proxy_read_timeout 90s;
proxy_set_header X-Real-IP $remote_addr;
# test proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
# proxy_set_header X-Forwarded-For $remote_addr;
# test proxy_set_header Proxy "";
rewrite ^/(.+)$ /$1 break;
}
@ -269,11 +276,11 @@ http {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_read_timeout 600s;
# proxy_cache mattermost_cache;
# proxy_cache_revalidate on;
# proxy_cache_min_uses 2;
# proxy_cache_use_stale timeout;
# proxy_cache_lock on;
# proxy_cache mattermost_cache; # test
# proxy_cache_lock on; # test
# proxy_cache_min_uses 2; # test
# proxy_cache_revalidate on; # test
# proxy_cache_use_stale timeout; # test
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
@ -443,8 +450,6 @@ http {
}
}
# proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:10m max_size=2g inactive=120m use_temp_path=off;
server {
server_name ~^(?<asso>.+)-__MATTER_HOST__\.__DOMAIN__$;
include includes/agora_kaz_name;
@ -459,24 +464,23 @@ http {
include includes/allow_ip;
ssl_ecdh_curve prime256v1:secp384r1:secp521r1;
# client_max_body_size 50M;
add_header X-Early-Data $tls1_3_early_data;
location ~ /api/v[0-9]+/(users/)?websocket$ {
proxy_pass http://$asso-__MATTER_HOST__.__DOMAIN__:8000;
proxy_http_version 1.1;
proxy_set_header Connection "upgrade"; # test
# test proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# test proxy_set_header Connection $connection_upgrade;
client_body_timeout 60;
send_timeout 300;
lingering_timeout 5;
proxy_connect_timeout 90;
proxy_send_timeout 300;
proxy_read_timeout 90s;
proxy_set_header X-Real-IP $remote_addr;
# test proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
# proxy_set_header X-Forwarded-For $remote_addr;
# test proxy_set_header Proxy "";
rewrite ^/(.+)$ /$1 break;
}
@ -485,13 +489,12 @@ http {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_read_timeout 600s;
# proxy_cache mattermost_cache;
# proxy_cache_revalidate on;
# proxy_cache_min_uses 2;
# proxy_cache_use_stale timeout;
# proxy_cache_lock on;
# proxy_cache mattermost_cache; # test
# proxy_cache_lock on; # test
# proxy_cache_min_uses 2; # test
# proxy_cache_revalidate on; # test
# proxy_cache_use_stale timeout; # test
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#rewrite ^/(.+)$ /$1 break;
}
}

4
dockers/proxy/proxy-gen.sh

@ -5,6 +5,8 @@ KAZ_ROOT=$(cd "$(dirname $0)/../.."; pwd)
setKazVars
. "${DOCKERS_ENV}"
printKazMsg "\n *** Proxy update config"
NGINX_TMPL=config/nginx.tmpl.conf
NGINX_CONF=config/nginx.conf
DOCKER_DIST=docker-compose.tmpl.yml.dist
@ -116,4 +118,4 @@ cd $(dirname $0)
"${APPLY_TMPL}" -time "${DOCKER_TMPL}" "${DOCKER_CONF}"
"${APPLY_TMPL}" -time "${NGINX_TMPL}" "${NGINX_CONF}"
"${KAZ_COMP_DIR}/web/web-gen.sh"
#("${KAZ_COMP_DIR}/web/web-gen.sh" ) &

2
dockers/sympa/build.sh

@ -11,6 +11,6 @@ printKazMsg "\n *** Création du Dockerfile Sympa"
cd "${KAZ_ROOT}"
mkdir -p dockers/postfix/filter/
rsync -a git/depollueur/src/bash/* git/depollueur/build/out/* dockers/sympa/filter/
#TODO copier les lib depuis le git ce qui permet de faire les commandes de link et copy dans le Dockerfile
docker build -t sympakaz . -f dockers/sympa/Dockerfile

107
dockers/sympa/filter/filter.sh

@ -52,7 +52,7 @@ FIC_LOG=/var/log/mail/filter.log
SENDMAIL="/usr/sbin/sendmail -G -i"
MAILS=/tmp/FILTER
MAX_KEEP_IN_MAIL=5ki
MAX_UPLOAD_SIZE=100Mi
MAX_UPLOAD_SIZE=1Gi
SHRINK_CMD=/home/filter/eMailShrinker
JIRAFEAU_CMD=/home/filter/jirafeauAPI
JIRAFEAU_URL=https://depot.${DOMAINNAME:-"kaz.bzh"}
@ -65,16 +65,34 @@ ARCHIVE_TITLE="archive_content"
ARCHIVE_MIME="text/kaz_email_archive"
#################### FONCTIONS ############################################
BOLD=''
RED=''
GREEN=''
YELLOW=''
BLUE=''
MAGENTA=''
CYAN=''
NC='' # No Color
NL='
'
#--------------------- Fichier de LOG -------------------
LOG_FIC() {
echo -e "$(date +%d-%m-%Y-%H-%M-%S) : $*" >> "${FIC_LOG}"
echo "${BLUE}$(date +%d-%m-%Y-%H-%M-%S)${NC} : $*" >> "${FIC_LOG}"
}
quitFilter () {
LOG_FIC "${GREEN}######################################## filter stop${NC}"
exit $1
}
#################### MAIN #################################################
LOG_FIC "------------------------------------------------------"
LOG_FIC "--------------- debut de programme -------------------"
echo "${NL}" >> "${FIC_LOG}"
LOG_FIC "${GREEN}######################################## filter start${NC}"
mkdir -p "${MAILS}" || { LOG_FIC "impossible de creer ce dossier"; exit "${EX_UNAVAILABLE}"; }
if ! mkdir -p "${MAILS}"; then
LOG_FIC "${RED}Can't mkdir ${MAILS} ${NC}"
quitFilter "${EX_UNAVAILABLE}"
fi
MAIL_SOURCE=$(echo $@ | awk 'BEGIN{FS=" "} {print $2}')
DATE_TEMPS=$(date "+%Y-%m-%d-%H:%M:%S")
REP_PIECE_JOINTE="${MAILS}/${DATE_TEMPS}_${MAIL_SOURCE}_$$"
@ -84,7 +102,17 @@ if [ -n "$(echo "${PERIOD}" | grep -e minute -e hour -e day -e week -e month -e
JIRAFEAU_TIME="${PERIOD}"
fi
cd "${INSPECT_DIR}" || { echo "${INSPECT_DIR} does not exist"; exit "${EX_TEMPFAIL}"; }
LOG_FIC "\n" \
" MAIL_SOURCE : ${YELLOW}${MAIL_SOURCE}${NC}\n" \
" DATE_TEMPS : ${YELLOW}${DATE_TEMPS=}${NC}\n" \
" TRACK : ${YELLOW}${TRACK}${NC}\n" \
" PERIOD : ${YELLOW}${PERIOD}${NC}\n" \
" JIRAFEAU_TIME: ${YELLOW}${JIRAFEAU_TIME}${NC}"
if ! cd "${INSPECT_DIR}"; then
echo "${INSPECT_DIR} does not exist"
quitFilter "${EX_TEMPFAIL}"
fi
# lien renvoyé par le téléverssement
ONE_LINK="${REP_PIECE_JOINTE}/one.txt"
@ -92,11 +120,18 @@ ONE_LINK="${REP_PIECE_JOINTE}/one.txt"
OLD_LINKS="${REP_PIECE_JOINTE}/url-to-refresh.txt"
# contenu de l'archive
ARCHIVE_CONTENT="${REP_PIECE_JOINTE}/archive-content.txt"
# create if error
JIRAFEAU_ERROR="${REP_PIECE_JOINTE}/jirafeau-error.txt"
# Clean up when done or when aborting.
trap "rm -rf in.$$ in.$$.altered ${REP_PIECE_JOINTE}" 0 1 2 3 15
cat > "in.$$" || { LOG_FIC "Cannot save mail to file"; exit "${EX_TEMPFAIL}"; }
if ! cat > "in.$$"; then
LOG_FIC "${RED}Cannot save mail to file${NC}"
quitFilter "${EX_TEMPFAIL}"
fi
LOG_FIC "\n" \
" size: ${YELLOW}$(wc -c < "${INSPECT_DIR}/in.$$")${NC}"
# XXX trace
# cp "${INSPECT_DIR}/in.$$" "${INSPECT_DIR}/in.$$.bak"
@ -108,7 +143,7 @@ mkdir -p "${REP_PIECE_JOINTE}/"
echo "time: ${DATE_TEMPS}\nid: $(date +%s)" > "${ARCHIVE_CONTENT}"
[ -n "${TRACK}" ] && echo "sender: ${MAIL_SOURCE}" >> "${ARCHIVE_CONTENT}"
LOG_FIC "${SHRINK_CMD} -u \"${INSPECT_DIR}/in.$$\" 2>> \"${FIC_LOG}\" > \"${OLD_LINKS}\""
LOG_FIC "${CYAN}${SHRINK_CMD} -u \"${INSPECT_DIR}/in.$$\" 2>> \"${FIC_LOG}\" > \"${OLD_LINKS}\"${NC}"
"${SHRINK_CMD}" -u "${INSPECT_DIR}/in.$$" 2>> "${FIC_LOG}" > "${OLD_LINKS}"
cat "${OLD_LINKS}" | grep "${JIRAFEAU_URL}" | while read REMOTE_LINK
@ -117,14 +152,14 @@ do
[ -z "${REMOTE_REF}" ] && continue
REMOTE_KEY=$(echo "${REMOTE_LINK}" | grep "k=" | sed 's%.*k=\([^&]*\).*%\1%')
# update periode for download
LOG_FIC " - \"${JIRAFEAU_CMD}\" -f \"${JIRAFEAU_LOCAL}\" -t \"${JIRAFEAU_TIME}\" update \"${REMOTE_REF}\" 2>&1 >> \"${FIC_LOG}\""
LOG_FIC " - ${CYAN}\"${JIRAFEAU_CMD}\" -f \"${JIRAFEAU_LOCAL}\" -t \"${JIRAFEAU_TIME}\" update \"${REMOTE_REF}\" 2>&1 >> \"${FIC_LOG}\"${NC}"
"${JIRAFEAU_CMD}" -f "${JIRAFEAU_LOCAL}" -t "${JIRAFEAU_TIME}" update "${REMOTE_REF}" 2>&1 >> "${FIC_LOG}"
echo "old: ${REMOTE_REF} ${REMOTE_KEY}" >> "${ARCHIVE_CONTENT}"
done
LOG_FIC " - archive starts with: $(cat ${ARCHIVE_CONTENT})"
LOG_FIC " - archive starts with: ${NL}${YELLOW}$(cat ${ARCHIVE_CONTENT})${NC}"
# Etape extraction des pieces jointes
LOG_FIC "${SHRINK_CMD} -s ${MAX_KEEP_IN_MAIL} -d ${REP_PIECE_JOINTE} ${INSPECT_DIR}/in.$$"
LOG_FIC "${CYAN}${SHRINK_CMD} -s ${MAX_KEEP_IN_MAIL} -d ${REP_PIECE_JOINTE} ${INSPECT_DIR}/in.$$ ${NC}"
"${SHRINK_CMD}" -s "${MAX_KEEP_IN_MAIL}" -d "${REP_PIECE_JOINTE}" "${INSPECT_DIR}/in.$$" 2>> "${FIC_LOG}" | {
while read ATTACH_TMP_NAME
do
@ -134,89 +169,99 @@ LOG_FIC "${SHRINK_CMD} -s ${MAX_KEEP_IN_MAIL} -d ${REP_PIECE_JOINTE} ${INSPECT_D
ATTACH_NAME=$(grep "^Name: " "${ATTACH_TMP_NAME}/meta" | cut -c 7- )
ATTACH_CONTENT_TYPE=$(grep "^Content-Type: " "${ATTACH_TMP_NAME}/meta" | cut -c 15- )
else
LOG_FIC " - ${RED}no ATTACH_TMP_NAME (${ATTACH_TMP_NAME}) ${NC}"
# XXX error
continue
fi
# Etape de televersement des pieces jointes
PASSWORD=$(apg -n 1 -m 12)
PASSWORD_MD5=$(echo -n ${PASSWORD} | ${MD5_CMD} | cut -d \ -f 1)
LOG_FIC " - \"${JIRAFEAU_CMD}\" -f \"${JIRAFEAU_LOCAL}\" -t \"${JIRAFEAU_TIME}\" -s \"${MAX_UPLOAD_SIZE}\" -c \"${ATTACH_CONTENT_TYPE}\" -n \"${ATTACH_NAME}\" send \"${ATTACH_MEDIA}\" \"${PASSWORD}\" 2>> \"${FIC_LOG}\" > \"${ONE_LINK}\""
LOG_FIC " - ${CYAN}\"${JIRAFEAU_CMD}\" -f \"${JIRAFEAU_LOCAL}\" -t \"${JIRAFEAU_TIME}\" -s \"${MAX_UPLOAD_SIZE}\" -c \"${ATTACH_CONTENT_TYPE}\" -n \"${ATTACH_NAME}\" send \"${ATTACH_MEDIA}\" \"${PASSWORD}\" 2>> \"${FIC_LOG}\" > \"${ONE_LINK}\"${NC}"
"${JIRAFEAU_CMD}" -f "${JIRAFEAU_LOCAL}" -t "${JIRAFEAU_TIME}" -s "${MAX_UPLOAD_SIZE}" -c "${ATTACH_CONTENT_TYPE}" -n "${ATTACH_NAME}" send "${ATTACH_MEDIA}" "${PASSWORD}" 2>> "${FIC_LOG}" > "${ONE_LINK}"
cat "${ONE_LINK}" | {
read JIR_TOKEN
read JIR_CODE
LOG_FIC " - Jirafeau retourne ${JIR_TOKEN} et ${JIR_CODE}"
LOG_FIC " - return code ${YELLOW}${JIR_TOKEN}${NC} / ${YELLOW}${JIR_CODE}${NC}"
case "${JIR_TOKEN}" in
"" | no | *Error* | \<* )
LOG_FIC " - impossible de televerser ${ATTACH_TMP_FILE} (${JIR_TOKEN}), il ne sera pas remplace dans le message"
"" | no | *Error* | \<* )
LOG_FIC " - ${RED}Can't upload <${ATTACH_NAME}> <${ATTACH_CONTENT_TYPE}> <$(wc -c < "${ATTACH_MEDIA}")> (${JIR_TOKEN}) <in.$$.bak>. It will be not change in e-mail.${NC}"
echo "new:"
cp "${INSPECT_DIR}/in.$$" "${INSPECT_DIR}/in.$$.bak"
echo "UPLOAD_FAIL" >> "${JIRAFEAU_ERROR}"
;;
* )
LOG_FIC " - substitution par ${JIRAFEAU_URL}/f.php?d=1&h=${JIR_TOKEN}&k=${PASSWORD_MD5}"
LOG_FIC " - change by link ${YELLOW}${JIRAFEAU_URL}/f.php?d=1&h=${JIR_TOKEN}&k=${PASSWORD_MD5}${NC}"
echo "url: ${JIRAFEAU_URL}/f.php?d=1&h=${JIR_TOKEN}&k=${PASSWORD_MD5}"
echo "new: ${JIR_TOKEN} ${PASSWORD_MD5}" >> "${ARCHIVE_CONTENT}"
;;
esac
}
LOG_FIC " - supprimer l'extraction ${ATTACH_TMP_FILE}"
rm -f "${ATTACH_TMP_FILE}"
done
# Création de l'archive
NB_ATTACH=$(grep -e "^old: " -e "^new: " "${ARCHIVE_CONTENT}" | wc -l)
if [ \( -n "${TRACK}" -a "${NB_ATTACH}" -gt 0 \) -o "${NB_ATTACH}" -gt 1 ]; then
PASSWORD=$(apg -n 1 -m 12)
PASSWORD_MD5=$(echo -n ${PASSWORD} | ${MD5_CMD} | cut -d \ -f 1)
LOG_FIC " - \"${JIRAFEAU_CMD}\" -f \"${JIRAFEAU_LOCAL}\" -t \"${JIRAFEAU_TIME}\" -s \"${MAX_UPLOAD_SIZE}\" -c \"${ARCHIVE_MIME}\" -n \"${ARCHIVE_TITLE}\" send \"${ARCHIVE_CONTENT}\" \"${PASSWORD}\" 2>> \"${FIC_LOG}\" > \"${ONE_LINK}\""
LOG_FIC " - ${MAGENTA}upload archive${NC}"
LOG_FIC " - ${CYAN}\"${JIRAFEAU_CMD}\" -f \"${JIRAFEAU_LOCAL}\" -t \"${JIRAFEAU_TIME}\" -s \"${MAX_UPLOAD_SIZE}\" -c \"${ARCHIVE_MIME}\" -n \"${ARCHIVE_TITLE}\" send \"${ARCHIVE_CONTENT}\" \"${PASSWORD}\" 2>> \"${FIC_LOG}\" > \"${ONE_LINK}\"${NC}"
"${JIRAFEAU_CMD}" -f "${JIRAFEAU_LOCAL}" -t "${JIRAFEAU_TIME}" -s "${MAX_UPLOAD_SIZE}" -c "${ARCHIVE_MIME}" -n "${ARCHIVE_TITLE}" send "${ARCHIVE_CONTENT}" "${PASSWORD}" 2>> "${FIC_LOG}" > "${ONE_LINK}"
fi
LOG_FIC " - final archive content: ${NL}${YELLOW}$(cat ${ARCHIVE_CONTENT})${NC}"
if [ "${NB_ATTACH}" -gt 1 ]; then
cat "${ONE_LINK}" | {
read JIR_TOKEN
read JIR_CODE
LOG_FIC " - Jirafeau retourne ${JIR_TOKEN} et ${JIR_CODE}"
LOG_FIC " - return code ${YELLOW}${JIR_TOKEN}${NC} / ${YELLOW}${JIR_CODE}${NC}"
case "${JIR_TOKEN}" in
"" | no | *Error* | \<* )
LOG_FIC " - impossible de televerser l'archive (${JIR_TOKEN}), il ne sera pas remplace dans le message"
LOG_FIC " - ${RED}can't upload archive (${JIR_TOKEN}) <in.$$.bak>, substitution couldn't be done${NC}"
echo "arch: bad"
cp "${INSPECT_DIR}/in.$$" "${INSPECT_DIR}/in.$$.bak"
echo "ARCHIVE_FAIL" >> "${JIRAFEAU_ERROR}"
;;
* )
LOG_FIC " - ajoute de l'archive ${JIRAFEAU_URL}/a.php?g=${JIR_TOKEN}~${PASSWORD_MD5}"
LOG_FIC " - add archive ${YELLOW}${JIRAFEAU_URL}/a.php?g=${JIR_TOKEN}~${PASSWORD_MD5}${NC}"
echo "arch: ${JIRAFEAU_URL}/a.php?g=${JIR_TOKEN}~${PASSWORD_MD5}"
;;
esac
}
else
LOG_FIC " - pas d'archive (moins de 2 PJ)"
LOG_FIC " - no archive (less than 2 attach file)"
echo "arch: none"
fi
# Etape de substitution
LOG_FIC "${SHRINK_CMD} -s \"${MAX_KEEP_IN_MAIL}\" \"${INSPECT_DIR}/in.$$\" \"${INSPECT_DIR}/in.$$.altered\" 2>> \"${FIC_LOG}\""
LOG_FIC "${CYAN}${SHRINK_CMD} -s \"${MAX_KEEP_IN_MAIL}\" \"${INSPECT_DIR}/in.$$\" \"${INSPECT_DIR}/in.$$.altered\" 2>> \"${FIC_LOG}\"${NC}"
} | "${SHRINK_CMD}" -s "${MAX_KEEP_IN_MAIL}" "${INSPECT_DIR}/in.$$" "${INSPECT_DIR}/in.$$.altered" 2>> "${FIC_LOG}"
# XXX trace
# cp "${INSPECT_DIR}/in.$$" "${INSPECT_DIR}/in.$$.altered" /var/mail/tmp/
if [ -s "${JIRAFEAU_ERROR}" ]; then
LOG_FIC " - ${RED}upload fail${NC}"
quitFilter "${EX_TEMPFAIL}"
fi
# Etape choix de modification du message d'origine
if [ "$(wc -l < "${ARCHIVE_CONTENT}")" -ge 3 ]; then
# verification de taille finale
actualSize=$(wc -c < "${INSPECT_DIR}/in.$$.altered")
if [ ${actualSize} -ge $MAX_FINAL_SIZE ]; then
LOG_FIC " - message trop gros apres regime ${INSPECT_DIR}/in.$$.altered (${actualSize})"
exit "${EX_TOO_LARGE}";
LOG_FIC " - ${RED}too big even after diet ${INSPECT_DIR}/in.$$.altered (${actualSize})${NC}"
quitFilter "${EX_TOO_LARGE}"
fi
LOG_FIC " - envoi de la commande : ${SENDMAIL} $@ ${INSPECT_DIR}/in.$$.altered"
LOG_FIC " - ${GREEN}send with : ${SENDMAIL} $@ ${INSPECT_DIR}/in.$$.altered ${NC}"
${SENDMAIL} "$@" < "${INSPECT_DIR}/in.$$.altered"
else
# verification de taille finale
actualSize=$(wc -c < "${INSPECT_DIR}/in.$$")
if [ ${actualSize} -ge $MAX_FINAL_SIZE ]; then
LOG_FIC " - message trop gros sans regime ${INSPECT_DIR}/in.$$ (${actualSize})"
exit "${EX_TOO_LARGE}";
LOG_FIC " - ${RED}too big without diet ${INSPECT_DIR}/in.$$ (${actualSize}) ${NC}"
quitFilter "${EX_TOO_LARGE}"
fi
LOG_FIC " - pas de piece jointe"
LOG_FIC " - ${GREEN}send without attach file${NC}"
${SENDMAIL} "$@" < "in.$$"
fi
exit 0
quitFilter 0
##########################################################################

9
dockers/sympa/reload.sh

@ -1,9 +1,4 @@
#!/bin/bash
docker exec -i sympaServ bash -c "/etc/init.d/postfix restart"
docker exec -i sympaServ bash -c "/etc/init.d/apache2 reload"
docker exec -i sympaServ bash -c "/etc/init.d/sympa stop"
sleep 5
docker exec -i sympaServ bash -c "/etc/init.d/sympa stop"
docker exec -i sympaServ bash -c "/etc/init.d/sympa start"
# copie les binaires pour le filtre
docker exec -ti sympaServ bash /home/filter/cp-lib.sh

2
dockers/web/html/assets/html/footer.html

@ -76,7 +76,7 @@ function updateAnchor(el) {
<section>
<h2>Nous contacter</h2>
Vous souhaitez obtenir un <b>compte gratuit</b> chez kaz?
Vous êtes du Morbihan (ou à coté) et vous souhaitez obtenir un <b>compte gratuit</b> chez kaz?
</br>
Rien de plus simple, envoyez un mail à
<a class="eml-protected" href="#">9cfff3f2e8fdffe8dcf7fde6b2fee6f4</a>

2
dockers/web/html/index.html

@ -45,7 +45,7 @@ Nous sommes un joyeux collectif de citoyens provenant d’horizons divers, doté
<p><strong>Pour changer le monde (rien que ça !), on commence par des services numériques cousus mains, respectueux de la vie privée, hébergés en Bretagne, pour tous les particuliers, associations et entreprises.</strong></p>
<p><strong>Comme association à but non lucratif, nous fonctionnons avec des bénévoles et des dons. C'est bien comme cela que nous pouvons vivre sans vendre vos données. Un soutiens de votre part sera toujours le bienvenu.</strong></p>
<p><strong>Comme association à but non lucratif, nous fonctionnons avec des bénévoles et des dons. C'est bien comme cela que nous pouvons vivre sans vendre vos données. Un soutien de votre part sera toujours le bienvenu.</strong></p>
<h2><center>Laissez-vous happer par un petit vent de liberté<img width="32" src="images/1f609.png" alt="smile" /></center></h2>

2
dockers/web/html/qui_sommes_nous.html

@ -26,7 +26,7 @@
<div class="inner">
<h1>Qui sommes nous</h1>
<span class="image main"><img src="images/qui_sommes_nous.png" alt="" /></span>
<p><b>Nous sommes un collectif de citoyens</b> provenant d’horizons divers, dotés de compétences diverses, qui partageons une vision commune des enjeux humains, écologiques, techniques, économiques, pédagogiques, artistiques, juridiques et politiques pour l'avenir de l'humanité et de notre planète Terre.<p>
<p><b>Nous sommes un collectif de citoyennes et citoyens</b> provenant d’horizons divers, dotés de compétences diverses, qui partageons une vision commune des enjeux humains, écologiques, techniques, économiques, pédagogiques, artistiques, juridiques et politiques pour l'avenir de l'humanité et de notre planète Terre.<p>
<p><b>Le Numérique a pris une place considérable dans le fonctionnement de nos sociétés,</b> que ce soit au niveau des individus, des organisations et des institutions.</p>
<p><b>La crise sanitaire a été un accélérateur</b>extraordinaire des transformations que le Numérique induit dans toutes les relations sociales, familiales, amicales, professionnelles, citoyennes,...</p>
<p><b>Le numérique est-il un progrès dans l'évolution de la société ?</b> Les critères "Quantité de données échangées" et "Rapidité de la circulation de ces données" sont-ils pertinents dans l'évaluation de la contribution du Numérique au seul progrès qui vaille, le progrès humain ?</p>

16
dockers/web/web-gen.sh

@ -4,6 +4,8 @@ KAZ_ROOT=$(cd "$(dirname $0)/../.."; pwd)
. "${KAZ_ROOT}/bin/.commonFunctions.sh"
setKazVars
printKazMsg "\n *** Web update config"
#TMPL=html/index.tmpl.html
#CONF=html/index.html
TEST_TMPL="${DOCK_VOL}/web_html/_data/status/allServices.tmpl.html"
@ -49,30 +51,34 @@ cat > "${TEST_TMPL}" <<EOF
EOF
for service in ${availableServices[@]} ; do
echo " <div><p><a href=\"__HTTP_PROTO__://${service}.__DOMAIN__\">${service}</a></p><iframe src=\"__HTTP_PROTO__://${service}.__DOMAIN__\"></iframe></div>" >> "${TEST_TMPL}"
done
echo " <div><p><a href=\"__HTTP_PROTO__://${service}.__DOMAIN__\">${service}</a></p><iframe src=\"__HTTP_PROTO__://${service}.__DOMAIN__\"></iframe></div>"
done >> "${TEST_TMPL}"
echo " <br/>" >> "${TEST_TMPL}"
declare -a availableOrga
availableOrga=$(getList "${KAZ_CONF_DIR}/container-orga.list")
echo "web-gen: orga"
for orga in ${availableOrga[@]} ; do
orgaName=${orga%-orga}
echo " <H1>${orgaName}</H1>"
for service in $("${KAZ_COMP_DIR}/${orga}/orga-gen.sh" -l | sed -e "s/collabora/office/" ); do
echo " <div><p><a href=\"__HTTP_PROTO__://${orgaName}-${service}.__DOMAIN__\">${orgaName}-${service}</a></p><iframe src=\"__HTTP_PROTO__://${orgaName}-${service}.__DOMAIN__\"></iframe></div>"
echo " <div><p><a href=\"__HTTP_PROTO__://${orgaName}-${service}.__DOMAIN__\">${orgaName}-${service}</a></p></div>"
done
echo " <br/>"
done >> "${TEST_TMPL}"
echo "web-gen: extrenal"
for extrenal in $("${KAZ_BIN_DIR}/foreign-domain.sh" -l) ; do
echo " <H1>${extrenal}</H1>"
echo " <div><p><a href=\"__HTTP_PROTO__://${extrenal}\">${extrenal}</a></p><iframe src=\"__HTTP_PROTO__://${extrenal}\"></iframe></div>"
echo " <div><p><a href=\"__HTTP_PROTO__://${extrenal}\">${extrenal}</a></p></div>"
echo " <br/>"
done >> "${TEST_TMPL}"
echo " </html>" >> "${TEST_TMPL}"
echo "web-gen: end"
########################################
#"${APPLY_TMPL}" "${TMPL}" "${CONF}"
"${APPLY_TMPL}" "${TEST_TMPL}" "${TEST_CONF}"

Loading…
Cancel
Save