mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-11-04 12:18:17 +00:00 
			
		
		
		
	General Optimations
This commit is contained in:
		@@ -6,8 +6,9 @@ import os
 | 
				
			|||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def run_ansible_playbook(inventory, playbook, modes, limit=None, password_file=None, verbose=0, skip_tests=False):
 | 
					def run_ansible_playbook(inventory, playbook, modes, limit=None, password_file=None, verbose=0, skip_tests=False):
 | 
				
			||||||
    start_time = datetime.datetime.now().isoformat()
 | 
					    start_time = datetime.datetime.now()
 | 
				
			||||||
    print(f"\n▶️ Script started at: {start_time}\n")
 | 
					    print(f"\n▶️ Script started at: {start_time.isoformat()}\n")
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    print("\n🛠️  Building project (make build)...\n")
 | 
					    print("\n🛠️  Building project (make build)...\n")
 | 
				
			||||||
    subprocess.run(["make", "build"], check=True)
 | 
					    subprocess.run(["make", "build"], check=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,8 +36,11 @@ def run_ansible_playbook(inventory, playbook, modes, limit=None, password_file=N
 | 
				
			|||||||
    print("\n🚀 Launching Ansible Playbook...\n")
 | 
					    print("\n🚀 Launching Ansible Playbook...\n")
 | 
				
			||||||
    subprocess.run(cmd, check=True)
 | 
					    subprocess.run(cmd, check=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    end_time = datetime.datetime.now().isoformat()
 | 
					    end_time = datetime.datetime.now()
 | 
				
			||||||
    print(f"\n✅ Script ended at: {end_time}\n")
 | 
					    print(f"\n✅ Script ended at: {end_time.isoformat()}\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    duration = end_time - start_time
 | 
				
			||||||
 | 
					    print(f"⏱️ Total execution time: {duration}\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main():
 | 
					def main():
 | 
				
			||||||
    script_dir = os.path.dirname(os.path.realpath(__file__))
 | 
					    script_dir = os.path.dirname(os.path.realpath(__file__))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,25 @@ _users_no_reply_email:          "{{ users['no-reply'].email | default(_users_no_
 | 
				
			|||||||
_users_blackhole_username:       "{{ users.blackhole.username | default('no-reply') }}"
 | 
					_users_blackhole_username:       "{{ users.blackhole.username | default('no-reply') }}"
 | 
				
			||||||
_users_blackhole_email:          "{{ users.blackhole.email | default(_users_blackhole_username ~ '@' ~ primary_domain) }}"
 | 
					_users_blackhole_email:          "{{ users.blackhole.email | default(_users_blackhole_username ~ '@' ~ primary_domain) }}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper Variables for contact user
 | 
				
			||||||
 | 
					_users_contact_username:       "{{ users.contact.username | default('contact') }}"
 | 
				
			||||||
 | 
					_users_contact_email:          "{{ users.contact.email | default(_users_contact_username ~ '@' ~ primary_domain) }}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper Variables for support
 | 
				
			||||||
 | 
					_users_support_username:       "{{ users.support.username | default('support') }}"
 | 
				
			||||||
 | 
					_users_support_email:          "{{ users.support.email | default(_users_support_username ~ '@' ~ primary_domain) }}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper Variables for helpdesk
 | 
				
			||||||
 | 
					_users_helpdesk_username:      "{{ users.helpdesk.username | default('helpdesk') }}"
 | 
				
			||||||
 | 
					_users_helpdesk_email:         "{{ users.helpdesk.email | default(_users_helpdesk_username ~ '@' ~ primary_domain) }}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Extract SLD and TLD from primary_domain
 | 
				
			||||||
 | 
					_users_sld_username:           "{{ primary_domain.split('.')[0] }}"
 | 
				
			||||||
 | 
					_users_sld_email:              "{{ _users_sld_username ~ '@' ~ primary_domain }}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_users_tld_username:           "{{ primary_domain.split('.')[-1] }}"
 | 
				
			||||||
 | 
					_users_tld_email:              "{{ _users_tld_username ~ '@' ~ primary_domain }}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Administrator
 | 
					# Administrator
 | 
				
			||||||
default_users:
 | 
					default_users:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,3 +70,41 @@ default_users:
 | 
				
			|||||||
    password:           "{{ansible_become_password}}"           # Example initialisation password needs to be set in inventory file
 | 
					    password:           "{{ansible_become_password}}"           # Example initialisation password needs to be set in inventory file
 | 
				
			||||||
    uid:                1004                                    # Posix User ID for bounce
 | 
					    uid:                1004                                    # Posix User ID for bounce
 | 
				
			||||||
    gid:                1004                                    # Posix Group ID for bounce
 | 
					    gid:                1004                                    # Posix Group ID for bounce
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # The contact user account which clients and plattform users can contact
 | 
				
			||||||
 | 
					  contact:
 | 
				
			||||||
 | 
					    username:           "{{ _users_contact_username }}"         # Contact account username
 | 
				
			||||||
 | 
					    email:              "{{ _users_contact_email }}"            # Email address to which initial contacct emails can be send
 | 
				
			||||||
 | 
					    password:           "{{ansible_become_password}}"           # Example initialisation password needs to be set in inventory file
 | 
				
			||||||
 | 
					    uid:                1005                                    # Posix User ID for bounce
 | 
				
			||||||
 | 
					    gid:                1005                                    # Posix Group ID for bounce
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Support and Helpdesk accounts
 | 
				
			||||||
 | 
					  support:
 | 
				
			||||||
 | 
					    username:           "{{ _users_support_username }}"         # Support account username
 | 
				
			||||||
 | 
					    email:              "{{ _users_support_email }}"            # Email for customer and platform support communication
 | 
				
			||||||
 | 
					    password:           "{{ ansible_become_password }}"         # Example initialisation password needs to be set in inventory file
 | 
				
			||||||
 | 
					    uid:                1006                                    # Posix User ID for support
 | 
				
			||||||
 | 
					    gid:                1006                                    # Posix Group ID for support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  helpdesk:
 | 
				
			||||||
 | 
					    username:           "{{ _users_helpdesk_username }}"        # Helpdesk account username
 | 
				
			||||||
 | 
					    email:              "{{ _users_helpdesk_email }}"           # Email for internal technical helpdesk communication
 | 
				
			||||||
 | 
					    password:           "{{ ansible_become_password }}"         # Example initialisation password needs to be set in inventory file
 | 
				
			||||||
 | 
					    uid:                1007                                    # Posix User ID for helpdesk
 | 
				
			||||||
 | 
					    gid:                1007                                    # Posix Group ID for helpdesk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sld_user:
 | 
				
			||||||
 | 
					    username:           "{{ _users_sld_username }}"             # Username based on SLD of the primary domain
 | 
				
			||||||
 | 
					    email:              "{{ _users_sld_email }}"                # Email address with SLD username
 | 
				
			||||||
 | 
					    password:           "{{ ansible_become_password }}"         # Init password from inventory
 | 
				
			||||||
 | 
					    uid:                1008
 | 
				
			||||||
 | 
					    gid:                1008
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tld_user:
 | 
				
			||||||
 | 
					    username:           "{{ _users_tld_username }}"             # Username based on TLD of the primary domain
 | 
				
			||||||
 | 
					    email:              "{{ _users_tld_email }}"                # Email address with TLD username
 | 
				
			||||||
 | 
					    password:           "{{ ansible_become_password }}"         # Init password from inventory
 | 
				
			||||||
 | 
					    uid:                1009
 | 
				
			||||||
 | 
					    gid:                1009
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,15 +17,15 @@ defaults_service_provider:
 | 
				
			|||||||
    favicon:        "{{ applications['assets-server'].url ~ '/img/favicon.ico' }}"
 | 
					    favicon:        "{{ applications['assets-server'].url ~ '/img/favicon.ico' }}"
 | 
				
			||||||
  contact:
 | 
					  contact:
 | 
				
			||||||
    bluesky: >-
 | 
					    bluesky: >-
 | 
				
			||||||
      {{ ('@' ~ users.administrator.username ~ '.' ~ domains.bluesky.api)
 | 
					      {{ ('@' ~ users.contact.username ~ '.' ~ domains.bluesky.api)
 | 
				
			||||||
         if 'bluesky' in group_names else '' }}
 | 
					         if 'bluesky' in group_names else '' }}
 | 
				
			||||||
    email:          "contact@{{ primary_domain }}"
 | 
					    email:          "{{ users.contact.username ~ '@' ~ domains | get_domain('mailu') if 'mailu' in group_names else '' }}"
 | 
				
			||||||
    mastodon:       "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('mastodon') if 'mastodon' in group_names else '' }}"
 | 
					    mastodon:       "{{ '@' ~ users.contact.username ~ '@' ~ domains | get_domain('mastodon') if 'mastodon' in group_names else '' }}"
 | 
				
			||||||
    matrix:         "{{ '@' ~ users.administrator.username ~ ':' ~ domains.matrix.synapse if 'matrix' in group_names else '' }}"
 | 
					    matrix:         "{{ '@' ~ users.contact.username ~ ':' ~ domains.matrix.synapse if 'matrix' in group_names else '' }}"
 | 
				
			||||||
    peertube:       "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('peertube') if 'peertube' in group_names else '' }}"
 | 
					    peertube:       "{{ '@' ~ users.contact.username ~ '@' ~ domains | get_domain('peertube') if 'peertube' in group_names else '' }}"
 | 
				
			||||||
    pixelfed:       "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('pixelfed') if 'pixelfed' in group_names else '' }}"
 | 
					    pixelfed:       "{{ '@' ~ users.contact.username ~ '@' ~ domains | get_domain('pixelfed') if 'pixelfed' in group_names else '' }}"
 | 
				
			||||||
    phone:          "+0 000 000 404"
 | 
					    phone:          "+0 000 000 404"
 | 
				
			||||||
    wordpress:      "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('wordpress') if 'wordpress' in group_names else '' }}"
 | 
					    wordpress:      "{{ '@' ~ users.contact.username ~ '@' ~ domains | get_domain('wordpress') if 'wordpress' in group_names else '' }}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  legal:
 | 
					  legal:
 | 
				
			||||||
    editorial_responsible:  "Johannes Gutenberg"
 | 
					    editorial_responsible:  "Johannes Gutenberg"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,4 +19,5 @@ galaxy_info:
 | 
				
			|||||||
  documentation: "https://s.veen.world/cymais"
 | 
					  documentation: "https://s.veen.world/cymais"
 | 
				
			||||||
  logo:
 | 
					  logo:
 | 
				
			||||||
    class: "fa-solid fa-phone"
 | 
					    class: "fa-solid fa-phone"
 | 
				
			||||||
dependencies: []
 | 
					  run_after:  
 | 
				
			||||||
 | 
					    - docker-keycloak
 | 
				
			||||||
@@ -31,7 +31,7 @@ services:
 | 
				
			|||||||
      driver: journald
 | 
					      driver: journald
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      - ESPOCRM_CONFIG_USE_WEB_SOCKET=true
 | 
					      - ESPOCRM_CONFIG_USE_WEB_SOCKET=true
 | 
				
			||||||
      - ESPOCRM_CONFIG_WEB_SOCKET_URL=ws://{{ domains | get_domain(application_id) }}/ws
 | 
					      - ESPOCRM_CONFIG_WEB_SOCKET_URL=wss://{{ domains | get_domain(application_id) }}/ws
 | 
				
			||||||
      - ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN=tcp://*:7777
 | 
					      - ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN=tcp://*:7777
 | 
				
			||||||
      - ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN=tcp://websocket:7777
 | 
					      - ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN=tcp://websocket:7777
 | 
				
			||||||
    entrypoint: docker-websocket.sh
 | 
					    entrypoint: docker-websocket.sh
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ csp:
 | 
				
			|||||||
      unsafe-inline:  true
 | 
					      unsafe-inline:  true
 | 
				
			||||||
  whitelist:
 | 
					  whitelist:
 | 
				
			||||||
    connect-src:
 | 
					    connect-src:
 | 
				
			||||||
      - ws://espocrm.{{ primary_domain }}
 | 
					      - wss://espocrm.{{ primary_domain }}
 | 
				
			||||||
domains:
 | 
					domains:
 | 
				
			||||||
  aliases:
 | 
					  aliases:
 | 
				
			||||||
    - "crm.{{ primary_domain }}"
 | 
					    - "crm.{{ primary_domain }}"
 | 
				
			||||||
@@ -19,4 +19,5 @@ galaxy_info:
 | 
				
			|||||||
  documentation: "https://s.veen.world/cymais"
 | 
					  documentation: "https://s.veen.world/cymais"
 | 
				
			||||||
  logo:
 | 
					  logo:
 | 
				
			||||||
    class: "fa-solid fa-envelope"
 | 
					    class: "fa-solid fa-envelope"
 | 
				
			||||||
dependencies: []
 | 
					  run_after:  
 | 
				
			||||||
 | 
					    - docker-keycloak
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
- name: "Ensure Mailu user {{ mailu_user }}@{{ mailu_domain }} exists"
 | 
					- name: "Ensure Mailu user '{{ mailu_user_key }};{{ mailu_user_name }}@{{ mailu_domain }}'' exists"
 | 
				
			||||||
  command: >
 | 
					  command: >
 | 
				
			||||||
    docker compose exec admin flask mailu {{ mailu_action }}
 | 
					    docker compose exec admin flask mailu {{ mailu_action }}
 | 
				
			||||||
      {{ mailu_user }} {{ mailu_domain }} '{{ mailu_password }}'
 | 
					      {{ mailu_user_name }} {{ mailu_domain }} '{{ mailu_password }}'
 | 
				
			||||||
  args:
 | 
					  args:
 | 
				
			||||||
    chdir: "{{ mailu_compose_dir }}"
 | 
					    chdir: "{{ mailu_compose_dir }}"
 | 
				
			||||||
  register: mailu_user_result
 | 
					  register: mailu_user_result
 | 
				
			||||||
@@ -13,10 +13,10 @@
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
  changed_when: mailu_user_result.rc == 0
 | 
					  changed_when: mailu_user_result.rc == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- name: "Change password for user {{ mailu_user }}@{{ mailu_domain }}"
 | 
					- name: "Change password for user '{{ mailu_user_key }};{{ mailu_user_name }}@{{ mailu_domain }}'"
 | 
				
			||||||
  command: >
 | 
					  command: >
 | 
				
			||||||
    docker compose exec admin flask mailu password
 | 
					    docker compose exec admin flask mailu password
 | 
				
			||||||
      {{ mailu_user }} {{ mailu_domain }} '{{ mailu_password }}'
 | 
					      {{ mailu_user_name }} {{ mailu_domain }} '{{ mailu_password }}'
 | 
				
			||||||
  args:
 | 
					  args:
 | 
				
			||||||
    chdir: "{{ mailu_compose_dir }}"
 | 
					    chdir: "{{ mailu_compose_dir }}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,18 +30,18 @@
 | 
				
			|||||||
  register: mailu_tokens_cli
 | 
					  register: mailu_tokens_cli
 | 
				
			||||||
  changed_when: false
 | 
					  changed_when: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- name: "Extract existing token info for {{ mailu_user }}"
 | 
					- name: "Extract existing token info for '{{ mailu_user_key }};{{ mailu_user_name }}'"
 | 
				
			||||||
  set_fact:
 | 
					  set_fact:
 | 
				
			||||||
    mailu_user_existing_token: >-
 | 
					    mailu_user_existing_token: >-
 | 
				
			||||||
      {{ (
 | 
					      {{ (
 | 
				
			||||||
           mailu_tokens_cli.stdout
 | 
					           mailu_tokens_cli.stdout
 | 
				
			||||||
           | default('[]')
 | 
					           | default('[]')
 | 
				
			||||||
           | from_json
 | 
					           | from_json
 | 
				
			||||||
           | selectattr('comment','equalto', mailu_user ~ " - ansible.cymais")
 | 
					           | selectattr('comment','equalto', mailu_user_key ~ " - ansible.cymais")
 | 
				
			||||||
           | list
 | 
					           | list
 | 
				
			||||||
         ).0 | default(None) }}
 | 
					         ).0 | default(None) }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- name: "Delete existing API token for {{ mailu_user }} if local token missing but remote exists"
 | 
					- name: "Delete existing API token for '{{ mailu_user_key }};{{ mailu_user_name }}' if local token missing but remote exists"
 | 
				
			||||||
  command: >-
 | 
					  command: >-
 | 
				
			||||||
    docker compose exec -T admin \
 | 
					    docker compose exec -T admin \
 | 
				
			||||||
      curl -s -X DELETE {{ mailu_api_base_url }}/token/{{ mailu_user_existing_token.id }} \
 | 
					      curl -s -X DELETE {{ mailu_api_base_url }}/token/{{ mailu_user_existing_token.id }} \
 | 
				
			||||||
@@ -49,40 +49,40 @@
 | 
				
			|||||||
  args:
 | 
					  args:
 | 
				
			||||||
    chdir: "{{ mailu_compose_dir }}"
 | 
					    chdir: "{{ mailu_compose_dir }}"
 | 
				
			||||||
  when:
 | 
					  when:
 | 
				
			||||||
    - users[mailu_user].mailu_token is not defined
 | 
					    - users[mailu_user_key].mailu_token is not defined
 | 
				
			||||||
    - mailu_user_existing_token is not none
 | 
					    - mailu_user_existing_token is not none
 | 
				
			||||||
    - mailu_user_existing_token.id is defined
 | 
					    - mailu_user_existing_token.id is defined
 | 
				
			||||||
  register: mailu_token_delete
 | 
					  register: mailu_token_delete
 | 
				
			||||||
  changed_when: mailu_token_delete.rc == 0
 | 
					  changed_when: mailu_token_delete.rc == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- name: "Create API token for {{ mailu_user }} if no local token defined"
 | 
					- name: "Create API token for '{{ mailu_user_key }};{{ mailu_user_name }}' if no local token defined"
 | 
				
			||||||
  command: >-
 | 
					  command: >-
 | 
				
			||||||
    docker compose exec -T admin \
 | 
					    docker compose exec -T admin \
 | 
				
			||||||
      curl -s -X POST {{ mailu_api_base_url }}/token \
 | 
					      curl -s -X POST {{ mailu_api_base_url }}/token \
 | 
				
			||||||
        -H "Authorization: Bearer {{ mailu_global_api_token }}" \
 | 
					        -H "Authorization: Bearer {{ mailu_global_api_token }}" \
 | 
				
			||||||
        -H "Content-Type: application/json" \
 | 
					        -H "Content-Type: application/json" \
 | 
				
			||||||
        -d '{{ {
 | 
					        -d '{{ {
 | 
				
			||||||
              "comment": mailu_user ~ " - ansible.cymais",
 | 
					              "comment": mailu_user_key ~ " - ansible.cymais",
 | 
				
			||||||
              "email": users[mailu_user].email,
 | 
					              "email": users[mailu_user_key].email,
 | 
				
			||||||
              "ip": mailu_token_ip
 | 
					              "ip": mailu_token_ip
 | 
				
			||||||
            } | to_json }}'
 | 
					            } | to_json }}'
 | 
				
			||||||
  args:
 | 
					  args:
 | 
				
			||||||
    chdir: "{{ mailu_compose_dir }}"
 | 
					    chdir: "{{ mailu_compose_dir }}"
 | 
				
			||||||
  when: users[mailu_user].mailu_token is not defined
 | 
					  when: users[mailu_user_key].mailu_token is not defined
 | 
				
			||||||
  register: mailu_token_creation
 | 
					  register: mailu_token_creation
 | 
				
			||||||
  changed_when: mailu_token_creation.rc == 0
 | 
					  changed_when: mailu_token_creation.rc == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- name: "Set mailu_token for {{ mailu_user }} in users dict if newly created"
 | 
					- name: "Set mailu_token for '{{ mailu_user_key }};{{ mailu_user_name }}' in users dict if newly created"
 | 
				
			||||||
  set_fact:
 | 
					  set_fact:
 | 
				
			||||||
    users: >-
 | 
					    users: >-
 | 
				
			||||||
      {{ users
 | 
					      {{ users
 | 
				
			||||||
         | combine({
 | 
					         | combine({
 | 
				
			||||||
             mailu_user: (
 | 
					             mailu_user_key: (
 | 
				
			||||||
               users[mailu_user]
 | 
					               users[mailu_user_key]
 | 
				
			||||||
               | combine({
 | 
					               | combine({
 | 
				
			||||||
                   'mailu_token': (mailu_token_creation.stdout | from_json).token
 | 
					                   'mailu_token': (mailu_token_creation.stdout | from_json).token
 | 
				
			||||||
                 })
 | 
					                 })
 | 
				
			||||||
             )
 | 
					             )
 | 
				
			||||||
           }, recursive=True)
 | 
					           }, recursive=True)
 | 
				
			||||||
      }}
 | 
					      }}
 | 
				
			||||||
  when: users[mailu_user].mailu_token is not defined
 | 
					  when: users[mailu_user_key].mailu_token is not defined
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,8 @@
 | 
				
			|||||||
    mailu_api_base_url:       "http://127.0.0.1:8080/api/v1"
 | 
					    mailu_api_base_url:       "http://127.0.0.1:8080/api/v1"
 | 
				
			||||||
    mailu_global_api_token:   "{{ applications.mailu.credentials.api_token }}"
 | 
					    mailu_global_api_token:   "{{ applications.mailu.credentials.api_token }}"
 | 
				
			||||||
    mailu_action:             "{{ item.value.is_admin | default(false) | ternary('admin','user') }}"
 | 
					    mailu_action:             "{{ item.value.is_admin | default(false) | ternary('admin','user') }}"
 | 
				
			||||||
    mailu_user:               "{{ item.key }}"
 | 
					    mailu_user_key:           "{{ item.key }}"
 | 
				
			||||||
 | 
					    mailu_user_name:          "{{ item.value.username }}"
 | 
				
			||||||
    mailu_password:           "{{ item.value.password }}"
 | 
					    mailu_password:           "{{ item.value.password }}"
 | 
				
			||||||
    mailu_token_ip:           "{{ item.value.ip | default('') }}"
 | 
					    mailu_token_ip:           "{{ item.value.ip | default('') }}"
 | 
				
			||||||
  loop:                       "{{ users | dict2items }}"
 | 
					  loop:                       "{{ users | dict2items }}"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,3 +16,8 @@ features:
 | 
				
			|||||||
domains:
 | 
					domains:
 | 
				
			||||||
  canonical:
 | 
					  canonical:
 | 
				
			||||||
    - "mail.{{ primary_domain }}"
 | 
					    - "mail.{{ primary_domain }}"
 | 
				
			||||||
 | 
					flags:
 | 
				
			||||||
 | 
					  style-src:
 | 
				
			||||||
 | 
					    unsafe-inline:        true
 | 
				
			||||||
 | 
					  script-src:
 | 
				
			||||||
 | 
					    unsafe-inline:        true
 | 
				
			||||||
@@ -10,9 +10,7 @@ accounts:
 | 
				
			|||||||
    description: Platforms where I share content.
 | 
					    description: Platforms where I share content.
 | 
				
			||||||
    icon:
 | 
					    icon:
 | 
				
			||||||
      class: fas fa-newspaper
 | 
					      class: fas fa-newspaper
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% if ["mastodon", "bluesky"] | any_in(group_names) %}
 | 
					{% if ["mastodon", "bluesky"] | any_in(group_names) %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
    children:
 | 
					    children:
 | 
				
			||||||
    - name: Microblogs
 | 
					    - name: Microblogs
 | 
				
			||||||
      description: Stay updated with {{ 'our' if service_provider.type == 'legal' else 'my' }} microblogs.
 | 
					      description: Stay updated with {{ 'our' if service_provider.type == 'legal' else 'my' }} microblogs.
 | 
				
			||||||
@@ -20,8 +18,6 @@ accounts:
 | 
				
			|||||||
        class: fa-solid fa-pen-nib
 | 
					        class: fa-solid fa-pen-nib
 | 
				
			||||||
      children:
 | 
					      children:
 | 
				
			||||||
{% if service_provider.contact.mastodon is defined and service_provider.contact.mastodon != "" %}
 | 
					{% if service_provider.contact.mastodon is defined and service_provider.contact.mastodon != "" %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      - name: Mastodon
 | 
					      - name: Mastodon
 | 
				
			||||||
        description: Follow {{ 'our' if service_provider.type == 'legal' else 'my' }} updates on Mastodon.
 | 
					        description: Follow {{ 'our' if service_provider.type == 'legal' else 'my' }} updates on Mastodon.
 | 
				
			||||||
        icon:
 | 
					        icon:
 | 
				
			||||||
@@ -29,11 +25,8 @@ accounts:
 | 
				
			|||||||
        url: "{{ web_protocol }}://{{ service_provider.contact.mastodon.split('@')[2] }}/@{{ service_provider.contact.mastodon.split('@')[1] }}"
 | 
					        url: "{{ web_protocol }}://{{ service_provider.contact.mastodon.split('@')[2] }}/@{{ service_provider.contact.mastodon.split('@')[1] }}"
 | 
				
			||||||
        identifier: "{{service_provider.contact.mastodon}}"
 | 
					        identifier: "{{service_provider.contact.mastodon}}"
 | 
				
			||||||
        iframe: {{ applications | is_feature_enabled('portfolio_iframe','mastodon') }}
 | 
					        iframe: {{ applications | is_feature_enabled('portfolio_iframe','mastodon') }}
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% if service_provider.contact.bluesky is defined and service_provider.contact.bluesky != "" %}
 | 
					{% if service_provider.contact.bluesky is defined and service_provider.contact.bluesky != "" %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      - name: Bluesky
 | 
					      - name: Bluesky
 | 
				
			||||||
        description: Follow {{ 'our' if service_provider.type == 'legal' else 'my' }} on Bluesky.
 | 
					        description: Follow {{ 'our' if service_provider.type == 'legal' else 'my' }} on Bluesky.
 | 
				
			||||||
        icon:
 | 
					        icon:
 | 
				
			||||||
@@ -41,11 +34,9 @@ accounts:
 | 
				
			|||||||
        alternatives:
 | 
					        alternatives:
 | 
				
			||||||
        - link: accounts.publishingchannels.microblogs.mastodon
 | 
					        - link: accounts.publishingchannels.microblogs.mastodon
 | 
				
			||||||
        identifier: "{{service_provider.contact.bluesky}}"
 | 
					        identifier: "{{service_provider.contact.bluesky}}"
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% if service_provider.contact.pixelfed  is defined and service_provider.contact.pixelfed  != "" %}
 | 
					{% if service_provider.contact.pixelfed  is defined and service_provider.contact.pixelfed  != "" %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: Pictures
 | 
					    - name: Pictures
 | 
				
			||||||
      description: Explore {{ 'our' if service_provider.type == 'legal' else 'my' }} photo gallery on Pixelfed.
 | 
					      description: Explore {{ 'our' if service_provider.type == 'legal' else 'my' }} photo gallery on Pixelfed.
 | 
				
			||||||
      icon:
 | 
					      icon:
 | 
				
			||||||
@@ -53,11 +44,8 @@ accounts:
 | 
				
			|||||||
      identifier: "{{service_provider.contact.pixelfed}}"
 | 
					      identifier: "{{service_provider.contact.pixelfed}}"
 | 
				
			||||||
      url: "{{ web_protocol }}://{{ service_provider.contact.pixelfed.split('@')[2] }}/@{{ service_provider.contact.pixelfed.split('@')[1] }}"
 | 
					      url: "{{ web_protocol }}://{{ service_provider.contact.pixelfed.split('@')[2] }}/@{{ service_provider.contact.pixelfed.split('@')[1] }}"
 | 
				
			||||||
      iframe: {{ applications | is_feature_enabled('portfolio_iframe','pixelfed') }}
 | 
					      iframe: {{ applications | is_feature_enabled('portfolio_iframe','pixelfed') }}
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% if service_provider.contact.peertube  is defined and service_provider.contact.peertube  != "" %}
 | 
					{% if service_provider.contact.peertube  is defined and service_provider.contact.peertube  != "" %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: Peertube
 | 
					    - name: Peertube
 | 
				
			||||||
      description: Discover {{ 'our' if service_provider.type == 'legal' else 'my' }} videos on Peertube.
 | 
					      description: Discover {{ 'our' if service_provider.type == 'legal' else 'my' }} videos on Peertube.
 | 
				
			||||||
      icon:
 | 
					      icon:
 | 
				
			||||||
@@ -65,11 +53,8 @@ accounts:
 | 
				
			|||||||
      identifier: "{{service_provider.contact.peertube}}"
 | 
					      identifier: "{{service_provider.contact.peertube}}"
 | 
				
			||||||
      url: "{{ web_protocol }}://{{ service_provider.contact.peertube.split('@')[2] }}/@{{ service_provider.contact.peertube.split('@')[1] }}"
 | 
					      url: "{{ web_protocol }}://{{ service_provider.contact.peertube.split('@')[2] }}/@{{ service_provider.contact.peertube.split('@')[1] }}"
 | 
				
			||||||
      iframe: {{ applications | is_feature_enabled('portfolio_iframe','peertube') }}
 | 
					      iframe: {{ applications | is_feature_enabled('portfolio_iframe','peertube') }}
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% if service_provider.contact.wordpress is defined and service_provider.contact.wordpress != "" %}
 | 
					{% if service_provider.contact.wordpress is defined and service_provider.contact.wordpress != "" %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: Blog
 | 
					    - name: Blog
 | 
				
			||||||
      description: Read {{ 'our' if service_provider.type == 'legal' else 'my' }} articles and stories.
 | 
					      description: Read {{ 'our' if service_provider.type == 'legal' else 'my' }} articles and stories.
 | 
				
			||||||
      icon:
 | 
					      icon:
 | 
				
			||||||
@@ -77,21 +62,15 @@ accounts:
 | 
				
			|||||||
      identifier: "{{service_provider.contact.wordpress}}"
 | 
					      identifier: "{{service_provider.contact.wordpress}}"
 | 
				
			||||||
      url: "{{ web_protocol }}://{{ service_provider.contact.wordpress.split('@')[2] }}/@{{ service_provider.contact.wordpress.split('@')[1] }}"
 | 
					      url: "{{ web_protocol }}://{{ service_provider.contact.wordpress.split('@')[2] }}/@{{ service_provider.contact.wordpress.split('@')[1] }}"
 | 
				
			||||||
      iframe: {{ applications | is_feature_enabled('portfolio_iframe','wordpress') }}
 | 
					      iframe: {{ applications | is_feature_enabled('portfolio_iframe','wordpress') }}
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% if service_provider.contact.source_code is defined and service_provider.contact.source_code != "" %}
 | 
					{% if service_provider.legal.source_code is defined and service_provider.legal.source_code != "" %}
 | 
				
			||||||
 | 
					    - name: Source Code
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    - name: Our Code
 | 
					 | 
				
			||||||
      description: Explore {{ 'our' if service_provider.type == 'legal' else 'my' }} code.
 | 
					      description: Explore {{ 'our' if service_provider.type == 'legal' else 'my' }} code.
 | 
				
			||||||
      icon:
 | 
					      icon:
 | 
				
			||||||
        class: fa-solid fa-code
 | 
					        class: fa-solid fa-code
 | 
				
			||||||
      url: "{{service_provider.legal.source_code}}"
 | 
					      url: "{{service_provider.legal.source_code}}"
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
{% if service_provider.contact.friendica is defined and service_provider.contact.friendica != "" %}
 | 
					{% if service_provider.contact.friendica is defined and service_provider.contact.friendica != "" %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  - name: Social Network
 | 
					  - name: Social Network
 | 
				
			||||||
    description: Visit {{ 'our' if service_provider.type == 'legal' else 'my' }} friendica profile
 | 
					    description: Visit {{ 'our' if service_provider.type == 'legal' else 'my' }} friendica profile
 | 
				
			||||||
    icon:
 | 
					    icon:
 | 
				
			||||||
@@ -99,9 +78,7 @@ accounts:
 | 
				
			|||||||
    identifier: "{{service_provider.contact.friendica}}"
 | 
					    identifier: "{{service_provider.contact.friendica}}"
 | 
				
			||||||
    url: "{{ web_protocol }}://{{ service_provider.contact.friendica.split('@')[2] }}/@{{ service_provider.contact.friendica.split('@')[1] }}"
 | 
					    url: "{{ web_protocol }}://{{ service_provider.contact.friendica.split('@')[2] }}/@{{ service_provider.contact.friendica.split('@')[1] }}"
 | 
				
			||||||
    iframe: {{ applications | is_feature_enabled('portfolio_iframe','friendica') }}
 | 
					    iframe: {{ applications | is_feature_enabled('portfolio_iframe','friendica') }}
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
  - link: navigation.header.contact
 | 
					  - link: navigation.header.contact
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cards:
 | 
					cards:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,16 +15,12 @@ def get_expected_statuses(domain: str, parts: list[str], redirected_domains: set
 | 
				
			|||||||
    Returns:
 | 
					    Returns:
 | 
				
			||||||
        A list of expected HTTP status codes.
 | 
					        A list of expected HTTP status codes.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    {%- if domains.listmonk | safe_var | bool %}
 | 
					 | 
				
			||||||
    if domain == '{{domains | get_domain('listmonk')}}':
 | 
					    if domain == '{{domains | get_domain('listmonk')}}':
 | 
				
			||||||
        return [404]
 | 
					        return [404]
 | 
				
			||||||
    {%- endif %}
 | 
					 | 
				
			||||||
    if (parts and parts[0] == 'www') or (domain in redirected_domains):
 | 
					    if (parts and parts[0] == 'www') or (domain in redirected_domains):
 | 
				
			||||||
        return [301]
 | 
					        return [301]
 | 
				
			||||||
    {%- if domains.yourls | safe_var | bool %}
 | 
					 | 
				
			||||||
    if domain == '{{domains | get_domain('yourls')}}':
 | 
					    if domain == '{{domains | get_domain('yourls')}}':
 | 
				
			||||||
        return [403]
 | 
					        return [403]
 | 
				
			||||||
    {%- endif %}
 | 
					 | 
				
			||||||
    # Default: Expect status code 200 or 302 for a domain
 | 
					    # Default: Expect status code 200 or 302 for a domain
 | 
				
			||||||
    return [200,302]
 | 
					    return [200,302]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,9 +44,7 @@ for filename in os.listdir(config_path):
 | 
				
			|||||||
        url = f"{{ web_protocol }}://{domain}"
 | 
					        url = f"{{ web_protocol }}://{domain}"
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        redirected_domains = [domain['source'] for domain in {{ current_play_domain_mappings_redirect}}]
 | 
					        redirected_domains = [domain['source'] for domain in {{ current_play_domain_mappings_redirect}}]
 | 
				
			||||||
        {%- if domains.mailu | safe_var | bool %}
 | 
					 | 
				
			||||||
        redirected_domains.append("{{domains | get_domain('mailu')}}")
 | 
					        redirected_domains.append("{{domains | get_domain('mailu')}}")
 | 
				
			||||||
        {%- endif %}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expected_statuses = get_expected_statuses(domain, parts, redirected_domains)
 | 
					        expected_statuses = get_expected_statuses(domain, parts, redirected_domains)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user