Compare commits
	
		
			53 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					834e602686 | ||
| 
						 | 
					1f693ca4f6 | ||
| 
						 | 
					97a0bc6045 | ||
| 
						 | 
					8b75cdfefd | ||
| 
						 | 
					917aecf1ff | ||
| 
						 | 
					663dcd0396 | ||
| 
						 | 
					8f2dffb1ad | ||
| 
						 | 
					20228e3d19 | ||
| 
						 | 
					81c6cc11b3 | ||
| 
						 | 
					2ccacbe5f3 | ||
| 
						 | 
					a5345e8468 | ||
| 
						 | 
					8f5d62bb81 | ||
| 
						 | 
					28f6838560 | ||
| 
						 | 
					c86aacb31c | ||
| 
						 | 
					f62f5192d6 | ||
| 
						 | 
					b14ea1fe3e | ||
| 
						 | 
					552633a00b | ||
| 
						 | 
					7faba2a690 | ||
| 
						 | 
					db910aff06 | ||
| 
						 | 
					72126052ad | ||
| 
						 | 
					75d9f6a7e7 | ||
| 
						 | 
					de677294c6 | ||
| 
						 | 
					da1e6b8259 | ||
| 
						 | 
					a9633b3990 | ||
| 
						 | 
					7ac9af1cc1 | ||
| 
						 | 
					00d8b8cd61 | ||
| 
						 | 
					af7ff7f5cf | ||
| 
						 | 
					2a20719130 | ||
| 
						 | 
					f481940180 | ||
| 
						 | 
					ca8824d1e3 | ||
| 
						 | 
					f4be199b77 | ||
| 
						 | 
					6bcef8334e | ||
| 
						 | 
					3955eff683 | ||
| 
						 | 
					aa0f6ecd75 | ||
| 
						 | 
					ef4a94ed78 | ||
| 
						 | 
					b5c803ce65 | ||
| 
						 | 
					d4325ed82e | ||
| 
						 | 
					3805fb8f26 | ||
| 
						 | 
					d4d938c655 | ||
| 
						 | 
					1c6911e361 | ||
| 
						 | 
					a1b364f337 | ||
| 
						 | 
					ece5c3da86 | ||
| 
						 | 
					5d1ae6047b | ||
| 
						 | 
					5605c72253 | ||
| 
						 | 
					66bbcf0733 | ||
| 
						 | 
					acc23ea7bb | ||
| 
						 | 
					663bd0c9f0 | ||
| 
						 | 
					39b1025dfa | ||
| 
						 | 
					d2875e90b2 | ||
| 
						 | 
					ff461d1d02 | ||
| 
						 | 
					58164ea2d3 | ||
| 
						 | 
					1bf4834004 | ||
| 
						 | 
					bf58d78281 | 
@@ -1,11 +1,11 @@
 | 
			
		||||
# pulls community scripts from git repo
 | 
			
		||||
FROM python:3.10-slim AS GET_SCRIPTS_STAGE
 | 
			
		||||
FROM python:3.10.6-slim AS GET_SCRIPTS_STAGE
 | 
			
		||||
 | 
			
		||||
RUN apt-get update && \
 | 
			
		||||
    apt-get install -y --no-install-recommends git && \
 | 
			
		||||
    git clone https://github.com/amidaware/community-scripts.git /community-scripts
 | 
			
		||||
 | 
			
		||||
FROM python:3.10-slim
 | 
			
		||||
FROM python:3.10.6-slim
 | 
			
		||||
 | 
			
		||||
ENV TACTICAL_DIR /opt/tactical
 | 
			
		||||
ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready
 | 
			
		||||
 
 | 
			
		||||
@@ -22,22 +22,6 @@ services:
 | 
			
		||||
        aliases:
 | 
			
		||||
          - tactical-backend
 | 
			
		||||
 | 
			
		||||
  app-dev:
 | 
			
		||||
    container_name: trmm-app-dev
 | 
			
		||||
    image: node:16-alpine
 | 
			
		||||
    restart: always
 | 
			
		||||
    command: /bin/sh -c "npm install --cache ~/.npm && npm run serve"
 | 
			
		||||
    user: 1000:1000
 | 
			
		||||
    working_dir: /workspace/web
 | 
			
		||||
    volumes:
 | 
			
		||||
      - ..:/workspace:cached
 | 
			
		||||
    ports:
 | 
			
		||||
      - "8080:${APP_PORT}"
 | 
			
		||||
    networks:
 | 
			
		||||
      dev:
 | 
			
		||||
        aliases:
 | 
			
		||||
          - tactical-frontend
 | 
			
		||||
 | 
			
		||||
  # nats
 | 
			
		||||
  nats-dev:
 | 
			
		||||
    container_name: trmm-nats-dev
 | 
			
		||||
 
 | 
			
		||||
@@ -15,10 +15,7 @@ set -e
 | 
			
		||||
: "${MESH_PASS:=meshcentralpass}"
 | 
			
		||||
: "${MESH_HOST:=tactical-meshcentral}"
 | 
			
		||||
: "${API_HOST:=tactical-backend}"
 | 
			
		||||
: "${APP_HOST:=tactical-frontend}"
 | 
			
		||||
: "${REDIS_HOST:=tactical-redis}"
 | 
			
		||||
: "${HTTP_PROTOCOL:=http}"
 | 
			
		||||
: "${APP_PORT:=8080}"
 | 
			
		||||
: "${API_PORT:=8000}"
 | 
			
		||||
 | 
			
		||||
: "${CERT_PRIV_PATH:=${TACTICAL_DIR}/certs/privkey.pem}"
 | 
			
		||||
@@ -142,16 +139,6 @@ if [ "$1" = 'tactical-init-dev' ]; then
 | 
			
		||||
 | 
			
		||||
  django_setup
 | 
			
		||||
 | 
			
		||||
  # create .env file for frontend
 | 
			
		||||
  webenv="$(cat << EOF
 | 
			
		||||
PROD_URL = "${HTTP_PROTOCOL}://${API_HOST}"
 | 
			
		||||
DEV_URL = "${HTTP_PROTOCOL}://${API_HOST}"
 | 
			
		||||
DEV_PORT = ${APP_PORT}
 | 
			
		||||
DOCKER_BUILD = 1
 | 
			
		||||
EOF
 | 
			
		||||
)"
 | 
			
		||||
  echo "${webenv}" | tee "${WORKSPACE_DIR}"/web/.env > /dev/null
 | 
			
		||||
 | 
			
		||||
  # chown everything to tactical user
 | 
			
		||||
  chown -R "${TACTICAL_USER}":"${TACTICAL_USER}" "${WORKSPACE_DIR}"
 | 
			
		||||
  chown -R "${TACTICAL_USER}":"${TACTICAL_USER}" "${TACTICAL_DIR}"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
-r ../api/tacticalrmm/requirements.txt
 | 
			
		||||
-r ../api/tacticalrmm/requirements-dev.txt
 | 
			
		||||
-r ../api/tacticalrmm/requirements-test.txt
 | 
			
		||||
-r /workspace/api/tacticalrmm/requirements.txt
 | 
			
		||||
-r /workspace/api/tacticalrmm/requirements-dev.txt
 | 
			
		||||
-r /workspace/api/tacticalrmm/requirements-test.txt
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/workflows/ci-tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci-tests.yml
									
									
									
									
										vendored
									
									
								
							@@ -14,7 +14,7 @@ jobs:
 | 
			
		||||
    name: Tests
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        python-version: ["3.10.4"]
 | 
			
		||||
        python-version: ["3.10.6"]
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v3
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -55,3 +55,4 @@ coverage.lcov
 | 
			
		||||
daphne.sock.lock
 | 
			
		||||
.pytest_cache
 | 
			
		||||
coverage.xml
 | 
			
		||||
setup_dev.yml
 | 
			
		||||
 
 | 
			
		||||
@@ -2,10 +2,7 @@
 | 
			
		||||
 | 
			
		||||
## Supported Versions
 | 
			
		||||
 | 
			
		||||
| Version | Supported          |
 | 
			
		||||
| ------- | ------------------ |
 | 
			
		||||
| 0.14.1   | :white_check_mark: |
 | 
			
		||||
| < 0.14.1 | :x:                |
 | 
			
		||||
[Latest](https://github.com/amidaware/tacticalrmm/releases/latest) release
 | 
			
		||||
 | 
			
		||||
## Reporting a Vulnerability
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,19 @@
 | 
			
		||||
---
 | 
			
		||||
user: "tactical"
 | 
			
		||||
python_ver: "3.10.4"
 | 
			
		||||
python_ver: "3.10.6"
 | 
			
		||||
go_ver: "1.18.5"
 | 
			
		||||
backend_repo: "https://github.com/amidaware/tacticalrmm.git"
 | 
			
		||||
frontend_repo: "https://github.com/amidaware/tacticalrmm-web.git"
 | 
			
		||||
scripts_repo: "https://github.com/amidaware/community-scripts.git"
 | 
			
		||||
backend_dir: "/opt/trmm"
 | 
			
		||||
frontend_dir: "/opt/trmm-web"
 | 
			
		||||
scripts_dir: "/opt/community-scripts"
 | 
			
		||||
trmm_dir: "/opt/trmm/api/tacticalrmm/tacticalrmm"
 | 
			
		||||
scripts_dir: "/opt/trmm-community-scripts"
 | 
			
		||||
trmm_dir: "{{ backend_dir }}/api/tacticalrmm/tacticalrmm"
 | 
			
		||||
mesh_dir: "/opt/meshcentral"
 | 
			
		||||
settings_file: "{{ trmm_dir }}/settings.py"
 | 
			
		||||
local_settings_file: "{{ trmm_dir }}/local_settings.py"
 | 
			
		||||
fullchain_dest: /etc/ssl/certs/fullchain.pem
 | 
			
		||||
privkey_dest: /etc/ssl/certs/privkey.pem
 | 
			
		||||
 | 
			
		||||
base_pkgs:
 | 
			
		||||
  - build-essential
 | 
			
		||||
@@ -22,7 +26,6 @@ base_pkgs:
 | 
			
		||||
  - g++
 | 
			
		||||
  - make
 | 
			
		||||
  - ca-certificates
 | 
			
		||||
  - redis
 | 
			
		||||
  - git
 | 
			
		||||
 | 
			
		||||
python_pkgs:
 | 
			
		||||
 
 | 
			
		||||
@@ -5,18 +5,24 @@ pid /run/nginx.pid;
 | 
			
		||||
include /etc/nginx/modules-enabled/*.conf;
 | 
			
		||||
 | 
			
		||||
events {
 | 
			
		||||
        worker_connections 2048;
 | 
			
		||||
        worker_connections 4096;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
http {
 | 
			
		||||
        sendfile on;
 | 
			
		||||
        server_tokens off;
 | 
			
		||||
        tcp_nopush on;
 | 
			
		||||
        types_hash_max_size 2048;
 | 
			
		||||
        server_names_hash_bucket_size 64;
 | 
			
		||||
        include /etc/nginx/mime.types;
 | 
			
		||||
        default_type application/octet-stream;
 | 
			
		||||
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
 | 
			
		||||
        ssl_protocols TLSv1.2 TLSv1.3;
 | 
			
		||||
        ssl_prefer_server_ciphers on;
 | 
			
		||||
        ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
 | 
			
		||||
        ssl_ecdh_curve secp384r1;
 | 
			
		||||
        ssl_stapling on;
 | 
			
		||||
        ssl_stapling_verify on;
 | 
			
		||||
        add_header X-Content-Type-Options nosniff;
 | 
			
		||||
        access_log /var/log/nginx/access.log;
 | 
			
		||||
        error_log /var/log/nginx/error.log;
 | 
			
		||||
        gzip on;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								ansible/roles/trmm_dev/files/nginx.repo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								ansible/roles/trmm_dev/files/nginx.repo
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
deb https://nginx.org/packages/debian/ bullseye nginx
 | 
			
		||||
deb-src https://nginx.org/packages/debian/ bullseye nginx
 | 
			
		||||
@@ -9,6 +9,19 @@
 | 
			
		||||
    group: "root"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
 | 
			
		||||
- name: set max_user_watches
 | 
			
		||||
  tags: sysctl
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.lineinfile:
 | 
			
		||||
    path: /etc/sysctl.conf
 | 
			
		||||
    line: fs.inotify.max_user_watches=524288
 | 
			
		||||
 | 
			
		||||
- name: reload sysctl
 | 
			
		||||
  tags: sysctl
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.command:
 | 
			
		||||
    cmd: sysctl -p
 | 
			
		||||
 | 
			
		||||
- name: install base packages
 | 
			
		||||
  tags: base
 | 
			
		||||
  become: yes
 | 
			
		||||
@@ -19,6 +32,21 @@
 | 
			
		||||
  with_items:
 | 
			
		||||
    - "{{ base_pkgs }}"
 | 
			
		||||
 | 
			
		||||
- name: download and install golang
 | 
			
		||||
  tags: golang
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.unarchive:
 | 
			
		||||
    src: "https://go.dev/dl/go{{ go_ver }}.linux-amd64.tar.gz"
 | 
			
		||||
    dest: /usr/local
 | 
			
		||||
    remote_src: yes
 | 
			
		||||
 | 
			
		||||
- name: add golang to path
 | 
			
		||||
  become: yes
 | 
			
		||||
  tags: golang
 | 
			
		||||
  ansible.builtin.copy:
 | 
			
		||||
    dest: /etc/profile.d/golang.sh
 | 
			
		||||
    content: "PATH=$PATH:/usr/local/go/bin"
 | 
			
		||||
 | 
			
		||||
- name: install python prereqs
 | 
			
		||||
  tags: python
 | 
			
		||||
  become: yes
 | 
			
		||||
@@ -63,31 +91,13 @@
 | 
			
		||||
    cmd: |
 | 
			
		||||
      make altinstall
 | 
			
		||||
 | 
			
		||||
- name: install nginx
 | 
			
		||||
  tags: nginx
 | 
			
		||||
- name: install redis
 | 
			
		||||
  tags: redis
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.apt:
 | 
			
		||||
    pkg: nginx
 | 
			
		||||
    pkg: redis
 | 
			
		||||
    state: present
 | 
			
		||||
 | 
			
		||||
- name: set nginx default conf
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.copy:
 | 
			
		||||
    src: nginx-default.conf
 | 
			
		||||
    dest: /etc/nginx/nginx.conf
 | 
			
		||||
    owner: "root"
 | 
			
		||||
    group: "root"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
 | 
			
		||||
- name: ensure nginx enabled and restarted
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.service:
 | 
			
		||||
    name: nginx
 | 
			
		||||
    enabled: yes
 | 
			
		||||
    state: restarted
 | 
			
		||||
 | 
			
		||||
- name: create postgres repo
 | 
			
		||||
  tags: postgres
 | 
			
		||||
  become: yes
 | 
			
		||||
@@ -96,7 +106,7 @@
 | 
			
		||||
    dest: /etc/apt/sources.list.d/pgdg.list
 | 
			
		||||
    owner: root
 | 
			
		||||
    group: root
 | 
			
		||||
    mode: "0440"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
 | 
			
		||||
- name: import postgres repo signing key
 | 
			
		||||
  tags: postgres
 | 
			
		||||
@@ -232,6 +242,200 @@
 | 
			
		||||
  ansible.builtin.shell:
 | 
			
		||||
    cmd: npm install -g npm
 | 
			
		||||
 | 
			
		||||
- name: install quasar cli
 | 
			
		||||
  tags: quasar
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.shell:
 | 
			
		||||
    cmd: npm install -g @quasar/cli
 | 
			
		||||
 | 
			
		||||
- name: install frontend
 | 
			
		||||
  tags: quasar
 | 
			
		||||
  ansible.builtin.shell:
 | 
			
		||||
    chdir: "{{ frontend_dir }}"
 | 
			
		||||
    cmd: npm install
 | 
			
		||||
 | 
			
		||||
- name: add quasar env
 | 
			
		||||
  tags: quasar
 | 
			
		||||
  ansible.builtin.template:
 | 
			
		||||
    src: quasar.env.j2
 | 
			
		||||
    dest: "{{ frontend_dir }}/.env"
 | 
			
		||||
    owner: "{{ user }}"
 | 
			
		||||
    group: "{{ user }}"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
 | 
			
		||||
- name: remove tempdirs
 | 
			
		||||
  tags: cleanup
 | 
			
		||||
  become: yes
 | 
			
		||||
  ignore_errors: yes
 | 
			
		||||
  ansible.builtin.file:
 | 
			
		||||
    path: "{{ item }}"
 | 
			
		||||
    state: absent
 | 
			
		||||
  with_items:
 | 
			
		||||
    - "{{ nats_tmp.path }}"
 | 
			
		||||
    - "{{ python_tmp.path }}"
 | 
			
		||||
    - "{{ nodejs_tmp.path }}"
 | 
			
		||||
 | 
			
		||||
- name: deploy fullchain
 | 
			
		||||
  tags: certs
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.copy:
 | 
			
		||||
    src: "{{ fullchain_src }}"
 | 
			
		||||
    dest: "{{ fullchain_dest }}"
 | 
			
		||||
    owner: "{{ user }}"
 | 
			
		||||
    group: "{{ user }}"
 | 
			
		||||
    mode: "0440"
 | 
			
		||||
 | 
			
		||||
- name: deploy privkey
 | 
			
		||||
  tags: certs
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.copy:
 | 
			
		||||
    src: "{{ privkey_src }}"
 | 
			
		||||
    dest: "{{ privkey_dest }}"
 | 
			
		||||
    owner: "{{ user }}"
 | 
			
		||||
    group: "{{ user }}"
 | 
			
		||||
    mode: "0440"
 | 
			
		||||
 | 
			
		||||
- name: import nginx signing key
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.apt_key:
 | 
			
		||||
    url: https://nginx.org/packages/keys/nginx_signing.key
 | 
			
		||||
    state: present
 | 
			
		||||
 | 
			
		||||
- name: add nginx repo
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.copy:
 | 
			
		||||
    src: nginx.repo
 | 
			
		||||
    dest: /etc/apt/sources.list.d/nginx.list
 | 
			
		||||
    owner: "root"
 | 
			
		||||
    group: "root"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
 | 
			
		||||
- name: install nginx
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.apt:
 | 
			
		||||
    pkg: nginx
 | 
			
		||||
    state: present
 | 
			
		||||
    update_cache: yes
 | 
			
		||||
 | 
			
		||||
- name: set nginx default conf
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.copy:
 | 
			
		||||
    src: nginx-default.conf
 | 
			
		||||
    dest: /etc/nginx/nginx.conf
 | 
			
		||||
    owner: "root"
 | 
			
		||||
    group: "root"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
 | 
			
		||||
- name: create nginx dirs
 | 
			
		||||
  become: yes
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  ansible.builtin.file:
 | 
			
		||||
    state: directory
 | 
			
		||||
    path: "{{ item }}"
 | 
			
		||||
    mode: "0755"
 | 
			
		||||
  with_items:
 | 
			
		||||
    - /etc/nginx/sites-available
 | 
			
		||||
    - /etc/nginx/sites-enabled
 | 
			
		||||
 | 
			
		||||
- name: deploy nginx sites
 | 
			
		||||
  become: yes
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  ansible.builtin.template:
 | 
			
		||||
    src: "{{ item.src }}"
 | 
			
		||||
    dest: "{{ item.dest }}"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
    owner: root
 | 
			
		||||
    group: root
 | 
			
		||||
  with_items:
 | 
			
		||||
    - { src: backend.nginx.j2, dest: /etc/nginx/sites-available/backend.conf }
 | 
			
		||||
    - { src: mesh.nginx.j2, dest: /etc/nginx/sites-available/mesh.conf }
 | 
			
		||||
 | 
			
		||||
- name: enable nginx sites
 | 
			
		||||
  become: yes
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  ansible.builtin.file:
 | 
			
		||||
    src: "{{ item.src }}"
 | 
			
		||||
    dest: "{{ item.dest }}"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
    owner: root
 | 
			
		||||
    group: root
 | 
			
		||||
    state: link
 | 
			
		||||
  with_items:
 | 
			
		||||
    - {
 | 
			
		||||
        src: /etc/nginx/sites-available/backend.conf,
 | 
			
		||||
        dest: /etc/nginx/sites-enabled/backend.conf,
 | 
			
		||||
      }
 | 
			
		||||
    - {
 | 
			
		||||
        src: /etc/nginx/sites-available/mesh.conf,
 | 
			
		||||
        dest: /etc/nginx/sites-enabled/mesh.conf,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
- name: ensure nginx enabled and restarted
 | 
			
		||||
  tags: nginx
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.service:
 | 
			
		||||
    name: nginx
 | 
			
		||||
    enabled: yes
 | 
			
		||||
    state: restarted
 | 
			
		||||
 | 
			
		||||
- name: copy nats-api bin
 | 
			
		||||
  tags: nats-api
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.copy:
 | 
			
		||||
    remote_src: yes
 | 
			
		||||
    src: "{{ backend_dir }}/natsapi/bin/nats-api"
 | 
			
		||||
    dest: /usr/local/bin/nats-api
 | 
			
		||||
    owner: "{{ user }}"
 | 
			
		||||
    group: "{{ user }}"
 | 
			
		||||
    mode: "0755"
 | 
			
		||||
 | 
			
		||||
- name: get setuptools_ver
 | 
			
		||||
  tags: pip
 | 
			
		||||
  ansible.builtin.shell: grep "^SETUPTOOLS_VER" {{ settings_file }} | awk -F'[= "]' '{print $5}'
 | 
			
		||||
  register: setuptools_ver
 | 
			
		||||
 | 
			
		||||
- name: get wheel_ver
 | 
			
		||||
  tags: pip
 | 
			
		||||
  ansible.builtin.shell: grep "^WHEEL_VER" {{ settings_file }} | awk -F'[= "]' '{print $5}'
 | 
			
		||||
  register: wheel_ver
 | 
			
		||||
 | 
			
		||||
- name: setup virtual env
 | 
			
		||||
  tags: pip
 | 
			
		||||
  ansible.builtin.shell:
 | 
			
		||||
    chdir: "{{ backend_dir }}/api"
 | 
			
		||||
    cmd: python3.10 -m venv env
 | 
			
		||||
 | 
			
		||||
- name: update pip to latest
 | 
			
		||||
  tags: pip
 | 
			
		||||
  ansible.builtin.pip:
 | 
			
		||||
    virtualenv: "{{ backend_dir }}/api/env"
 | 
			
		||||
    name: pip
 | 
			
		||||
    state: latest
 | 
			
		||||
 | 
			
		||||
- name: install setuptools and wheel
 | 
			
		||||
  tags: pip
 | 
			
		||||
  ansible.builtin.pip:
 | 
			
		||||
    virtualenv: "{{ backend_dir }}/api/env"
 | 
			
		||||
    name: "{{ item }}"
 | 
			
		||||
  with_items:
 | 
			
		||||
    - "setuptools=={{ setuptools_ver.stdout }}"
 | 
			
		||||
    - "wheel=={{ wheel_ver.stdout }}"
 | 
			
		||||
 | 
			
		||||
- name: install python packages
 | 
			
		||||
  tags: pip
 | 
			
		||||
  ansible.builtin.pip:
 | 
			
		||||
    virtualenv: "{{ backend_dir }}/api/env"
 | 
			
		||||
    chdir: "{{ backend_dir }}/api/tacticalrmm"
 | 
			
		||||
    requirements: "{{ item }}"
 | 
			
		||||
  with_items:
 | 
			
		||||
    - requirements.txt
 | 
			
		||||
    - requirements-dev.txt
 | 
			
		||||
    - requirements-test.txt
 | 
			
		||||
 | 
			
		||||
- name: deploy django local settings
 | 
			
		||||
  tags: django
 | 
			
		||||
  ansible.builtin.template:
 | 
			
		||||
@@ -241,13 +445,189 @@
 | 
			
		||||
    owner: "{{ user }}"
 | 
			
		||||
    group: "{{ user }}"
 | 
			
		||||
 | 
			
		||||
- name: remove tempdirs
 | 
			
		||||
  tags: cleanup
 | 
			
		||||
- name: setup django
 | 
			
		||||
  tags: django
 | 
			
		||||
  ansible.builtin.shell:
 | 
			
		||||
    chdir: "{{ backend_dir }}/api/tacticalrmm"
 | 
			
		||||
    cmd: |
 | 
			
		||||
      . ../env/bin/activate
 | 
			
		||||
      python manage.py migrate --no-input
 | 
			
		||||
      python manage.py collectstatic --no-input
 | 
			
		||||
      python manage.py create_natsapi_conf
 | 
			
		||||
      python manage.py load_chocos
 | 
			
		||||
      python manage.py load_community_scripts
 | 
			
		||||
      echo "from accounts.models import User; User.objects.create_superuser('{{ django_user }}', '{{ github_email }}', '{{ django_password }}') if not User.objects.filter(username='{{ django_user }}').exists() else 0;" | python manage.py shell
 | 
			
		||||
      python manage.py create_installer_user
 | 
			
		||||
 | 
			
		||||
- name: deploy services
 | 
			
		||||
  tags: services
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.template:
 | 
			
		||||
    src: "{{ item.src }}"
 | 
			
		||||
    dest: "{{ item.dest }}"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
    owner: "root"
 | 
			
		||||
    group: "root"
 | 
			
		||||
  with_items:
 | 
			
		||||
    - { src: nats-api.systemd.j2, dest: /etc/systemd/system/nats-api.service }
 | 
			
		||||
    - { src: nats-server.systemd.j2, dest: /etc/systemd/system/nats.service }
 | 
			
		||||
    - { src: mesh.systemd.j2, dest: /etc/systemd/system/meshcentral.service }
 | 
			
		||||
 | 
			
		||||
- name: import mongodb repo signing key
 | 
			
		||||
  tags: mongo
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.apt_key:
 | 
			
		||||
    url: https://www.mongodb.org/static/pgp/server-4.4.asc
 | 
			
		||||
    state: present
 | 
			
		||||
 | 
			
		||||
- name: setup mongodb repo
 | 
			
		||||
  tags: mongo
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.copy:
 | 
			
		||||
    content: "deb https://repo.mongodb.org/apt/debian buster/mongodb-org/4.4 main"
 | 
			
		||||
    dest: /etc/apt/sources.list.d/mongodb-org-4.4.list
 | 
			
		||||
    owner: root
 | 
			
		||||
    group: root
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
 | 
			
		||||
- name: install mongodb
 | 
			
		||||
  tags: mongo
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.apt:
 | 
			
		||||
    pkg: mongodb-org
 | 
			
		||||
    state: present
 | 
			
		||||
    update_cache: yes
 | 
			
		||||
 | 
			
		||||
- name: ensure mongodb enabled and started
 | 
			
		||||
  tags: mongo
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.service:
 | 
			
		||||
    name: mongod
 | 
			
		||||
    enabled: yes
 | 
			
		||||
    state: started
 | 
			
		||||
 | 
			
		||||
- name: get mesh_ver
 | 
			
		||||
  tags: mesh
 | 
			
		||||
  ansible.builtin.shell: grep "^MESH_VER" {{ settings_file }} | awk -F'[= "]' '{print $5}'
 | 
			
		||||
  register: mesh_ver
 | 
			
		||||
 | 
			
		||||
- name: create meshcentral data directory
 | 
			
		||||
  tags: mesh
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.file:
 | 
			
		||||
    path: "{{ item }}"
 | 
			
		||||
    state: absent
 | 
			
		||||
    path: "{{ mesh_dir }}/meshcentral-data"
 | 
			
		||||
    state: directory
 | 
			
		||||
    owner: "{{ user }}"
 | 
			
		||||
    group: "{{ user }}"
 | 
			
		||||
    mode: "0755"
 | 
			
		||||
 | 
			
		||||
- name: install meshcentral
 | 
			
		||||
  tags: mesh
 | 
			
		||||
  ansible.builtin.command:
 | 
			
		||||
    chdir: "{{ mesh_dir }}"
 | 
			
		||||
    cmd: "npm install meshcentral@{{ mesh_ver.stdout }}"
 | 
			
		||||
 | 
			
		||||
- name: deploy mesh config
 | 
			
		||||
  tags: mesh
 | 
			
		||||
  ansible.builtin.template:
 | 
			
		||||
    src: mesh.cfg.j2
 | 
			
		||||
    dest: "{{ mesh_dir }}/meshcentral-data/config.json"
 | 
			
		||||
    mode: "0644"
 | 
			
		||||
    owner: "{{ user }}"
 | 
			
		||||
    group: "{{ user }}"
 | 
			
		||||
 | 
			
		||||
- name: start meshcentral
 | 
			
		||||
  tags: mesh
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.systemd:
 | 
			
		||||
    name: meshcentral.service
 | 
			
		||||
    state: started
 | 
			
		||||
    enabled: yes
 | 
			
		||||
    daemon_reload: yes
 | 
			
		||||
 | 
			
		||||
- name: wait for meshcentral to be ready
 | 
			
		||||
  tags: mesh
 | 
			
		||||
  uri:
 | 
			
		||||
    url: "https://{{ mesh }}"
 | 
			
		||||
    return_content: yes
 | 
			
		||||
    validate_certs: yes
 | 
			
		||||
    status_code: 200
 | 
			
		||||
  register: mesh_status
 | 
			
		||||
  until: mesh_status.status == 200
 | 
			
		||||
  retries: 20
 | 
			
		||||
  delay: 3
 | 
			
		||||
 | 
			
		||||
- name: get meshcentral login token key
 | 
			
		||||
  tags: mesh_key
 | 
			
		||||
  ansible.builtin.command:
 | 
			
		||||
    chdir: "{{ mesh_dir }}"
 | 
			
		||||
    cmd: node node_modules/meshcentral --logintokenkey
 | 
			
		||||
  register: mesh_token_key
 | 
			
		||||
 | 
			
		||||
- name: add mesh key to django settings file
 | 
			
		||||
  tags: mesh_key
 | 
			
		||||
  ansible.builtin.lineinfile:
 | 
			
		||||
    path: "{{ local_settings_file }}"
 | 
			
		||||
    line: 'MESH_TOKEN_KEY = "{{ mesh_token_key.stdout }}"'
 | 
			
		||||
 | 
			
		||||
- name: stop meshcentral service
 | 
			
		||||
  tags: mesh_user
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.service:
 | 
			
		||||
    name: meshcentral.service
 | 
			
		||||
    state: stopped
 | 
			
		||||
 | 
			
		||||
- name: create mesh user
 | 
			
		||||
  tags: mesh_user
 | 
			
		||||
  ansible.builtin.shell:
 | 
			
		||||
    chdir: "{{ mesh_dir }}"
 | 
			
		||||
    cmd: |
 | 
			
		||||
      node node_modules/meshcentral --createaccount {{ mesh_user }} --pass {{ mesh_password }} --email {{ github_email }}
 | 
			
		||||
      node node_modules/meshcentral --adminaccount {{ mesh_user }}
 | 
			
		||||
 | 
			
		||||
- name: start meshcentral service
 | 
			
		||||
  tags: mesh_user
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.service:
 | 
			
		||||
    name: meshcentral.service
 | 
			
		||||
    state: started
 | 
			
		||||
 | 
			
		||||
- name: wait for meshcentral to be ready
 | 
			
		||||
  tags: mesh_user
 | 
			
		||||
  uri:
 | 
			
		||||
    url: "https://{{ mesh }}"
 | 
			
		||||
    return_content: yes
 | 
			
		||||
    validate_certs: yes
 | 
			
		||||
    status_code: 200
 | 
			
		||||
  register: mesh_status
 | 
			
		||||
  until: mesh_status.status == 200
 | 
			
		||||
  retries: 20
 | 
			
		||||
  delay: 3
 | 
			
		||||
 | 
			
		||||
- name: create mesh device group
 | 
			
		||||
  tags: mesh_user
 | 
			
		||||
  ansible.builtin.shell:
 | 
			
		||||
    chdir: "{{ mesh_dir }}"
 | 
			
		||||
    cmd: |
 | 
			
		||||
      node node_modules/meshcentral/meshctrl.js --url wss://{{ mesh }}:443 --loginuser {{ mesh_user }} --loginpass {{ mesh_password }} AddDeviceGroup --name TacticalRMM
 | 
			
		||||
 | 
			
		||||
- name: finish up django
 | 
			
		||||
  tags: mesh_user
 | 
			
		||||
  ansible.builtin.shell:
 | 
			
		||||
    chdir: "{{ backend_dir }}/api/tacticalrmm"
 | 
			
		||||
    cmd: |
 | 
			
		||||
      . ../env/bin/activate
 | 
			
		||||
      python manage.py initial_db_setup
 | 
			
		||||
      python manage.py reload_nats
 | 
			
		||||
 | 
			
		||||
- name: restart services
 | 
			
		||||
  tags: services
 | 
			
		||||
  become: yes
 | 
			
		||||
  ansible.builtin.systemd:
 | 
			
		||||
    daemon_reload: yes
 | 
			
		||||
    enabled: yes
 | 
			
		||||
    state: restarted
 | 
			
		||||
    name: "{{ item }}.service"
 | 
			
		||||
  with_items:
 | 
			
		||||
    - "{{ nats_tmp.path }}"
 | 
			
		||||
    - "{{ python_tmp.path }}"
 | 
			
		||||
    - "{{ nodejs_tmp.path }}"
 | 
			
		||||
    - nats
 | 
			
		||||
    - nats-api
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								ansible/roles/trmm_dev/templates/backend.nginx.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								ansible/roles/trmm_dev/templates/backend.nginx.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
server {
 | 
			
		||||
    listen 443 ssl reuseport;
 | 
			
		||||
    listen [::]:443 ssl;
 | 
			
		||||
    server_name {{ api }};
 | 
			
		||||
    client_max_body_size 300M;
 | 
			
		||||
    ssl_certificate {{ fullchain_dest }};
 | 
			
		||||
    ssl_certificate_key {{ privkey_dest }};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    location ~ ^/natsws {
 | 
			
		||||
        proxy_pass http://127.0.0.1:9235;
 | 
			
		||||
        proxy_http_version 1.1;
 | 
			
		||||
        proxy_set_header Host $host;
 | 
			
		||||
        proxy_set_header Upgrade $http_upgrade;
 | 
			
		||||
        proxy_set_header Connection "upgrade";
 | 
			
		||||
        proxy_set_header X-Forwarded-Host $host:$server_port;
 | 
			
		||||
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 | 
			
		||||
        proxy_set_header X-Forwarded-Proto $scheme;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -2,9 +2,7 @@ SECRET_KEY = "{{ django_secret }}"
 | 
			
		||||
DEBUG = True
 | 
			
		||||
ALLOWED_HOSTS = ['{{ api }}']
 | 
			
		||||
ADMIN_URL = "admin/"
 | 
			
		||||
CORS_ORIGIN_WHITELIST = [
 | 
			
		||||
    "https://{{ rmm }}"
 | 
			
		||||
]
 | 
			
		||||
CORS_ORIGIN_ALLOW_ALL = True
 | 
			
		||||
DATABASES = {
 | 
			
		||||
    'default': {
 | 
			
		||||
        'ENGINE': 'django.db.backends.postgresql',
 | 
			
		||||
@@ -17,3 +15,7 @@ DATABASES = {
 | 
			
		||||
}
 | 
			
		||||
REDIS_HOST    = "localhost"
 | 
			
		||||
ADMIN_ENABLED = True
 | 
			
		||||
CERT_FILE = "{{ fullchain_src }}"
 | 
			
		||||
KEY_FILE = "{{ privkey_src }}"
 | 
			
		||||
MESH_USERNAME = "{{ mesh_user }}"
 | 
			
		||||
MESH_SITE = "https://{{ mesh }}"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								ansible/roles/trmm_dev/templates/mesh.cfg.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								ansible/roles/trmm_dev/templates/mesh.cfg.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
{
 | 
			
		||||
  "settings": {
 | 
			
		||||
    "Cert": "{{ mesh }}",
 | 
			
		||||
    "MongoDb": "mongodb://127.0.0.1:27017",
 | 
			
		||||
    "MongoDbName": "meshcentral",
 | 
			
		||||
    "WANonly": true,
 | 
			
		||||
    "Minify": 1,
 | 
			
		||||
    "Port": 4430,
 | 
			
		||||
    "AliasPort": 443,
 | 
			
		||||
    "RedirPort": 800,
 | 
			
		||||
    "AllowLoginToken": true,
 | 
			
		||||
    "AllowFraming": true,
 | 
			
		||||
    "AgentPong": 300,
 | 
			
		||||
    "AllowHighQualityDesktop": true,
 | 
			
		||||
    "TlsOffload": "127.0.0.1",
 | 
			
		||||
    "agentCoreDump": false,
 | 
			
		||||
    "Compression": true,
 | 
			
		||||
    "WsCompression": true,
 | 
			
		||||
    "AgentWsCompression": true,
 | 
			
		||||
    "MaxInvalidLogin": { "time": 5, "count": 5, "coolofftime": 30 }
 | 
			
		||||
  },
 | 
			
		||||
  "domains": {
 | 
			
		||||
    "": {
 | 
			
		||||
      "Title": "Tactical RMM",
 | 
			
		||||
      "Title2": "Tactical RMM",
 | 
			
		||||
      "NewAccounts": false,
 | 
			
		||||
      "CertUrl": "https://{{ mesh }}:443/",
 | 
			
		||||
      "GeoLocation": true,
 | 
			
		||||
      "CookieIpCheck": false,
 | 
			
		||||
      "mstsc": true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								ansible/roles/trmm_dev/templates/mesh.nginx.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								ansible/roles/trmm_dev/templates/mesh.nginx.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
server {
 | 
			
		||||
    listen 443 ssl;
 | 
			
		||||
    listen [::]:443 ssl;
 | 
			
		||||
    proxy_send_timeout 330s;
 | 
			
		||||
    proxy_read_timeout 330s;
 | 
			
		||||
    server_name {{ mesh }};
 | 
			
		||||
    ssl_certificate {{ fullchain_dest }};
 | 
			
		||||
    ssl_certificate_key {{ privkey_dest }};
 | 
			
		||||
 | 
			
		||||
    ssl_session_cache shared:WEBSSL:10m;
 | 
			
		||||
 | 
			
		||||
    location / {
 | 
			
		||||
        proxy_pass http://127.0.0.1:4430/;
 | 
			
		||||
        proxy_http_version 1.1;
 | 
			
		||||
        proxy_set_header Host $host;
 | 
			
		||||
        proxy_set_header Upgrade $http_upgrade;
 | 
			
		||||
        proxy_set_header Connection "upgrade";
 | 
			
		||||
        proxy_set_header X-Forwarded-Host $host:$server_port;
 | 
			
		||||
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 | 
			
		||||
        proxy_set_header X-Forwarded-Proto $scheme;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								ansible/roles/trmm_dev/templates/mesh.systemd.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								ansible/roles/trmm_dev/templates/mesh.systemd.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=MeshCentral Server
 | 
			
		||||
After=network.target mongod.service nginx.service
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
LimitNOFILE=1000000
 | 
			
		||||
ExecStart=/usr/bin/node node_modules/meshcentral
 | 
			
		||||
Environment=NODE_ENV=production
 | 
			
		||||
WorkingDirectory={{ mesh_dir }}
 | 
			
		||||
User={{ user }}
 | 
			
		||||
Group={{ user }}
 | 
			
		||||
Restart=always
 | 
			
		||||
RestartSec=10s
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
							
								
								
									
										14
									
								
								ansible/roles/trmm_dev/templates/nats-api.systemd.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								ansible/roles/trmm_dev/templates/nats-api.systemd.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=TacticalRMM Nats Api
 | 
			
		||||
After=nats.service
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
ExecStart=/usr/local/bin/nats-api -config {{ backend_dir }}/api/tacticalrmm/nats-api.conf
 | 
			
		||||
User={{ user }}
 | 
			
		||||
Group={{ user }}
 | 
			
		||||
Restart=always
 | 
			
		||||
RestartSec=5s
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
							
								
								
									
										18
									
								
								ansible/roles/trmm_dev/templates/nats-server.systemd.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								ansible/roles/trmm_dev/templates/nats-server.systemd.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=NATS Server
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
PrivateTmp=true
 | 
			
		||||
Type=simple
 | 
			
		||||
ExecStart=/usr/local/bin/nats-server -c {{ backend_dir }}/api/tacticalrmm/nats-rmm.conf
 | 
			
		||||
ExecReload=/usr/bin/kill -s HUP $MAINPID
 | 
			
		||||
ExecStop=/usr/bin/kill -s SIGINT $MAINPID
 | 
			
		||||
User={{ user }}
 | 
			
		||||
Group={{ user }}
 | 
			
		||||
Restart=always
 | 
			
		||||
RestartSec=5s
 | 
			
		||||
LimitNOFILE=1000000
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
							
								
								
									
										4
									
								
								ansible/roles/trmm_dev/templates/quasar.env.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								ansible/roles/trmm_dev/templates/quasar.env.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
DEV_URL = "http://{{ api }}:8000"
 | 
			
		||||
DEV_HOST = "{{ rmm }}"
 | 
			
		||||
DEV_PORT = "8080"
 | 
			
		||||
USE_HTTPS = false
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
api: 'api.example.com'
 | 
			
		||||
rmm: 'rmm.example.com'
 | 
			
		||||
mesh: 'mesh.example.com'
 | 
			
		||||
github_username: 'changeme'
 | 
			
		||||
github_email: 'changeme@example.com'
 | 
			
		||||
mesh_site: 'changeme'
 | 
			
		||||
mesh_user: 'changeme'
 | 
			
		||||
mesh_token: 'changeme'
 | 
			
		||||
db_user: 'changeme'
 | 
			
		||||
db_passwd: 'changeme'
 | 
			
		||||
django_secret: 'changeme'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
- hosts: "{{ target }}"
 | 
			
		||||
  vars:
 | 
			
		||||
    ansible_user: tactical
 | 
			
		||||
  roles:
 | 
			
		||||
    - trmm_dev
 | 
			
		||||
							
								
								
									
										20
									
								
								ansible/setup_dev.yml.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								ansible/setup_dev.yml.example
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
---
 | 
			
		||||
- hosts: "{{ target }}"
 | 
			
		||||
  vars:
 | 
			
		||||
    ansible_user: tactical
 | 
			
		||||
    fullchain_src: /path/to/fullchain.pem
 | 
			
		||||
    privkey_src: /path/to/privkey.pem
 | 
			
		||||
    api: "api.example.com"
 | 
			
		||||
    rmm: "rmm.example.com"
 | 
			
		||||
    mesh: "mesh.example.com"
 | 
			
		||||
    github_username: "changeme"
 | 
			
		||||
    github_email: "changeme@example.com"
 | 
			
		||||
    mesh_user: "changeme"
 | 
			
		||||
    mesh_password: "changeme"
 | 
			
		||||
    db_user: "changeme"
 | 
			
		||||
    db_passwd: "changeme"
 | 
			
		||||
    django_secret: "changeme"
 | 
			
		||||
    django_user: "changeme"
 | 
			
		||||
    django_password: "changeme"
 | 
			
		||||
  roles:
 | 
			
		||||
    - trmm_dev
 | 
			
		||||
							
								
								
									
										18
									
								
								api/tacticalrmm/accounts/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								api/tacticalrmm/accounts/utils.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
from typing import TYPE_CHECKING
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from django.http import HttpRequest
 | 
			
		||||
    from accounts.models import User
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_root_user(*, request: "HttpRequest", user: "User") -> bool:
 | 
			
		||||
    root = (
 | 
			
		||||
        hasattr(settings, "ROOT_USER")
 | 
			
		||||
        and request.user != user
 | 
			
		||||
        and user.username == settings.ROOT_USER
 | 
			
		||||
    )
 | 
			
		||||
    demo = (
 | 
			
		||||
        getattr(settings, "DEMO", False) and request.user.username == settings.ROOT_USER
 | 
			
		||||
    )
 | 
			
		||||
    return root or demo
 | 
			
		||||
@@ -22,18 +22,7 @@ from .serializers import (
 | 
			
		||||
    UserSerializer,
 | 
			
		||||
    UserUISerializer,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _is_root_user(request, user) -> bool:
 | 
			
		||||
    root = (
 | 
			
		||||
        hasattr(settings, "ROOT_USER")
 | 
			
		||||
        and request.user != user
 | 
			
		||||
        and user.username == settings.ROOT_USER
 | 
			
		||||
    )
 | 
			
		||||
    demo = (
 | 
			
		||||
        getattr(settings, "DEMO", False) and request.user.username == settings.ROOT_USER
 | 
			
		||||
    )
 | 
			
		||||
    return root or demo
 | 
			
		||||
from accounts.utils import is_root_user
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CheckCreds(KnoxLoginView):
 | 
			
		||||
@@ -159,7 +148,7 @@ class GetUpdateDeleteUser(APIView):
 | 
			
		||||
    def put(self, request, pk):
 | 
			
		||||
        user = get_object_or_404(User, pk=pk)
 | 
			
		||||
 | 
			
		||||
        if _is_root_user(request, user):
 | 
			
		||||
        if is_root_user(request=request, user=user):
 | 
			
		||||
            return notify_error("The root user cannot be modified from the UI")
 | 
			
		||||
 | 
			
		||||
        serializer = UserSerializer(instance=user, data=request.data, partial=True)
 | 
			
		||||
@@ -170,7 +159,7 @@ class GetUpdateDeleteUser(APIView):
 | 
			
		||||
 | 
			
		||||
    def delete(self, request, pk):
 | 
			
		||||
        user = get_object_or_404(User, pk=pk)
 | 
			
		||||
        if _is_root_user(request, user):
 | 
			
		||||
        if is_root_user(request=request, user=user):
 | 
			
		||||
            return notify_error("The root user cannot be deleted from the UI")
 | 
			
		||||
 | 
			
		||||
        user.delete()
 | 
			
		||||
@@ -183,7 +172,7 @@ class UserActions(APIView):
 | 
			
		||||
    # reset password
 | 
			
		||||
    def post(self, request):
 | 
			
		||||
        user = get_object_or_404(User, pk=request.data["id"])
 | 
			
		||||
        if _is_root_user(request, user):
 | 
			
		||||
        if is_root_user(request=request, user=user):
 | 
			
		||||
            return notify_error("The root user cannot be modified from the UI")
 | 
			
		||||
 | 
			
		||||
        user.set_password(request.data["password"])
 | 
			
		||||
@@ -194,7 +183,7 @@ class UserActions(APIView):
 | 
			
		||||
    # reset two factor token
 | 
			
		||||
    def put(self, request):
 | 
			
		||||
        user = get_object_or_404(User, pk=request.data["id"])
 | 
			
		||||
        if _is_root_user(request, user):
 | 
			
		||||
        if is_root_user(request=request, user=user):
 | 
			
		||||
            return notify_error("The root user cannot be modified from the UI")
 | 
			
		||||
 | 
			
		||||
        user.totp_key = ""
 | 
			
		||||
 
 | 
			
		||||
@@ -568,6 +568,12 @@ class Command(BaseCommand):
 | 
			
		||||
                    check5_history.y = 1
 | 
			
		||||
                else:
 | 
			
		||||
                    check5_history.y = 0
 | 
			
		||||
                check5_history.results = {
 | 
			
		||||
                    "retcode": 0,
 | 
			
		||||
                    "stdout": None,
 | 
			
		||||
                    "stderr": None,
 | 
			
		||||
                    "execution_time": "4.0000",
 | 
			
		||||
                }
 | 
			
		||||
                check5_history.save()
 | 
			
		||||
 | 
			
		||||
            check6 = Check()
 | 
			
		||||
@@ -595,6 +601,12 @@ class Command(BaseCommand):
 | 
			
		||||
                check6_history.agent_id = agent.agent_id
 | 
			
		||||
                check6_history.x = django_now - djangotime.timedelta(minutes=i * 2)
 | 
			
		||||
                check6_history.y = 0
 | 
			
		||||
                check6_history.results = {
 | 
			
		||||
                    "retcode": 0,
 | 
			
		||||
                    "stdout": None,
 | 
			
		||||
                    "stderr": None,
 | 
			
		||||
                    "execution_time": "4.0000",
 | 
			
		||||
                }
 | 
			
		||||
                check6_history.save()
 | 
			
		||||
 | 
			
		||||
            nla_task = AutomatedTask()
 | 
			
		||||
@@ -712,6 +724,12 @@ class Command(BaseCommand):
 | 
			
		||||
                check7_history.agent_id = agent.agent_id
 | 
			
		||||
                check7_history.x = django_now - djangotime.timedelta(minutes=i * 2)
 | 
			
		||||
                check7_history.y = 0
 | 
			
		||||
                check7_history.results = {
 | 
			
		||||
                    "retcode": 0,
 | 
			
		||||
                    "stdout": spooler_stdout,
 | 
			
		||||
                    "stderr": None,
 | 
			
		||||
                    "execution_time": "3.1337",
 | 
			
		||||
                }
 | 
			
		||||
                check7_history.save()
 | 
			
		||||
 | 
			
		||||
            if agent.plat == AgentPlat.WINDOWS:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										631
									
								
								api/tacticalrmm/agents/migrations/0055_alter_agent_time_zone.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										631
									
								
								api/tacticalrmm/agents/migrations/0055_alter_agent_time_zone.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,631 @@
 | 
			
		||||
# Generated by Django 4.1 on 2022-08-24 07:32
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("agents", "0054_alter_agent_goarch"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="agent",
 | 
			
		||||
            name="time_zone",
 | 
			
		||||
            field=models.CharField(
 | 
			
		||||
                blank=True,
 | 
			
		||||
                choices=[
 | 
			
		||||
                    ("Africa/Abidjan", "Africa/Abidjan"),
 | 
			
		||||
                    ("Africa/Accra", "Africa/Accra"),
 | 
			
		||||
                    ("Africa/Addis_Ababa", "Africa/Addis_Ababa"),
 | 
			
		||||
                    ("Africa/Algiers", "Africa/Algiers"),
 | 
			
		||||
                    ("Africa/Asmara", "Africa/Asmara"),
 | 
			
		||||
                    ("Africa/Asmera", "Africa/Asmera"),
 | 
			
		||||
                    ("Africa/Bamako", "Africa/Bamako"),
 | 
			
		||||
                    ("Africa/Bangui", "Africa/Bangui"),
 | 
			
		||||
                    ("Africa/Banjul", "Africa/Banjul"),
 | 
			
		||||
                    ("Africa/Bissau", "Africa/Bissau"),
 | 
			
		||||
                    ("Africa/Blantyre", "Africa/Blantyre"),
 | 
			
		||||
                    ("Africa/Brazzaville", "Africa/Brazzaville"),
 | 
			
		||||
                    ("Africa/Bujumbura", "Africa/Bujumbura"),
 | 
			
		||||
                    ("Africa/Cairo", "Africa/Cairo"),
 | 
			
		||||
                    ("Africa/Casablanca", "Africa/Casablanca"),
 | 
			
		||||
                    ("Africa/Ceuta", "Africa/Ceuta"),
 | 
			
		||||
                    ("Africa/Conakry", "Africa/Conakry"),
 | 
			
		||||
                    ("Africa/Dakar", "Africa/Dakar"),
 | 
			
		||||
                    ("Africa/Dar_es_Salaam", "Africa/Dar_es_Salaam"),
 | 
			
		||||
                    ("Africa/Djibouti", "Africa/Djibouti"),
 | 
			
		||||
                    ("Africa/Douala", "Africa/Douala"),
 | 
			
		||||
                    ("Africa/El_Aaiun", "Africa/El_Aaiun"),
 | 
			
		||||
                    ("Africa/Freetown", "Africa/Freetown"),
 | 
			
		||||
                    ("Africa/Gaborone", "Africa/Gaborone"),
 | 
			
		||||
                    ("Africa/Harare", "Africa/Harare"),
 | 
			
		||||
                    ("Africa/Johannesburg", "Africa/Johannesburg"),
 | 
			
		||||
                    ("Africa/Juba", "Africa/Juba"),
 | 
			
		||||
                    ("Africa/Kampala", "Africa/Kampala"),
 | 
			
		||||
                    ("Africa/Khartoum", "Africa/Khartoum"),
 | 
			
		||||
                    ("Africa/Kigali", "Africa/Kigali"),
 | 
			
		||||
                    ("Africa/Kinshasa", "Africa/Kinshasa"),
 | 
			
		||||
                    ("Africa/Lagos", "Africa/Lagos"),
 | 
			
		||||
                    ("Africa/Libreville", "Africa/Libreville"),
 | 
			
		||||
                    ("Africa/Lome", "Africa/Lome"),
 | 
			
		||||
                    ("Africa/Luanda", "Africa/Luanda"),
 | 
			
		||||
                    ("Africa/Lubumbashi", "Africa/Lubumbashi"),
 | 
			
		||||
                    ("Africa/Lusaka", "Africa/Lusaka"),
 | 
			
		||||
                    ("Africa/Malabo", "Africa/Malabo"),
 | 
			
		||||
                    ("Africa/Maputo", "Africa/Maputo"),
 | 
			
		||||
                    ("Africa/Maseru", "Africa/Maseru"),
 | 
			
		||||
                    ("Africa/Mbabane", "Africa/Mbabane"),
 | 
			
		||||
                    ("Africa/Mogadishu", "Africa/Mogadishu"),
 | 
			
		||||
                    ("Africa/Monrovia", "Africa/Monrovia"),
 | 
			
		||||
                    ("Africa/Nairobi", "Africa/Nairobi"),
 | 
			
		||||
                    ("Africa/Ndjamena", "Africa/Ndjamena"),
 | 
			
		||||
                    ("Africa/Niamey", "Africa/Niamey"),
 | 
			
		||||
                    ("Africa/Nouakchott", "Africa/Nouakchott"),
 | 
			
		||||
                    ("Africa/Ouagadougou", "Africa/Ouagadougou"),
 | 
			
		||||
                    ("Africa/Porto-Novo", "Africa/Porto-Novo"),
 | 
			
		||||
                    ("Africa/Sao_Tome", "Africa/Sao_Tome"),
 | 
			
		||||
                    ("Africa/Timbuktu", "Africa/Timbuktu"),
 | 
			
		||||
                    ("Africa/Tripoli", "Africa/Tripoli"),
 | 
			
		||||
                    ("Africa/Tunis", "Africa/Tunis"),
 | 
			
		||||
                    ("Africa/Windhoek", "Africa/Windhoek"),
 | 
			
		||||
                    ("America/Adak", "America/Adak"),
 | 
			
		||||
                    ("America/Anchorage", "America/Anchorage"),
 | 
			
		||||
                    ("America/Anguilla", "America/Anguilla"),
 | 
			
		||||
                    ("America/Antigua", "America/Antigua"),
 | 
			
		||||
                    ("America/Araguaina", "America/Araguaina"),
 | 
			
		||||
                    (
 | 
			
		||||
                        "America/Argentina/Buenos_Aires",
 | 
			
		||||
                        "America/Argentina/Buenos_Aires",
 | 
			
		||||
                    ),
 | 
			
		||||
                    ("America/Argentina/Catamarca", "America/Argentina/Catamarca"),
 | 
			
		||||
                    (
 | 
			
		||||
                        "America/Argentina/ComodRivadavia",
 | 
			
		||||
                        "America/Argentina/ComodRivadavia",
 | 
			
		||||
                    ),
 | 
			
		||||
                    ("America/Argentina/Cordoba", "America/Argentina/Cordoba"),
 | 
			
		||||
                    ("America/Argentina/Jujuy", "America/Argentina/Jujuy"),
 | 
			
		||||
                    ("America/Argentina/La_Rioja", "America/Argentina/La_Rioja"),
 | 
			
		||||
                    ("America/Argentina/Mendoza", "America/Argentina/Mendoza"),
 | 
			
		||||
                    (
 | 
			
		||||
                        "America/Argentina/Rio_Gallegos",
 | 
			
		||||
                        "America/Argentina/Rio_Gallegos",
 | 
			
		||||
                    ),
 | 
			
		||||
                    ("America/Argentina/Salta", "America/Argentina/Salta"),
 | 
			
		||||
                    ("America/Argentina/San_Juan", "America/Argentina/San_Juan"),
 | 
			
		||||
                    ("America/Argentina/San_Luis", "America/Argentina/San_Luis"),
 | 
			
		||||
                    ("America/Argentina/Tucuman", "America/Argentina/Tucuman"),
 | 
			
		||||
                    ("America/Argentina/Ushuaia", "America/Argentina/Ushuaia"),
 | 
			
		||||
                    ("America/Aruba", "America/Aruba"),
 | 
			
		||||
                    ("America/Asuncion", "America/Asuncion"),
 | 
			
		||||
                    ("America/Atikokan", "America/Atikokan"),
 | 
			
		||||
                    ("America/Atka", "America/Atka"),
 | 
			
		||||
                    ("America/Bahia", "America/Bahia"),
 | 
			
		||||
                    ("America/Bahia_Banderas", "America/Bahia_Banderas"),
 | 
			
		||||
                    ("America/Barbados", "America/Barbados"),
 | 
			
		||||
                    ("America/Belem", "America/Belem"),
 | 
			
		||||
                    ("America/Belize", "America/Belize"),
 | 
			
		||||
                    ("America/Blanc-Sablon", "America/Blanc-Sablon"),
 | 
			
		||||
                    ("America/Boa_Vista", "America/Boa_Vista"),
 | 
			
		||||
                    ("America/Bogota", "America/Bogota"),
 | 
			
		||||
                    ("America/Boise", "America/Boise"),
 | 
			
		||||
                    ("America/Buenos_Aires", "America/Buenos_Aires"),
 | 
			
		||||
                    ("America/Cambridge_Bay", "America/Cambridge_Bay"),
 | 
			
		||||
                    ("America/Campo_Grande", "America/Campo_Grande"),
 | 
			
		||||
                    ("America/Cancun", "America/Cancun"),
 | 
			
		||||
                    ("America/Caracas", "America/Caracas"),
 | 
			
		||||
                    ("America/Catamarca", "America/Catamarca"),
 | 
			
		||||
                    ("America/Cayenne", "America/Cayenne"),
 | 
			
		||||
                    ("America/Cayman", "America/Cayman"),
 | 
			
		||||
                    ("America/Chicago", "America/Chicago"),
 | 
			
		||||
                    ("America/Chihuahua", "America/Chihuahua"),
 | 
			
		||||
                    ("America/Coral_Harbour", "America/Coral_Harbour"),
 | 
			
		||||
                    ("America/Cordoba", "America/Cordoba"),
 | 
			
		||||
                    ("America/Costa_Rica", "America/Costa_Rica"),
 | 
			
		||||
                    ("America/Creston", "America/Creston"),
 | 
			
		||||
                    ("America/Cuiaba", "America/Cuiaba"),
 | 
			
		||||
                    ("America/Curacao", "America/Curacao"),
 | 
			
		||||
                    ("America/Danmarkshavn", "America/Danmarkshavn"),
 | 
			
		||||
                    ("America/Dawson", "America/Dawson"),
 | 
			
		||||
                    ("America/Dawson_Creek", "America/Dawson_Creek"),
 | 
			
		||||
                    ("America/Denver", "America/Denver"),
 | 
			
		||||
                    ("America/Detroit", "America/Detroit"),
 | 
			
		||||
                    ("America/Dominica", "America/Dominica"),
 | 
			
		||||
                    ("America/Edmonton", "America/Edmonton"),
 | 
			
		||||
                    ("America/Eirunepe", "America/Eirunepe"),
 | 
			
		||||
                    ("America/El_Salvador", "America/El_Salvador"),
 | 
			
		||||
                    ("America/Ensenada", "America/Ensenada"),
 | 
			
		||||
                    ("America/Fort_Nelson", "America/Fort_Nelson"),
 | 
			
		||||
                    ("America/Fort_Wayne", "America/Fort_Wayne"),
 | 
			
		||||
                    ("America/Fortaleza", "America/Fortaleza"),
 | 
			
		||||
                    ("America/Glace_Bay", "America/Glace_Bay"),
 | 
			
		||||
                    ("America/Godthab", "America/Godthab"),
 | 
			
		||||
                    ("America/Goose_Bay", "America/Goose_Bay"),
 | 
			
		||||
                    ("America/Grand_Turk", "America/Grand_Turk"),
 | 
			
		||||
                    ("America/Grenada", "America/Grenada"),
 | 
			
		||||
                    ("America/Guadeloupe", "America/Guadeloupe"),
 | 
			
		||||
                    ("America/Guatemala", "America/Guatemala"),
 | 
			
		||||
                    ("America/Guayaquil", "America/Guayaquil"),
 | 
			
		||||
                    ("America/Guyana", "America/Guyana"),
 | 
			
		||||
                    ("America/Halifax", "America/Halifax"),
 | 
			
		||||
                    ("America/Havana", "America/Havana"),
 | 
			
		||||
                    ("America/Hermosillo", "America/Hermosillo"),
 | 
			
		||||
                    ("America/Indiana/Indianapolis", "America/Indiana/Indianapolis"),
 | 
			
		||||
                    ("America/Indiana/Knox", "America/Indiana/Knox"),
 | 
			
		||||
                    ("America/Indiana/Marengo", "America/Indiana/Marengo"),
 | 
			
		||||
                    ("America/Indiana/Petersburg", "America/Indiana/Petersburg"),
 | 
			
		||||
                    ("America/Indiana/Tell_City", "America/Indiana/Tell_City"),
 | 
			
		||||
                    ("America/Indiana/Vevay", "America/Indiana/Vevay"),
 | 
			
		||||
                    ("America/Indiana/Vincennes", "America/Indiana/Vincennes"),
 | 
			
		||||
                    ("America/Indiana/Winamac", "America/Indiana/Winamac"),
 | 
			
		||||
                    ("America/Indianapolis", "America/Indianapolis"),
 | 
			
		||||
                    ("America/Inuvik", "America/Inuvik"),
 | 
			
		||||
                    ("America/Iqaluit", "America/Iqaluit"),
 | 
			
		||||
                    ("America/Jamaica", "America/Jamaica"),
 | 
			
		||||
                    ("America/Jujuy", "America/Jujuy"),
 | 
			
		||||
                    ("America/Juneau", "America/Juneau"),
 | 
			
		||||
                    ("America/Kentucky/Louisville", "America/Kentucky/Louisville"),
 | 
			
		||||
                    ("America/Kentucky/Monticello", "America/Kentucky/Monticello"),
 | 
			
		||||
                    ("America/Knox_IN", "America/Knox_IN"),
 | 
			
		||||
                    ("America/Kralendijk", "America/Kralendijk"),
 | 
			
		||||
                    ("America/La_Paz", "America/La_Paz"),
 | 
			
		||||
                    ("America/Lima", "America/Lima"),
 | 
			
		||||
                    ("America/Los_Angeles", "America/Los_Angeles"),
 | 
			
		||||
                    ("America/Louisville", "America/Louisville"),
 | 
			
		||||
                    ("America/Lower_Princes", "America/Lower_Princes"),
 | 
			
		||||
                    ("America/Maceio", "America/Maceio"),
 | 
			
		||||
                    ("America/Managua", "America/Managua"),
 | 
			
		||||
                    ("America/Manaus", "America/Manaus"),
 | 
			
		||||
                    ("America/Marigot", "America/Marigot"),
 | 
			
		||||
                    ("America/Martinique", "America/Martinique"),
 | 
			
		||||
                    ("America/Matamoros", "America/Matamoros"),
 | 
			
		||||
                    ("America/Mazatlan", "America/Mazatlan"),
 | 
			
		||||
                    ("America/Mendoza", "America/Mendoza"),
 | 
			
		||||
                    ("America/Menominee", "America/Menominee"),
 | 
			
		||||
                    ("America/Merida", "America/Merida"),
 | 
			
		||||
                    ("America/Metlakatla", "America/Metlakatla"),
 | 
			
		||||
                    ("America/Mexico_City", "America/Mexico_City"),
 | 
			
		||||
                    ("America/Miquelon", "America/Miquelon"),
 | 
			
		||||
                    ("America/Moncton", "America/Moncton"),
 | 
			
		||||
                    ("America/Monterrey", "America/Monterrey"),
 | 
			
		||||
                    ("America/Montevideo", "America/Montevideo"),
 | 
			
		||||
                    ("America/Montreal", "America/Montreal"),
 | 
			
		||||
                    ("America/Montserrat", "America/Montserrat"),
 | 
			
		||||
                    ("America/Nassau", "America/Nassau"),
 | 
			
		||||
                    ("America/New_York", "America/New_York"),
 | 
			
		||||
                    ("America/Nipigon", "America/Nipigon"),
 | 
			
		||||
                    ("America/Nome", "America/Nome"),
 | 
			
		||||
                    ("America/Noronha", "America/Noronha"),
 | 
			
		||||
                    ("America/North_Dakota/Beulah", "America/North_Dakota/Beulah"),
 | 
			
		||||
                    ("America/North_Dakota/Center", "America/North_Dakota/Center"),
 | 
			
		||||
                    (
 | 
			
		||||
                        "America/North_Dakota/New_Salem",
 | 
			
		||||
                        "America/North_Dakota/New_Salem",
 | 
			
		||||
                    ),
 | 
			
		||||
                    ("America/Nuuk", "America/Nuuk"),
 | 
			
		||||
                    ("America/Ojinaga", "America/Ojinaga"),
 | 
			
		||||
                    ("America/Panama", "America/Panama"),
 | 
			
		||||
                    ("America/Pangnirtung", "America/Pangnirtung"),
 | 
			
		||||
                    ("America/Paramaribo", "America/Paramaribo"),
 | 
			
		||||
                    ("America/Phoenix", "America/Phoenix"),
 | 
			
		||||
                    ("America/Port-au-Prince", "America/Port-au-Prince"),
 | 
			
		||||
                    ("America/Port_of_Spain", "America/Port_of_Spain"),
 | 
			
		||||
                    ("America/Porto_Acre", "America/Porto_Acre"),
 | 
			
		||||
                    ("America/Porto_Velho", "America/Porto_Velho"),
 | 
			
		||||
                    ("America/Puerto_Rico", "America/Puerto_Rico"),
 | 
			
		||||
                    ("America/Punta_Arenas", "America/Punta_Arenas"),
 | 
			
		||||
                    ("America/Rainy_River", "America/Rainy_River"),
 | 
			
		||||
                    ("America/Rankin_Inlet", "America/Rankin_Inlet"),
 | 
			
		||||
                    ("America/Recife", "America/Recife"),
 | 
			
		||||
                    ("America/Regina", "America/Regina"),
 | 
			
		||||
                    ("America/Resolute", "America/Resolute"),
 | 
			
		||||
                    ("America/Rio_Branco", "America/Rio_Branco"),
 | 
			
		||||
                    ("America/Rosario", "America/Rosario"),
 | 
			
		||||
                    ("America/Santa_Isabel", "America/Santa_Isabel"),
 | 
			
		||||
                    ("America/Santarem", "America/Santarem"),
 | 
			
		||||
                    ("America/Santiago", "America/Santiago"),
 | 
			
		||||
                    ("America/Santo_Domingo", "America/Santo_Domingo"),
 | 
			
		||||
                    ("America/Sao_Paulo", "America/Sao_Paulo"),
 | 
			
		||||
                    ("America/Scoresbysund", "America/Scoresbysund"),
 | 
			
		||||
                    ("America/Shiprock", "America/Shiprock"),
 | 
			
		||||
                    ("America/Sitka", "America/Sitka"),
 | 
			
		||||
                    ("America/St_Barthelemy", "America/St_Barthelemy"),
 | 
			
		||||
                    ("America/St_Johns", "America/St_Johns"),
 | 
			
		||||
                    ("America/St_Kitts", "America/St_Kitts"),
 | 
			
		||||
                    ("America/St_Lucia", "America/St_Lucia"),
 | 
			
		||||
                    ("America/St_Thomas", "America/St_Thomas"),
 | 
			
		||||
                    ("America/St_Vincent", "America/St_Vincent"),
 | 
			
		||||
                    ("America/Swift_Current", "America/Swift_Current"),
 | 
			
		||||
                    ("America/Tegucigalpa", "America/Tegucigalpa"),
 | 
			
		||||
                    ("America/Thule", "America/Thule"),
 | 
			
		||||
                    ("America/Thunder_Bay", "America/Thunder_Bay"),
 | 
			
		||||
                    ("America/Tijuana", "America/Tijuana"),
 | 
			
		||||
                    ("America/Toronto", "America/Toronto"),
 | 
			
		||||
                    ("America/Tortola", "America/Tortola"),
 | 
			
		||||
                    ("America/Vancouver", "America/Vancouver"),
 | 
			
		||||
                    ("America/Virgin", "America/Virgin"),
 | 
			
		||||
                    ("America/Whitehorse", "America/Whitehorse"),
 | 
			
		||||
                    ("America/Winnipeg", "America/Winnipeg"),
 | 
			
		||||
                    ("America/Yakutat", "America/Yakutat"),
 | 
			
		||||
                    ("America/Yellowknife", "America/Yellowknife"),
 | 
			
		||||
                    ("Antarctica/Casey", "Antarctica/Casey"),
 | 
			
		||||
                    ("Antarctica/Davis", "Antarctica/Davis"),
 | 
			
		||||
                    ("Antarctica/DumontDUrville", "Antarctica/DumontDUrville"),
 | 
			
		||||
                    ("Antarctica/Macquarie", "Antarctica/Macquarie"),
 | 
			
		||||
                    ("Antarctica/Mawson", "Antarctica/Mawson"),
 | 
			
		||||
                    ("Antarctica/McMurdo", "Antarctica/McMurdo"),
 | 
			
		||||
                    ("Antarctica/Palmer", "Antarctica/Palmer"),
 | 
			
		||||
                    ("Antarctica/Rothera", "Antarctica/Rothera"),
 | 
			
		||||
                    ("Antarctica/South_Pole", "Antarctica/South_Pole"),
 | 
			
		||||
                    ("Antarctica/Syowa", "Antarctica/Syowa"),
 | 
			
		||||
                    ("Antarctica/Troll", "Antarctica/Troll"),
 | 
			
		||||
                    ("Antarctica/Vostok", "Antarctica/Vostok"),
 | 
			
		||||
                    ("Arctic/Longyearbyen", "Arctic/Longyearbyen"),
 | 
			
		||||
                    ("Asia/Aden", "Asia/Aden"),
 | 
			
		||||
                    ("Asia/Almaty", "Asia/Almaty"),
 | 
			
		||||
                    ("Asia/Amman", "Asia/Amman"),
 | 
			
		||||
                    ("Asia/Anadyr", "Asia/Anadyr"),
 | 
			
		||||
                    ("Asia/Aqtau", "Asia/Aqtau"),
 | 
			
		||||
                    ("Asia/Aqtobe", "Asia/Aqtobe"),
 | 
			
		||||
                    ("Asia/Ashgabat", "Asia/Ashgabat"),
 | 
			
		||||
                    ("Asia/Ashkhabad", "Asia/Ashkhabad"),
 | 
			
		||||
                    ("Asia/Atyrau", "Asia/Atyrau"),
 | 
			
		||||
                    ("Asia/Baghdad", "Asia/Baghdad"),
 | 
			
		||||
                    ("Asia/Bahrain", "Asia/Bahrain"),
 | 
			
		||||
                    ("Asia/Baku", "Asia/Baku"),
 | 
			
		||||
                    ("Asia/Bangkok", "Asia/Bangkok"),
 | 
			
		||||
                    ("Asia/Barnaul", "Asia/Barnaul"),
 | 
			
		||||
                    ("Asia/Beirut", "Asia/Beirut"),
 | 
			
		||||
                    ("Asia/Bishkek", "Asia/Bishkek"),
 | 
			
		||||
                    ("Asia/Brunei", "Asia/Brunei"),
 | 
			
		||||
                    ("Asia/Calcutta", "Asia/Calcutta"),
 | 
			
		||||
                    ("Asia/Chita", "Asia/Chita"),
 | 
			
		||||
                    ("Asia/Choibalsan", "Asia/Choibalsan"),
 | 
			
		||||
                    ("Asia/Chongqing", "Asia/Chongqing"),
 | 
			
		||||
                    ("Asia/Chungking", "Asia/Chungking"),
 | 
			
		||||
                    ("Asia/Colombo", "Asia/Colombo"),
 | 
			
		||||
                    ("Asia/Dacca", "Asia/Dacca"),
 | 
			
		||||
                    ("Asia/Damascus", "Asia/Damascus"),
 | 
			
		||||
                    ("Asia/Dhaka", "Asia/Dhaka"),
 | 
			
		||||
                    ("Asia/Dili", "Asia/Dili"),
 | 
			
		||||
                    ("Asia/Dubai", "Asia/Dubai"),
 | 
			
		||||
                    ("Asia/Dushanbe", "Asia/Dushanbe"),
 | 
			
		||||
                    ("Asia/Famagusta", "Asia/Famagusta"),
 | 
			
		||||
                    ("Asia/Gaza", "Asia/Gaza"),
 | 
			
		||||
                    ("Asia/Harbin", "Asia/Harbin"),
 | 
			
		||||
                    ("Asia/Hebron", "Asia/Hebron"),
 | 
			
		||||
                    ("Asia/Ho_Chi_Minh", "Asia/Ho_Chi_Minh"),
 | 
			
		||||
                    ("Asia/Hong_Kong", "Asia/Hong_Kong"),
 | 
			
		||||
                    ("Asia/Hovd", "Asia/Hovd"),
 | 
			
		||||
                    ("Asia/Irkutsk", "Asia/Irkutsk"),
 | 
			
		||||
                    ("Asia/Istanbul", "Asia/Istanbul"),
 | 
			
		||||
                    ("Asia/Jakarta", "Asia/Jakarta"),
 | 
			
		||||
                    ("Asia/Jayapura", "Asia/Jayapura"),
 | 
			
		||||
                    ("Asia/Jerusalem", "Asia/Jerusalem"),
 | 
			
		||||
                    ("Asia/Kabul", "Asia/Kabul"),
 | 
			
		||||
                    ("Asia/Kamchatka", "Asia/Kamchatka"),
 | 
			
		||||
                    ("Asia/Karachi", "Asia/Karachi"),
 | 
			
		||||
                    ("Asia/Kashgar", "Asia/Kashgar"),
 | 
			
		||||
                    ("Asia/Kathmandu", "Asia/Kathmandu"),
 | 
			
		||||
                    ("Asia/Katmandu", "Asia/Katmandu"),
 | 
			
		||||
                    ("Asia/Khandyga", "Asia/Khandyga"),
 | 
			
		||||
                    ("Asia/Kolkata", "Asia/Kolkata"),
 | 
			
		||||
                    ("Asia/Krasnoyarsk", "Asia/Krasnoyarsk"),
 | 
			
		||||
                    ("Asia/Kuala_Lumpur", "Asia/Kuala_Lumpur"),
 | 
			
		||||
                    ("Asia/Kuching", "Asia/Kuching"),
 | 
			
		||||
                    ("Asia/Kuwait", "Asia/Kuwait"),
 | 
			
		||||
                    ("Asia/Macao", "Asia/Macao"),
 | 
			
		||||
                    ("Asia/Macau", "Asia/Macau"),
 | 
			
		||||
                    ("Asia/Magadan", "Asia/Magadan"),
 | 
			
		||||
                    ("Asia/Makassar", "Asia/Makassar"),
 | 
			
		||||
                    ("Asia/Manila", "Asia/Manila"),
 | 
			
		||||
                    ("Asia/Muscat", "Asia/Muscat"),
 | 
			
		||||
                    ("Asia/Nicosia", "Asia/Nicosia"),
 | 
			
		||||
                    ("Asia/Novokuznetsk", "Asia/Novokuznetsk"),
 | 
			
		||||
                    ("Asia/Novosibirsk", "Asia/Novosibirsk"),
 | 
			
		||||
                    ("Asia/Omsk", "Asia/Omsk"),
 | 
			
		||||
                    ("Asia/Oral", "Asia/Oral"),
 | 
			
		||||
                    ("Asia/Phnom_Penh", "Asia/Phnom_Penh"),
 | 
			
		||||
                    ("Asia/Pontianak", "Asia/Pontianak"),
 | 
			
		||||
                    ("Asia/Pyongyang", "Asia/Pyongyang"),
 | 
			
		||||
                    ("Asia/Qatar", "Asia/Qatar"),
 | 
			
		||||
                    ("Asia/Qostanay", "Asia/Qostanay"),
 | 
			
		||||
                    ("Asia/Qyzylorda", "Asia/Qyzylorda"),
 | 
			
		||||
                    ("Asia/Rangoon", "Asia/Rangoon"),
 | 
			
		||||
                    ("Asia/Riyadh", "Asia/Riyadh"),
 | 
			
		||||
                    ("Asia/Saigon", "Asia/Saigon"),
 | 
			
		||||
                    ("Asia/Sakhalin", "Asia/Sakhalin"),
 | 
			
		||||
                    ("Asia/Samarkand", "Asia/Samarkand"),
 | 
			
		||||
                    ("Asia/Seoul", "Asia/Seoul"),
 | 
			
		||||
                    ("Asia/Shanghai", "Asia/Shanghai"),
 | 
			
		||||
                    ("Asia/Singapore", "Asia/Singapore"),
 | 
			
		||||
                    ("Asia/Srednekolymsk", "Asia/Srednekolymsk"),
 | 
			
		||||
                    ("Asia/Taipei", "Asia/Taipei"),
 | 
			
		||||
                    ("Asia/Tashkent", "Asia/Tashkent"),
 | 
			
		||||
                    ("Asia/Tbilisi", "Asia/Tbilisi"),
 | 
			
		||||
                    ("Asia/Tehran", "Asia/Tehran"),
 | 
			
		||||
                    ("Asia/Tel_Aviv", "Asia/Tel_Aviv"),
 | 
			
		||||
                    ("Asia/Thimbu", "Asia/Thimbu"),
 | 
			
		||||
                    ("Asia/Thimphu", "Asia/Thimphu"),
 | 
			
		||||
                    ("Asia/Tokyo", "Asia/Tokyo"),
 | 
			
		||||
                    ("Asia/Tomsk", "Asia/Tomsk"),
 | 
			
		||||
                    ("Asia/Ujung_Pandang", "Asia/Ujung_Pandang"),
 | 
			
		||||
                    ("Asia/Ulaanbaatar", "Asia/Ulaanbaatar"),
 | 
			
		||||
                    ("Asia/Ulan_Bator", "Asia/Ulan_Bator"),
 | 
			
		||||
                    ("Asia/Urumqi", "Asia/Urumqi"),
 | 
			
		||||
                    ("Asia/Ust-Nera", "Asia/Ust-Nera"),
 | 
			
		||||
                    ("Asia/Vientiane", "Asia/Vientiane"),
 | 
			
		||||
                    ("Asia/Vladivostok", "Asia/Vladivostok"),
 | 
			
		||||
                    ("Asia/Yakutsk", "Asia/Yakutsk"),
 | 
			
		||||
                    ("Asia/Yangon", "Asia/Yangon"),
 | 
			
		||||
                    ("Asia/Yekaterinburg", "Asia/Yekaterinburg"),
 | 
			
		||||
                    ("Asia/Yerevan", "Asia/Yerevan"),
 | 
			
		||||
                    ("Atlantic/Azores", "Atlantic/Azores"),
 | 
			
		||||
                    ("Atlantic/Bermuda", "Atlantic/Bermuda"),
 | 
			
		||||
                    ("Atlantic/Canary", "Atlantic/Canary"),
 | 
			
		||||
                    ("Atlantic/Cape_Verde", "Atlantic/Cape_Verde"),
 | 
			
		||||
                    ("Atlantic/Faeroe", "Atlantic/Faeroe"),
 | 
			
		||||
                    ("Atlantic/Faroe", "Atlantic/Faroe"),
 | 
			
		||||
                    ("Atlantic/Jan_Mayen", "Atlantic/Jan_Mayen"),
 | 
			
		||||
                    ("Atlantic/Madeira", "Atlantic/Madeira"),
 | 
			
		||||
                    ("Atlantic/Reykjavik", "Atlantic/Reykjavik"),
 | 
			
		||||
                    ("Atlantic/South_Georgia", "Atlantic/South_Georgia"),
 | 
			
		||||
                    ("Atlantic/St_Helena", "Atlantic/St_Helena"),
 | 
			
		||||
                    ("Atlantic/Stanley", "Atlantic/Stanley"),
 | 
			
		||||
                    ("Australia/ACT", "Australia/ACT"),
 | 
			
		||||
                    ("Australia/Adelaide", "Australia/Adelaide"),
 | 
			
		||||
                    ("Australia/Brisbane", "Australia/Brisbane"),
 | 
			
		||||
                    ("Australia/Broken_Hill", "Australia/Broken_Hill"),
 | 
			
		||||
                    ("Australia/Canberra", "Australia/Canberra"),
 | 
			
		||||
                    ("Australia/Currie", "Australia/Currie"),
 | 
			
		||||
                    ("Australia/Darwin", "Australia/Darwin"),
 | 
			
		||||
                    ("Australia/Eucla", "Australia/Eucla"),
 | 
			
		||||
                    ("Australia/Hobart", "Australia/Hobart"),
 | 
			
		||||
                    ("Australia/LHI", "Australia/LHI"),
 | 
			
		||||
                    ("Australia/Lindeman", "Australia/Lindeman"),
 | 
			
		||||
                    ("Australia/Lord_Howe", "Australia/Lord_Howe"),
 | 
			
		||||
                    ("Australia/Melbourne", "Australia/Melbourne"),
 | 
			
		||||
                    ("Australia/NSW", "Australia/NSW"),
 | 
			
		||||
                    ("Australia/North", "Australia/North"),
 | 
			
		||||
                    ("Australia/Perth", "Australia/Perth"),
 | 
			
		||||
                    ("Australia/Queensland", "Australia/Queensland"),
 | 
			
		||||
                    ("Australia/South", "Australia/South"),
 | 
			
		||||
                    ("Australia/Sydney", "Australia/Sydney"),
 | 
			
		||||
                    ("Australia/Tasmania", "Australia/Tasmania"),
 | 
			
		||||
                    ("Australia/Victoria", "Australia/Victoria"),
 | 
			
		||||
                    ("Australia/West", "Australia/West"),
 | 
			
		||||
                    ("Australia/Yancowinna", "Australia/Yancowinna"),
 | 
			
		||||
                    ("Brazil/Acre", "Brazil/Acre"),
 | 
			
		||||
                    ("Brazil/DeNoronha", "Brazil/DeNoronha"),
 | 
			
		||||
                    ("Brazil/East", "Brazil/East"),
 | 
			
		||||
                    ("Brazil/West", "Brazil/West"),
 | 
			
		||||
                    ("CET", "CET"),
 | 
			
		||||
                    ("CST6CDT", "CST6CDT"),
 | 
			
		||||
                    ("Canada/Atlantic", "Canada/Atlantic"),
 | 
			
		||||
                    ("Canada/Central", "Canada/Central"),
 | 
			
		||||
                    ("Canada/Eastern", "Canada/Eastern"),
 | 
			
		||||
                    ("Canada/Mountain", "Canada/Mountain"),
 | 
			
		||||
                    ("Canada/Newfoundland", "Canada/Newfoundland"),
 | 
			
		||||
                    ("Canada/Pacific", "Canada/Pacific"),
 | 
			
		||||
                    ("Canada/Saskatchewan", "Canada/Saskatchewan"),
 | 
			
		||||
                    ("Canada/Yukon", "Canada/Yukon"),
 | 
			
		||||
                    ("Chile/Continental", "Chile/Continental"),
 | 
			
		||||
                    ("Chile/EasterIsland", "Chile/EasterIsland"),
 | 
			
		||||
                    ("Cuba", "Cuba"),
 | 
			
		||||
                    ("EET", "EET"),
 | 
			
		||||
                    ("EST", "EST"),
 | 
			
		||||
                    ("EST5EDT", "EST5EDT"),
 | 
			
		||||
                    ("Egypt", "Egypt"),
 | 
			
		||||
                    ("Eire", "Eire"),
 | 
			
		||||
                    ("Etc/GMT", "Etc/GMT"),
 | 
			
		||||
                    ("Etc/GMT+0", "Etc/GMT+0"),
 | 
			
		||||
                    ("Etc/GMT+1", "Etc/GMT+1"),
 | 
			
		||||
                    ("Etc/GMT+10", "Etc/GMT+10"),
 | 
			
		||||
                    ("Etc/GMT+11", "Etc/GMT+11"),
 | 
			
		||||
                    ("Etc/GMT+12", "Etc/GMT+12"),
 | 
			
		||||
                    ("Etc/GMT+2", "Etc/GMT+2"),
 | 
			
		||||
                    ("Etc/GMT+3", "Etc/GMT+3"),
 | 
			
		||||
                    ("Etc/GMT+4", "Etc/GMT+4"),
 | 
			
		||||
                    ("Etc/GMT+5", "Etc/GMT+5"),
 | 
			
		||||
                    ("Etc/GMT+6", "Etc/GMT+6"),
 | 
			
		||||
                    ("Etc/GMT+7", "Etc/GMT+7"),
 | 
			
		||||
                    ("Etc/GMT+8", "Etc/GMT+8"),
 | 
			
		||||
                    ("Etc/GMT+9", "Etc/GMT+9"),
 | 
			
		||||
                    ("Etc/GMT-0", "Etc/GMT-0"),
 | 
			
		||||
                    ("Etc/GMT-1", "Etc/GMT-1"),
 | 
			
		||||
                    ("Etc/GMT-10", "Etc/GMT-10"),
 | 
			
		||||
                    ("Etc/GMT-11", "Etc/GMT-11"),
 | 
			
		||||
                    ("Etc/GMT-12", "Etc/GMT-12"),
 | 
			
		||||
                    ("Etc/GMT-13", "Etc/GMT-13"),
 | 
			
		||||
                    ("Etc/GMT-14", "Etc/GMT-14"),
 | 
			
		||||
                    ("Etc/GMT-2", "Etc/GMT-2"),
 | 
			
		||||
                    ("Etc/GMT-3", "Etc/GMT-3"),
 | 
			
		||||
                    ("Etc/GMT-4", "Etc/GMT-4"),
 | 
			
		||||
                    ("Etc/GMT-5", "Etc/GMT-5"),
 | 
			
		||||
                    ("Etc/GMT-6", "Etc/GMT-6"),
 | 
			
		||||
                    ("Etc/GMT-7", "Etc/GMT-7"),
 | 
			
		||||
                    ("Etc/GMT-8", "Etc/GMT-8"),
 | 
			
		||||
                    ("Etc/GMT-9", "Etc/GMT-9"),
 | 
			
		||||
                    ("Etc/GMT0", "Etc/GMT0"),
 | 
			
		||||
                    ("Etc/Greenwich", "Etc/Greenwich"),
 | 
			
		||||
                    ("Etc/UCT", "Etc/UCT"),
 | 
			
		||||
                    ("Etc/UTC", "Etc/UTC"),
 | 
			
		||||
                    ("Etc/Universal", "Etc/Universal"),
 | 
			
		||||
                    ("Etc/Zulu", "Etc/Zulu"),
 | 
			
		||||
                    ("Europe/Amsterdam", "Europe/Amsterdam"),
 | 
			
		||||
                    ("Europe/Andorra", "Europe/Andorra"),
 | 
			
		||||
                    ("Europe/Astrakhan", "Europe/Astrakhan"),
 | 
			
		||||
                    ("Europe/Athens", "Europe/Athens"),
 | 
			
		||||
                    ("Europe/Belfast", "Europe/Belfast"),
 | 
			
		||||
                    ("Europe/Belgrade", "Europe/Belgrade"),
 | 
			
		||||
                    ("Europe/Berlin", "Europe/Berlin"),
 | 
			
		||||
                    ("Europe/Bratislava", "Europe/Bratislava"),
 | 
			
		||||
                    ("Europe/Brussels", "Europe/Brussels"),
 | 
			
		||||
                    ("Europe/Bucharest", "Europe/Bucharest"),
 | 
			
		||||
                    ("Europe/Budapest", "Europe/Budapest"),
 | 
			
		||||
                    ("Europe/Busingen", "Europe/Busingen"),
 | 
			
		||||
                    ("Europe/Chisinau", "Europe/Chisinau"),
 | 
			
		||||
                    ("Europe/Copenhagen", "Europe/Copenhagen"),
 | 
			
		||||
                    ("Europe/Dublin", "Europe/Dublin"),
 | 
			
		||||
                    ("Europe/Gibraltar", "Europe/Gibraltar"),
 | 
			
		||||
                    ("Europe/Guernsey", "Europe/Guernsey"),
 | 
			
		||||
                    ("Europe/Helsinki", "Europe/Helsinki"),
 | 
			
		||||
                    ("Europe/Isle_of_Man", "Europe/Isle_of_Man"),
 | 
			
		||||
                    ("Europe/Istanbul", "Europe/Istanbul"),
 | 
			
		||||
                    ("Europe/Jersey", "Europe/Jersey"),
 | 
			
		||||
                    ("Europe/Kaliningrad", "Europe/Kaliningrad"),
 | 
			
		||||
                    ("Europe/Kiev", "Europe/Kiev"),
 | 
			
		||||
                    ("Europe/Kirov", "Europe/Kirov"),
 | 
			
		||||
                    ("Europe/Kyiv", "Europe/Kyiv"),
 | 
			
		||||
                    ("Europe/Lisbon", "Europe/Lisbon"),
 | 
			
		||||
                    ("Europe/Ljubljana", "Europe/Ljubljana"),
 | 
			
		||||
                    ("Europe/London", "Europe/London"),
 | 
			
		||||
                    ("Europe/Luxembourg", "Europe/Luxembourg"),
 | 
			
		||||
                    ("Europe/Madrid", "Europe/Madrid"),
 | 
			
		||||
                    ("Europe/Malta", "Europe/Malta"),
 | 
			
		||||
                    ("Europe/Mariehamn", "Europe/Mariehamn"),
 | 
			
		||||
                    ("Europe/Minsk", "Europe/Minsk"),
 | 
			
		||||
                    ("Europe/Monaco", "Europe/Monaco"),
 | 
			
		||||
                    ("Europe/Moscow", "Europe/Moscow"),
 | 
			
		||||
                    ("Europe/Nicosia", "Europe/Nicosia"),
 | 
			
		||||
                    ("Europe/Oslo", "Europe/Oslo"),
 | 
			
		||||
                    ("Europe/Paris", "Europe/Paris"),
 | 
			
		||||
                    ("Europe/Podgorica", "Europe/Podgorica"),
 | 
			
		||||
                    ("Europe/Prague", "Europe/Prague"),
 | 
			
		||||
                    ("Europe/Riga", "Europe/Riga"),
 | 
			
		||||
                    ("Europe/Rome", "Europe/Rome"),
 | 
			
		||||
                    ("Europe/Samara", "Europe/Samara"),
 | 
			
		||||
                    ("Europe/San_Marino", "Europe/San_Marino"),
 | 
			
		||||
                    ("Europe/Sarajevo", "Europe/Sarajevo"),
 | 
			
		||||
                    ("Europe/Saratov", "Europe/Saratov"),
 | 
			
		||||
                    ("Europe/Simferopol", "Europe/Simferopol"),
 | 
			
		||||
                    ("Europe/Skopje", "Europe/Skopje"),
 | 
			
		||||
                    ("Europe/Sofia", "Europe/Sofia"),
 | 
			
		||||
                    ("Europe/Stockholm", "Europe/Stockholm"),
 | 
			
		||||
                    ("Europe/Tallinn", "Europe/Tallinn"),
 | 
			
		||||
                    ("Europe/Tirane", "Europe/Tirane"),
 | 
			
		||||
                    ("Europe/Tiraspol", "Europe/Tiraspol"),
 | 
			
		||||
                    ("Europe/Ulyanovsk", "Europe/Ulyanovsk"),
 | 
			
		||||
                    ("Europe/Uzhgorod", "Europe/Uzhgorod"),
 | 
			
		||||
                    ("Europe/Vaduz", "Europe/Vaduz"),
 | 
			
		||||
                    ("Europe/Vatican", "Europe/Vatican"),
 | 
			
		||||
                    ("Europe/Vienna", "Europe/Vienna"),
 | 
			
		||||
                    ("Europe/Vilnius", "Europe/Vilnius"),
 | 
			
		||||
                    ("Europe/Volgograd", "Europe/Volgograd"),
 | 
			
		||||
                    ("Europe/Warsaw", "Europe/Warsaw"),
 | 
			
		||||
                    ("Europe/Zagreb", "Europe/Zagreb"),
 | 
			
		||||
                    ("Europe/Zaporozhye", "Europe/Zaporozhye"),
 | 
			
		||||
                    ("Europe/Zurich", "Europe/Zurich"),
 | 
			
		||||
                    ("GB", "GB"),
 | 
			
		||||
                    ("GB-Eire", "GB-Eire"),
 | 
			
		||||
                    ("GMT", "GMT"),
 | 
			
		||||
                    ("GMT+0", "GMT+0"),
 | 
			
		||||
                    ("GMT-0", "GMT-0"),
 | 
			
		||||
                    ("GMT0", "GMT0"),
 | 
			
		||||
                    ("Greenwich", "Greenwich"),
 | 
			
		||||
                    ("HST", "HST"),
 | 
			
		||||
                    ("Hongkong", "Hongkong"),
 | 
			
		||||
                    ("Iceland", "Iceland"),
 | 
			
		||||
                    ("Indian/Antananarivo", "Indian/Antananarivo"),
 | 
			
		||||
                    ("Indian/Chagos", "Indian/Chagos"),
 | 
			
		||||
                    ("Indian/Christmas", "Indian/Christmas"),
 | 
			
		||||
                    ("Indian/Cocos", "Indian/Cocos"),
 | 
			
		||||
                    ("Indian/Comoro", "Indian/Comoro"),
 | 
			
		||||
                    ("Indian/Kerguelen", "Indian/Kerguelen"),
 | 
			
		||||
                    ("Indian/Mahe", "Indian/Mahe"),
 | 
			
		||||
                    ("Indian/Maldives", "Indian/Maldives"),
 | 
			
		||||
                    ("Indian/Mauritius", "Indian/Mauritius"),
 | 
			
		||||
                    ("Indian/Mayotte", "Indian/Mayotte"),
 | 
			
		||||
                    ("Indian/Reunion", "Indian/Reunion"),
 | 
			
		||||
                    ("Iran", "Iran"),
 | 
			
		||||
                    ("Israel", "Israel"),
 | 
			
		||||
                    ("Jamaica", "Jamaica"),
 | 
			
		||||
                    ("Japan", "Japan"),
 | 
			
		||||
                    ("Kwajalein", "Kwajalein"),
 | 
			
		||||
                    ("Libya", "Libya"),
 | 
			
		||||
                    ("MET", "MET"),
 | 
			
		||||
                    ("MST", "MST"),
 | 
			
		||||
                    ("MST7MDT", "MST7MDT"),
 | 
			
		||||
                    ("Mexico/BajaNorte", "Mexico/BajaNorte"),
 | 
			
		||||
                    ("Mexico/BajaSur", "Mexico/BajaSur"),
 | 
			
		||||
                    ("Mexico/General", "Mexico/General"),
 | 
			
		||||
                    ("NZ", "NZ"),
 | 
			
		||||
                    ("NZ-CHAT", "NZ-CHAT"),
 | 
			
		||||
                    ("Navajo", "Navajo"),
 | 
			
		||||
                    ("PRC", "PRC"),
 | 
			
		||||
                    ("PST8PDT", "PST8PDT"),
 | 
			
		||||
                    ("Pacific/Apia", "Pacific/Apia"),
 | 
			
		||||
                    ("Pacific/Auckland", "Pacific/Auckland"),
 | 
			
		||||
                    ("Pacific/Bougainville", "Pacific/Bougainville"),
 | 
			
		||||
                    ("Pacific/Chatham", "Pacific/Chatham"),
 | 
			
		||||
                    ("Pacific/Chuuk", "Pacific/Chuuk"),
 | 
			
		||||
                    ("Pacific/Easter", "Pacific/Easter"),
 | 
			
		||||
                    ("Pacific/Efate", "Pacific/Efate"),
 | 
			
		||||
                    ("Pacific/Enderbury", "Pacific/Enderbury"),
 | 
			
		||||
                    ("Pacific/Fakaofo", "Pacific/Fakaofo"),
 | 
			
		||||
                    ("Pacific/Fiji", "Pacific/Fiji"),
 | 
			
		||||
                    ("Pacific/Funafuti", "Pacific/Funafuti"),
 | 
			
		||||
                    ("Pacific/Galapagos", "Pacific/Galapagos"),
 | 
			
		||||
                    ("Pacific/Gambier", "Pacific/Gambier"),
 | 
			
		||||
                    ("Pacific/Guadalcanal", "Pacific/Guadalcanal"),
 | 
			
		||||
                    ("Pacific/Guam", "Pacific/Guam"),
 | 
			
		||||
                    ("Pacific/Honolulu", "Pacific/Honolulu"),
 | 
			
		||||
                    ("Pacific/Johnston", "Pacific/Johnston"),
 | 
			
		||||
                    ("Pacific/Kanton", "Pacific/Kanton"),
 | 
			
		||||
                    ("Pacific/Kiritimati", "Pacific/Kiritimati"),
 | 
			
		||||
                    ("Pacific/Kosrae", "Pacific/Kosrae"),
 | 
			
		||||
                    ("Pacific/Kwajalein", "Pacific/Kwajalein"),
 | 
			
		||||
                    ("Pacific/Majuro", "Pacific/Majuro"),
 | 
			
		||||
                    ("Pacific/Marquesas", "Pacific/Marquesas"),
 | 
			
		||||
                    ("Pacific/Midway", "Pacific/Midway"),
 | 
			
		||||
                    ("Pacific/Nauru", "Pacific/Nauru"),
 | 
			
		||||
                    ("Pacific/Niue", "Pacific/Niue"),
 | 
			
		||||
                    ("Pacific/Norfolk", "Pacific/Norfolk"),
 | 
			
		||||
                    ("Pacific/Noumea", "Pacific/Noumea"),
 | 
			
		||||
                    ("Pacific/Pago_Pago", "Pacific/Pago_Pago"),
 | 
			
		||||
                    ("Pacific/Palau", "Pacific/Palau"),
 | 
			
		||||
                    ("Pacific/Pitcairn", "Pacific/Pitcairn"),
 | 
			
		||||
                    ("Pacific/Pohnpei", "Pacific/Pohnpei"),
 | 
			
		||||
                    ("Pacific/Ponape", "Pacific/Ponape"),
 | 
			
		||||
                    ("Pacific/Port_Moresby", "Pacific/Port_Moresby"),
 | 
			
		||||
                    ("Pacific/Rarotonga", "Pacific/Rarotonga"),
 | 
			
		||||
                    ("Pacific/Saipan", "Pacific/Saipan"),
 | 
			
		||||
                    ("Pacific/Samoa", "Pacific/Samoa"),
 | 
			
		||||
                    ("Pacific/Tahiti", "Pacific/Tahiti"),
 | 
			
		||||
                    ("Pacific/Tarawa", "Pacific/Tarawa"),
 | 
			
		||||
                    ("Pacific/Tongatapu", "Pacific/Tongatapu"),
 | 
			
		||||
                    ("Pacific/Truk", "Pacific/Truk"),
 | 
			
		||||
                    ("Pacific/Wake", "Pacific/Wake"),
 | 
			
		||||
                    ("Pacific/Wallis", "Pacific/Wallis"),
 | 
			
		||||
                    ("Pacific/Yap", "Pacific/Yap"),
 | 
			
		||||
                    ("Poland", "Poland"),
 | 
			
		||||
                    ("Portugal", "Portugal"),
 | 
			
		||||
                    ("ROC", "ROC"),
 | 
			
		||||
                    ("ROK", "ROK"),
 | 
			
		||||
                    ("Singapore", "Singapore"),
 | 
			
		||||
                    ("Turkey", "Turkey"),
 | 
			
		||||
                    ("UCT", "UCT"),
 | 
			
		||||
                    ("US/Alaska", "US/Alaska"),
 | 
			
		||||
                    ("US/Aleutian", "US/Aleutian"),
 | 
			
		||||
                    ("US/Arizona", "US/Arizona"),
 | 
			
		||||
                    ("US/Central", "US/Central"),
 | 
			
		||||
                    ("US/East-Indiana", "US/East-Indiana"),
 | 
			
		||||
                    ("US/Eastern", "US/Eastern"),
 | 
			
		||||
                    ("US/Hawaii", "US/Hawaii"),
 | 
			
		||||
                    ("US/Indiana-Starke", "US/Indiana-Starke"),
 | 
			
		||||
                    ("US/Michigan", "US/Michigan"),
 | 
			
		||||
                    ("US/Mountain", "US/Mountain"),
 | 
			
		||||
                    ("US/Pacific", "US/Pacific"),
 | 
			
		||||
                    ("US/Samoa", "US/Samoa"),
 | 
			
		||||
                    ("UTC", "UTC"),
 | 
			
		||||
                    ("Universal", "Universal"),
 | 
			
		||||
                    ("W-SU", "W-SU"),
 | 
			
		||||
                    ("WET", "WET"),
 | 
			
		||||
                    ("Zulu", "Zulu"),
 | 
			
		||||
                ],
 | 
			
		||||
                max_length=255,
 | 
			
		||||
                null=True,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -748,10 +748,10 @@ class Agent(BaseAuditModel):
 | 
			
		||||
            cache_key = f"agent_{self.agent_id}_checks"
 | 
			
		||||
 | 
			
		||||
        elif self.policy:
 | 
			
		||||
            cache_key = f"site_{self.monitoring_type}_{self.site_id}_policy_{self.policy_id}_checks"
 | 
			
		||||
            cache_key = f"site_{self.monitoring_type}_{self.plat}_{self.site_id}_policy_{self.policy_id}_checks"
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            cache_key = f"site_{self.monitoring_type}_{self.site_id}_checks"
 | 
			
		||||
            cache_key = f"site_{self.monitoring_type}_{self.plat}_{self.site_id}_checks"
 | 
			
		||||
 | 
			
		||||
        cached_checks = cache.get(cache_key)
 | 
			
		||||
        if isinstance(cached_checks, list):
 | 
			
		||||
@@ -773,10 +773,10 @@ class Agent(BaseAuditModel):
 | 
			
		||||
            cache_key = f"agent_{self.agent_id}_tasks"
 | 
			
		||||
 | 
			
		||||
        elif self.policy:
 | 
			
		||||
            cache_key = f"site_{self.monitoring_type}_{self.site_id}_policy_{self.policy_id}_tasks"
 | 
			
		||||
            cache_key = f"site_{self.monitoring_type}_{self.plat}_{self.site_id}_policy_{self.policy_id}_tasks"
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            cache_key = f"site_{self.monitoring_type}_{self.site_id}_tasks"
 | 
			
		||||
            cache_key = f"site_{self.monitoring_type}_{self.plat}_{self.site_id}_tasks"
 | 
			
		||||
 | 
			
		||||
        cached_tasks = cache.get(cache_key)
 | 
			
		||||
        if isinstance(cached_tasks, list):
 | 
			
		||||
@@ -784,7 +784,7 @@ class Agent(BaseAuditModel):
 | 
			
		||||
        else:
 | 
			
		||||
            # get agent tasks based on policies
 | 
			
		||||
            tasks = Policy.get_policy_tasks(self)
 | 
			
		||||
            cache.set(f"site_{self.site_id}_tasks", tasks, 600)
 | 
			
		||||
            cache.set(cache_key, tasks, 600)
 | 
			
		||||
            return tasks
 | 
			
		||||
 | 
			
		||||
    def _do_nats_debug(self, agent: "Agent", message: str) -> None:
 | 
			
		||||
@@ -845,22 +845,22 @@ class Agent(BaseAuditModel):
 | 
			
		||||
            asyncio.run(
 | 
			
		||||
                send_command_with_mesh(cmd, mesh_uri, self.mesh_node_id, shell, 0)
 | 
			
		||||
            )
 | 
			
		||||
            return ("ok", False)
 | 
			
		||||
            return "ok", False
 | 
			
		||||
 | 
			
		||||
        elif mode == "mesh":
 | 
			
		||||
            data = {"func": "recover", "payload": {"mode": mode}}
 | 
			
		||||
            if wait:
 | 
			
		||||
                r = asyncio.run(self.nats_cmd(data, timeout=20))
 | 
			
		||||
                if r == "ok":
 | 
			
		||||
                    return ("ok", False)
 | 
			
		||||
                    return "ok", False
 | 
			
		||||
                else:
 | 
			
		||||
                    return (str(r), True)
 | 
			
		||||
                    return str(r), True
 | 
			
		||||
            else:
 | 
			
		||||
                asyncio.run(self.nats_cmd(data, timeout=20, wait=False))
 | 
			
		||||
 | 
			
		||||
            return ("ok", False)
 | 
			
		||||
            return "ok", False
 | 
			
		||||
 | 
			
		||||
        return ("invalid", True)
 | 
			
		||||
        return "invalid", True
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def serialize(agent: "Agent") -> Dict[str, Any]:
 | 
			
		||||
 
 | 
			
		||||
@@ -90,6 +90,11 @@ class AgentTableSerializer(serializers.ModelSerializer):
 | 
			
		||||
    last_seen = serializers.ReadOnlyField()
 | 
			
		||||
    pending_actions_count = serializers.ReadOnlyField()
 | 
			
		||||
    has_patches_pending = serializers.ReadOnlyField()
 | 
			
		||||
    cpu_model = serializers.ReadOnlyField()
 | 
			
		||||
    graphics = serializers.ReadOnlyField()
 | 
			
		||||
    local_ips = serializers.ReadOnlyField()
 | 
			
		||||
    make_model = serializers.ReadOnlyField()
 | 
			
		||||
    physical_disks = serializers.ReadOnlyField()
 | 
			
		||||
 | 
			
		||||
    def get_alert_template(self, obj):
 | 
			
		||||
 | 
			
		||||
@@ -141,16 +146,18 @@ class AgentTableSerializer(serializers.ModelSerializer):
 | 
			
		||||
            "plat",
 | 
			
		||||
            "goarch",
 | 
			
		||||
            "has_patches_pending",
 | 
			
		||||
            "version",
 | 
			
		||||
            "operating_system",
 | 
			
		||||
            "public_ip",
 | 
			
		||||
            "cpu_model",
 | 
			
		||||
            "graphics",
 | 
			
		||||
            "local_ips",
 | 
			
		||||
            "make_model",
 | 
			
		||||
            "physical_disks",
 | 
			
		||||
        ]
 | 
			
		||||
        depth = 2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class WinAgentSerializer(serializers.ModelSerializer):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Agent
 | 
			
		||||
        fields = "__all__"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AgentHostnameSerializer(serializers.ModelSerializer):
 | 
			
		||||
    client = serializers.ReadOnlyField(source="client.name")
 | 
			
		||||
    site = serializers.ReadOnlyField(source="site.name")
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ class TestAgentUpdate(TacticalTestCase):
 | 
			
		||||
            site=self.site1,
 | 
			
		||||
            monitoring_type=AgentMonType.SERVER,
 | 
			
		||||
            plat=AgentPlat.WINDOWS,
 | 
			
		||||
            version="2.3.0",
 | 
			
		||||
            version="2.1.1",
 | 
			
		||||
        )
 | 
			
		||||
        r = agent_noarch.do_update(token="", force=True)
 | 
			
		||||
        self.assertEqual(r, "noarch")
 | 
			
		||||
@@ -106,7 +106,7 @@ class TestAgentUpdate(TacticalTestCase):
 | 
			
		||||
            site=self.site1,
 | 
			
		||||
            monitoring_type=AgentMonType.SERVER,
 | 
			
		||||
            plat=AgentPlat.WINDOWS,
 | 
			
		||||
            version="2.3.0",
 | 
			
		||||
            version="2.1.1",
 | 
			
		||||
            goarch=GoArch.AMD64,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
@@ -115,7 +115,7 @@ class TestAgentUpdate(TacticalTestCase):
 | 
			
		||||
            site=self.site3,
 | 
			
		||||
            monitoring_type=AgentMonType.WORKSTATION,
 | 
			
		||||
            plat=AgentPlat.LINUX,
 | 
			
		||||
            version="2.3.0",
 | 
			
		||||
            version="2.1.1",
 | 
			
		||||
            goarch=GoArch.ARM32,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
@@ -193,7 +193,7 @@ class TestAgentUpdate(TacticalTestCase):
 | 
			
		||||
            site=self.site2,
 | 
			
		||||
            monitoring_type=AgentMonType.SERVER,
 | 
			
		||||
            plat=AgentPlat.WINDOWS,
 | 
			
		||||
            version="2.3.0",
 | 
			
		||||
            version="2.1.1",
 | 
			
		||||
            goarch=GoArch.AMD64,
 | 
			
		||||
            _quantity=6,
 | 
			
		||||
        )
 | 
			
		||||
@@ -215,7 +215,7 @@ class TestAgentUpdate(TacticalTestCase):
 | 
			
		||||
            site=self.site2,
 | 
			
		||||
            monitoring_type=AgentMonType.SERVER,
 | 
			
		||||
            plat=AgentPlat.WINDOWS,
 | 
			
		||||
            version="2.3.0",
 | 
			
		||||
            version="2.1.1",
 | 
			
		||||
            goarch=GoArch.AMD64,
 | 
			
		||||
            _quantity=7,
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ class TestAgentUtils(TacticalTestCase):
 | 
			
		||||
 | 
			
		||||
        self.assertIn(r"agentDL='asdasd3423'", ret)
 | 
			
		||||
        self.assertIn(
 | 
			
		||||
            r"meshDL='meshsite/meshagents?id=meshid&installflags=0&meshinstall=6'", ret
 | 
			
		||||
            r"meshDL='meshsite/meshagents?id=meshid&installflags=2&meshinstall=6'", ret
 | 
			
		||||
        )
 | 
			
		||||
        self.assertIn(r"apiURL='api.example.com'", ret)
 | 
			
		||||
        self.assertIn(r"agentDL='asdasd3423'", ret)
 | 
			
		||||
 
 | 
			
		||||
@@ -422,13 +422,13 @@ class TestAgentViews(TacticalTestCase):
 | 
			
		||||
        url = f"{base_url}/{self.agent.agent_id}/reboot/"
 | 
			
		||||
 | 
			
		||||
        # ensure we don't allow dates in past
 | 
			
		||||
        data = {"datetime": "2022-07-11T01:51:11"}
 | 
			
		||||
        data = {"datetime": "2022-07-11T01:51"}
 | 
			
		||||
        r = self.client.patch(url, data, format="json")
 | 
			
		||||
        self.assertEqual(r.status_code, 400)
 | 
			
		||||
        self.assertEqual(r.data, "Date cannot be set in the past")
 | 
			
		||||
 | 
			
		||||
        # test with date in future
 | 
			
		||||
        data["datetime"] = "2027-08-29T18:41:02"
 | 
			
		||||
        data["datetime"] = "2027-08-29T18:41"
 | 
			
		||||
        r = self.client.patch(url, data, format="json")
 | 
			
		||||
        self.assertEqual(r.status_code, 200)
 | 
			
		||||
        self.assertEqual(r.data["time"], "August 29, 2027 at 06:41 PM")
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ def generate_linux_install(
 | 
			
		||||
    uri = get_mesh_ws_url()
 | 
			
		||||
    mesh_id = asyncio.run(get_mesh_device_id(uri, core.mesh_device_group))
 | 
			
		||||
    mesh_dl = (
 | 
			
		||||
        f"{core.mesh_site}/meshagents?id={mesh_id}&installflags=0&meshinstall={arch_id}"
 | 
			
		||||
        f"{core.mesh_site}/meshagents?id={mesh_id}&installflags=2&meshinstall={arch_id}"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    sh = settings.LINUX_AGENT_SCRIPT
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.utils import timezone as djangotime
 | 
			
		||||
from meshctrl.utils import get_login_token
 | 
			
		||||
from packaging import version as pyver
 | 
			
		||||
from rest_framework import serializers
 | 
			
		||||
from rest_framework.decorators import api_view, permission_classes
 | 
			
		||||
from rest_framework.exceptions import PermissionDenied
 | 
			
		||||
from rest_framework.permissions import IsAuthenticated
 | 
			
		||||
@@ -29,6 +30,7 @@ from scripts.models import Script
 | 
			
		||||
from scripts.tasks import handle_bulk_command_task, handle_bulk_script_task
 | 
			
		||||
from tacticalrmm.constants import (
 | 
			
		||||
    AGENT_DEFER,
 | 
			
		||||
    AGENT_TABLE_DEFER,
 | 
			
		||||
    AGENT_STATUS_OFFLINE,
 | 
			
		||||
    AGENT_STATUS_ONLINE,
 | 
			
		||||
    AgentHistoryType,
 | 
			
		||||
@@ -114,7 +116,7 @@ class GetAgents(APIView):
 | 
			
		||||
                Agent.objects.filter_by_role(request.user)  # type: ignore
 | 
			
		||||
                .filter(monitoring_type_filter)
 | 
			
		||||
                .filter(client_site_filter)
 | 
			
		||||
                .defer(*AGENT_DEFER)
 | 
			
		||||
                .defer(*AGENT_TABLE_DEFER)
 | 
			
		||||
                .select_related(
 | 
			
		||||
                    "site__server_policy",
 | 
			
		||||
                    "site__workstation_policy",
 | 
			
		||||
@@ -166,6 +168,24 @@ class GetAgents(APIView):
 | 
			
		||||
class GetUpdateDeleteAgent(APIView):
 | 
			
		||||
    permission_classes = [IsAuthenticated, AgentPerms]
 | 
			
		||||
 | 
			
		||||
    class InputSerializer(serializers.ModelSerializer):
 | 
			
		||||
        class Meta:
 | 
			
		||||
            model = Agent
 | 
			
		||||
            fields = [
 | 
			
		||||
                "maintenance_mode",  # TODO separate this
 | 
			
		||||
                "policy",  # TODO separate this
 | 
			
		||||
                "monitoring_type",
 | 
			
		||||
                "description",
 | 
			
		||||
                "overdue_email_alert",
 | 
			
		||||
                "overdue_text_alert",
 | 
			
		||||
                "overdue_dashboard_alert",
 | 
			
		||||
                "offline_time",
 | 
			
		||||
                "overdue_time",
 | 
			
		||||
                "check_interval",
 | 
			
		||||
                "time_zone",
 | 
			
		||||
                "site",
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
    # get agent details
 | 
			
		||||
    def get(self, request, agent_id):
 | 
			
		||||
        agent = get_object_or_404(Agent, agent_id=agent_id)
 | 
			
		||||
@@ -175,9 +195,9 @@ class GetUpdateDeleteAgent(APIView):
 | 
			
		||||
    def put(self, request, agent_id):
 | 
			
		||||
        agent = get_object_or_404(Agent, agent_id=agent_id)
 | 
			
		||||
 | 
			
		||||
        a_serializer = AgentSerializer(instance=agent, data=request.data, partial=True)
 | 
			
		||||
        a_serializer.is_valid(raise_exception=True)
 | 
			
		||||
        a_serializer.save()
 | 
			
		||||
        s = self.InputSerializer(instance=agent, data=request.data, partial=True)
 | 
			
		||||
        s.is_valid(raise_exception=True)
 | 
			
		||||
        s.save()
 | 
			
		||||
 | 
			
		||||
        if "winupdatepolicy" in request.data.keys():
 | 
			
		||||
            policy = agent.winupdatepolicy.get()  # type: ignore
 | 
			
		||||
@@ -460,7 +480,7 @@ class Reboot(APIView):
 | 
			
		||||
            return notify_error(f"Not currently implemented for {agent.plat}")
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            obj = dt.datetime.strptime(request.data["datetime"], "%Y-%m-%dT%H:%M:%S")
 | 
			
		||||
            obj = dt.datetime.strptime(request.data["datetime"], "%Y-%m-%dT%H:%M")
 | 
			
		||||
        except Exception:
 | 
			
		||||
            return notify_error("Invalid date")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,11 @@ from rest_framework.serializers import (
 | 
			
		||||
from agents.serializers import AgentHostnameSerializer
 | 
			
		||||
from autotasks.models import TaskResult
 | 
			
		||||
from checks.models import CheckResult
 | 
			
		||||
from clients.models import Client
 | 
			
		||||
from clients.serializers import ClientMinimumSerializer, SiteMinimumSerializer
 | 
			
		||||
from clients.models import Client, Site
 | 
			
		||||
from clients.serializers import (
 | 
			
		||||
    ClientMinimumSerializer,
 | 
			
		||||
    SiteMinimumSerializer,
 | 
			
		||||
)
 | 
			
		||||
from winupdate.serializers import WinUpdatePolicySerializer
 | 
			
		||||
 | 
			
		||||
from .models import Policy
 | 
			
		||||
@@ -85,11 +88,29 @@ class PolicyRelatedSerializer(ModelSerializer):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PolicyOverviewSiteSerializer(ModelSerializer):
 | 
			
		||||
    workstation_policy = PolicySerializer(read_only=True)
 | 
			
		||||
    server_policy = PolicySerializer(read_only=True)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Site
 | 
			
		||||
        fields = ("pk", "name", "workstation_policy", "server_policy")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PolicyOverviewSerializer(ModelSerializer):
 | 
			
		||||
    sites = SerializerMethodField()
 | 
			
		||||
    workstation_policy = PolicySerializer(read_only=True)
 | 
			
		||||
    server_policy = PolicySerializer(read_only=True)
 | 
			
		||||
 | 
			
		||||
    def get_sites(self, obj):
 | 
			
		||||
        return PolicyOverviewSiteSerializer(
 | 
			
		||||
            obj.filtered_sites,
 | 
			
		||||
            many=True,
 | 
			
		||||
        ).data
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Client
 | 
			
		||||
        fields = ("pk", "name", "sites", "workstation_policy", "server_policy")
 | 
			
		||||
        depth = 2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PolicyCheckStatusSerializer(ModelSerializer):
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,9 @@ from itertools import cycle
 | 
			
		||||
from unittest.mock import patch
 | 
			
		||||
 | 
			
		||||
from model_bakery import baker, seq
 | 
			
		||||
 | 
			
		||||
from django.db.models import Prefetch
 | 
			
		||||
from agents.models import Agent
 | 
			
		||||
from clients.models import Site
 | 
			
		||||
from core.utils import get_core_settings
 | 
			
		||||
from tacticalrmm.constants import AgentMonType, TaskSyncStatus
 | 
			
		||||
from tacticalrmm.test import TacticalTestCase
 | 
			
		||||
@@ -186,7 +187,17 @@ class TestPolicyViews(TacticalTestCase):
 | 
			
		||||
 | 
			
		||||
        baker.make("clients.Site", client=cycle(clients), _quantity=3)
 | 
			
		||||
        resp = self.client.get(url, format="json")
 | 
			
		||||
        clients = Client.objects.all()
 | 
			
		||||
        clients = Client.objects.select_related(
 | 
			
		||||
            "workstation_policy", "server_policy"
 | 
			
		||||
        ).prefetch_related(
 | 
			
		||||
            Prefetch(
 | 
			
		||||
                "sites",
 | 
			
		||||
                queryset=Site.objects.select_related(
 | 
			
		||||
                    "workstation_policy", "server_policy"
 | 
			
		||||
                ),
 | 
			
		||||
                to_attr="filtered_sites",
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        serializer = PolicyOverviewSerializer(clients, many=True)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(resp.status_code, 200)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,11 @@ from rest_framework.views import APIView
 | 
			
		||||
from agents.models import Agent
 | 
			
		||||
from autotasks.models import TaskResult
 | 
			
		||||
from checks.models import CheckResult
 | 
			
		||||
from clients.models import Client
 | 
			
		||||
from clients.models import Client, Site
 | 
			
		||||
from tacticalrmm.permissions import _has_perm_on_client, _has_perm_on_site
 | 
			
		||||
from winupdate.models import WinUpdatePolicy
 | 
			
		||||
from winupdate.serializers import WinUpdatePolicySerializer
 | 
			
		||||
from django.db.models import Prefetch
 | 
			
		||||
 | 
			
		||||
from .models import Policy
 | 
			
		||||
from .permissions import AutomationPolicyPerms
 | 
			
		||||
@@ -108,8 +109,18 @@ class PolicyCheck(APIView):
 | 
			
		||||
class OverviewPolicy(APIView):
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
 | 
			
		||||
        clients = Client.objects.filter_by_role(request.user).select_related(
 | 
			
		||||
            "workstation_policy", "server_policy"
 | 
			
		||||
        clients = (
 | 
			
		||||
            Client.objects.filter_by_role(request.user)
 | 
			
		||||
            .select_related("workstation_policy", "server_policy")
 | 
			
		||||
            .prefetch_related(
 | 
			
		||||
                Prefetch(
 | 
			
		||||
                    "sites",
 | 
			
		||||
                    queryset=Site.objects.select_related(
 | 
			
		||||
                        "workstation_policy", "server_policy"
 | 
			
		||||
                    ),
 | 
			
		||||
                    to_attr="filtered_sites",
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        return Response(PolicyOverviewSerializer(clients, many=True).data)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -70,11 +70,11 @@ class Client(BaseAuditModel):
 | 
			
		||||
            sites = self.sites.all()
 | 
			
		||||
            if old_client.workstation_policy != self.workstation_policy:
 | 
			
		||||
                for site in sites:
 | 
			
		||||
                    cache.delete_many_pattern(f"site_workstation_{site.pk}_*")
 | 
			
		||||
                    cache.delete_many_pattern(f"site_workstation_*{site.pk}_*")
 | 
			
		||||
 | 
			
		||||
            if old_client.server_policy != self.server_policy:
 | 
			
		||||
                for site in sites:
 | 
			
		||||
                    cache.delete_many_pattern(f"site_server_{site.pk}_*")
 | 
			
		||||
                    cache.delete_many_pattern(f"site_server_*{site.pk}_*")
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        ordering = ("name",)
 | 
			
		||||
@@ -145,10 +145,10 @@ class Site(BaseAuditModel):
 | 
			
		||||
                cache_agents_alert_template.delay()
 | 
			
		||||
 | 
			
		||||
            if old_site.workstation_policy != self.workstation_policy:
 | 
			
		||||
                cache.delete_many_pattern(f"site_workstation_{self.pk}_*")
 | 
			
		||||
                cache.delete_many_pattern(f"site_workstation_*{self.pk}_*")
 | 
			
		||||
 | 
			
		||||
            if old_site.server_policy != self.server_policy:
 | 
			
		||||
                cache.delete_many_pattern(f"site_server_{self.pk}_*")
 | 
			
		||||
                cache.delete_many_pattern(f"site_server_*{self.pk}_*")
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        ordering = ("name",)
 | 
			
		||||
 
 | 
			
		||||
@@ -85,14 +85,14 @@ InstallMesh() {
 | 
			
		||||
    wget --no-check-certificate -q -O ${meshTmpBin} ${meshDL}
 | 
			
		||||
    chmod +x ${meshTmpBin}
 | 
			
		||||
    mkdir -p ${meshDir}
 | 
			
		||||
    env LC_ALL=en_US.UTF-8 LANGUAGE=en_US ${meshTmpBin} -install --installPath=${meshDir}
 | 
			
		||||
    env LC_ALL=en_US.UTF-8 LANGUAGE=en_US XAUTHORITY=foo DISPLAY=bar ${meshTmpBin} -install --installPath=${meshDir}
 | 
			
		||||
    sleep 1
 | 
			
		||||
    rm -rf ${meshTmpDir}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RemoveMesh() {
 | 
			
		||||
    if [ -f "${meshSystemBin}" ]; then
 | 
			
		||||
        ${meshSystemBin} -uninstall
 | 
			
		||||
        env XAUTHORITY=foo DISPLAY=bar ${meshSystemBin} -uninstall
 | 
			
		||||
        sleep 1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
@@ -133,7 +133,7 @@ else
 | 
			
		||||
    InstallMesh
 | 
			
		||||
    sleep 2
 | 
			
		||||
    echo "Getting mesh node id..."
 | 
			
		||||
    MESH_NODE_ID=$(${agentBin} -m nixmeshnodeid)
 | 
			
		||||
    MESH_NODE_ID=$(env XAUTHORITY=foo DISPLAY=bar ${agentBin} -m nixmeshnodeid)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ ! -d "${agentBinPath}" ]; then
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,8 @@ If (Get-Service $serviceName -ErrorAction SilentlyContinue) {
 | 
			
		||||
        $DefenderStatus = Get-MpComputerStatus | select  AntivirusEnabled
 | 
			
		||||
        if ($DefenderStatus -match "True") {
 | 
			
		||||
            Add-MpPreference -ExclusionPath 'C:\Program Files\TacticalAgent\*'
 | 
			
		||||
            Add-MpPreference -ExclusionPath 'C:\Windows\Temp\winagent-v*.exe'
 | 
			
		||||
            Add-MpPreference -ExclusionPath 'C:\Program Files\Mesh Agent\*'
 | 
			
		||||
            Add-MpPreference -ExclusionPath 'C:\Windows\Temp\trmm*\*'
 | 
			
		||||
            Add-MpPreference -ExclusionPath 'C:\ProgramData\TacticalRMM\*'
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    Catch {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,630 @@
 | 
			
		||||
# Generated by Django 4.1 on 2022-08-24 07:32
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("core", "0034_alter_customfield_name"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name="coresettings",
 | 
			
		||||
            name="default_time_zone",
 | 
			
		||||
            field=models.CharField(
 | 
			
		||||
                choices=[
 | 
			
		||||
                    ("Africa/Abidjan", "Africa/Abidjan"),
 | 
			
		||||
                    ("Africa/Accra", "Africa/Accra"),
 | 
			
		||||
                    ("Africa/Addis_Ababa", "Africa/Addis_Ababa"),
 | 
			
		||||
                    ("Africa/Algiers", "Africa/Algiers"),
 | 
			
		||||
                    ("Africa/Asmara", "Africa/Asmara"),
 | 
			
		||||
                    ("Africa/Asmera", "Africa/Asmera"),
 | 
			
		||||
                    ("Africa/Bamako", "Africa/Bamako"),
 | 
			
		||||
                    ("Africa/Bangui", "Africa/Bangui"),
 | 
			
		||||
                    ("Africa/Banjul", "Africa/Banjul"),
 | 
			
		||||
                    ("Africa/Bissau", "Africa/Bissau"),
 | 
			
		||||
                    ("Africa/Blantyre", "Africa/Blantyre"),
 | 
			
		||||
                    ("Africa/Brazzaville", "Africa/Brazzaville"),
 | 
			
		||||
                    ("Africa/Bujumbura", "Africa/Bujumbura"),
 | 
			
		||||
                    ("Africa/Cairo", "Africa/Cairo"),
 | 
			
		||||
                    ("Africa/Casablanca", "Africa/Casablanca"),
 | 
			
		||||
                    ("Africa/Ceuta", "Africa/Ceuta"),
 | 
			
		||||
                    ("Africa/Conakry", "Africa/Conakry"),
 | 
			
		||||
                    ("Africa/Dakar", "Africa/Dakar"),
 | 
			
		||||
                    ("Africa/Dar_es_Salaam", "Africa/Dar_es_Salaam"),
 | 
			
		||||
                    ("Africa/Djibouti", "Africa/Djibouti"),
 | 
			
		||||
                    ("Africa/Douala", "Africa/Douala"),
 | 
			
		||||
                    ("Africa/El_Aaiun", "Africa/El_Aaiun"),
 | 
			
		||||
                    ("Africa/Freetown", "Africa/Freetown"),
 | 
			
		||||
                    ("Africa/Gaborone", "Africa/Gaborone"),
 | 
			
		||||
                    ("Africa/Harare", "Africa/Harare"),
 | 
			
		||||
                    ("Africa/Johannesburg", "Africa/Johannesburg"),
 | 
			
		||||
                    ("Africa/Juba", "Africa/Juba"),
 | 
			
		||||
                    ("Africa/Kampala", "Africa/Kampala"),
 | 
			
		||||
                    ("Africa/Khartoum", "Africa/Khartoum"),
 | 
			
		||||
                    ("Africa/Kigali", "Africa/Kigali"),
 | 
			
		||||
                    ("Africa/Kinshasa", "Africa/Kinshasa"),
 | 
			
		||||
                    ("Africa/Lagos", "Africa/Lagos"),
 | 
			
		||||
                    ("Africa/Libreville", "Africa/Libreville"),
 | 
			
		||||
                    ("Africa/Lome", "Africa/Lome"),
 | 
			
		||||
                    ("Africa/Luanda", "Africa/Luanda"),
 | 
			
		||||
                    ("Africa/Lubumbashi", "Africa/Lubumbashi"),
 | 
			
		||||
                    ("Africa/Lusaka", "Africa/Lusaka"),
 | 
			
		||||
                    ("Africa/Malabo", "Africa/Malabo"),
 | 
			
		||||
                    ("Africa/Maputo", "Africa/Maputo"),
 | 
			
		||||
                    ("Africa/Maseru", "Africa/Maseru"),
 | 
			
		||||
                    ("Africa/Mbabane", "Africa/Mbabane"),
 | 
			
		||||
                    ("Africa/Mogadishu", "Africa/Mogadishu"),
 | 
			
		||||
                    ("Africa/Monrovia", "Africa/Monrovia"),
 | 
			
		||||
                    ("Africa/Nairobi", "Africa/Nairobi"),
 | 
			
		||||
                    ("Africa/Ndjamena", "Africa/Ndjamena"),
 | 
			
		||||
                    ("Africa/Niamey", "Africa/Niamey"),
 | 
			
		||||
                    ("Africa/Nouakchott", "Africa/Nouakchott"),
 | 
			
		||||
                    ("Africa/Ouagadougou", "Africa/Ouagadougou"),
 | 
			
		||||
                    ("Africa/Porto-Novo", "Africa/Porto-Novo"),
 | 
			
		||||
                    ("Africa/Sao_Tome", "Africa/Sao_Tome"),
 | 
			
		||||
                    ("Africa/Timbuktu", "Africa/Timbuktu"),
 | 
			
		||||
                    ("Africa/Tripoli", "Africa/Tripoli"),
 | 
			
		||||
                    ("Africa/Tunis", "Africa/Tunis"),
 | 
			
		||||
                    ("Africa/Windhoek", "Africa/Windhoek"),
 | 
			
		||||
                    ("America/Adak", "America/Adak"),
 | 
			
		||||
                    ("America/Anchorage", "America/Anchorage"),
 | 
			
		||||
                    ("America/Anguilla", "America/Anguilla"),
 | 
			
		||||
                    ("America/Antigua", "America/Antigua"),
 | 
			
		||||
                    ("America/Araguaina", "America/Araguaina"),
 | 
			
		||||
                    (
 | 
			
		||||
                        "America/Argentina/Buenos_Aires",
 | 
			
		||||
                        "America/Argentina/Buenos_Aires",
 | 
			
		||||
                    ),
 | 
			
		||||
                    ("America/Argentina/Catamarca", "America/Argentina/Catamarca"),
 | 
			
		||||
                    (
 | 
			
		||||
                        "America/Argentina/ComodRivadavia",
 | 
			
		||||
                        "America/Argentina/ComodRivadavia",
 | 
			
		||||
                    ),
 | 
			
		||||
                    ("America/Argentina/Cordoba", "America/Argentina/Cordoba"),
 | 
			
		||||
                    ("America/Argentina/Jujuy", "America/Argentina/Jujuy"),
 | 
			
		||||
                    ("America/Argentina/La_Rioja", "America/Argentina/La_Rioja"),
 | 
			
		||||
                    ("America/Argentina/Mendoza", "America/Argentina/Mendoza"),
 | 
			
		||||
                    (
 | 
			
		||||
                        "America/Argentina/Rio_Gallegos",
 | 
			
		||||
                        "America/Argentina/Rio_Gallegos",
 | 
			
		||||
                    ),
 | 
			
		||||
                    ("America/Argentina/Salta", "America/Argentina/Salta"),
 | 
			
		||||
                    ("America/Argentina/San_Juan", "America/Argentina/San_Juan"),
 | 
			
		||||
                    ("America/Argentina/San_Luis", "America/Argentina/San_Luis"),
 | 
			
		||||
                    ("America/Argentina/Tucuman", "America/Argentina/Tucuman"),
 | 
			
		||||
                    ("America/Argentina/Ushuaia", "America/Argentina/Ushuaia"),
 | 
			
		||||
                    ("America/Aruba", "America/Aruba"),
 | 
			
		||||
                    ("America/Asuncion", "America/Asuncion"),
 | 
			
		||||
                    ("America/Atikokan", "America/Atikokan"),
 | 
			
		||||
                    ("America/Atka", "America/Atka"),
 | 
			
		||||
                    ("America/Bahia", "America/Bahia"),
 | 
			
		||||
                    ("America/Bahia_Banderas", "America/Bahia_Banderas"),
 | 
			
		||||
                    ("America/Barbados", "America/Barbados"),
 | 
			
		||||
                    ("America/Belem", "America/Belem"),
 | 
			
		||||
                    ("America/Belize", "America/Belize"),
 | 
			
		||||
                    ("America/Blanc-Sablon", "America/Blanc-Sablon"),
 | 
			
		||||
                    ("America/Boa_Vista", "America/Boa_Vista"),
 | 
			
		||||
                    ("America/Bogota", "America/Bogota"),
 | 
			
		||||
                    ("America/Boise", "America/Boise"),
 | 
			
		||||
                    ("America/Buenos_Aires", "America/Buenos_Aires"),
 | 
			
		||||
                    ("America/Cambridge_Bay", "America/Cambridge_Bay"),
 | 
			
		||||
                    ("America/Campo_Grande", "America/Campo_Grande"),
 | 
			
		||||
                    ("America/Cancun", "America/Cancun"),
 | 
			
		||||
                    ("America/Caracas", "America/Caracas"),
 | 
			
		||||
                    ("America/Catamarca", "America/Catamarca"),
 | 
			
		||||
                    ("America/Cayenne", "America/Cayenne"),
 | 
			
		||||
                    ("America/Cayman", "America/Cayman"),
 | 
			
		||||
                    ("America/Chicago", "America/Chicago"),
 | 
			
		||||
                    ("America/Chihuahua", "America/Chihuahua"),
 | 
			
		||||
                    ("America/Coral_Harbour", "America/Coral_Harbour"),
 | 
			
		||||
                    ("America/Cordoba", "America/Cordoba"),
 | 
			
		||||
                    ("America/Costa_Rica", "America/Costa_Rica"),
 | 
			
		||||
                    ("America/Creston", "America/Creston"),
 | 
			
		||||
                    ("America/Cuiaba", "America/Cuiaba"),
 | 
			
		||||
                    ("America/Curacao", "America/Curacao"),
 | 
			
		||||
                    ("America/Danmarkshavn", "America/Danmarkshavn"),
 | 
			
		||||
                    ("America/Dawson", "America/Dawson"),
 | 
			
		||||
                    ("America/Dawson_Creek", "America/Dawson_Creek"),
 | 
			
		||||
                    ("America/Denver", "America/Denver"),
 | 
			
		||||
                    ("America/Detroit", "America/Detroit"),
 | 
			
		||||
                    ("America/Dominica", "America/Dominica"),
 | 
			
		||||
                    ("America/Edmonton", "America/Edmonton"),
 | 
			
		||||
                    ("America/Eirunepe", "America/Eirunepe"),
 | 
			
		||||
                    ("America/El_Salvador", "America/El_Salvador"),
 | 
			
		||||
                    ("America/Ensenada", "America/Ensenada"),
 | 
			
		||||
                    ("America/Fort_Nelson", "America/Fort_Nelson"),
 | 
			
		||||
                    ("America/Fort_Wayne", "America/Fort_Wayne"),
 | 
			
		||||
                    ("America/Fortaleza", "America/Fortaleza"),
 | 
			
		||||
                    ("America/Glace_Bay", "America/Glace_Bay"),
 | 
			
		||||
                    ("America/Godthab", "America/Godthab"),
 | 
			
		||||
                    ("America/Goose_Bay", "America/Goose_Bay"),
 | 
			
		||||
                    ("America/Grand_Turk", "America/Grand_Turk"),
 | 
			
		||||
                    ("America/Grenada", "America/Grenada"),
 | 
			
		||||
                    ("America/Guadeloupe", "America/Guadeloupe"),
 | 
			
		||||
                    ("America/Guatemala", "America/Guatemala"),
 | 
			
		||||
                    ("America/Guayaquil", "America/Guayaquil"),
 | 
			
		||||
                    ("America/Guyana", "America/Guyana"),
 | 
			
		||||
                    ("America/Halifax", "America/Halifax"),
 | 
			
		||||
                    ("America/Havana", "America/Havana"),
 | 
			
		||||
                    ("America/Hermosillo", "America/Hermosillo"),
 | 
			
		||||
                    ("America/Indiana/Indianapolis", "America/Indiana/Indianapolis"),
 | 
			
		||||
                    ("America/Indiana/Knox", "America/Indiana/Knox"),
 | 
			
		||||
                    ("America/Indiana/Marengo", "America/Indiana/Marengo"),
 | 
			
		||||
                    ("America/Indiana/Petersburg", "America/Indiana/Petersburg"),
 | 
			
		||||
                    ("America/Indiana/Tell_City", "America/Indiana/Tell_City"),
 | 
			
		||||
                    ("America/Indiana/Vevay", "America/Indiana/Vevay"),
 | 
			
		||||
                    ("America/Indiana/Vincennes", "America/Indiana/Vincennes"),
 | 
			
		||||
                    ("America/Indiana/Winamac", "America/Indiana/Winamac"),
 | 
			
		||||
                    ("America/Indianapolis", "America/Indianapolis"),
 | 
			
		||||
                    ("America/Inuvik", "America/Inuvik"),
 | 
			
		||||
                    ("America/Iqaluit", "America/Iqaluit"),
 | 
			
		||||
                    ("America/Jamaica", "America/Jamaica"),
 | 
			
		||||
                    ("America/Jujuy", "America/Jujuy"),
 | 
			
		||||
                    ("America/Juneau", "America/Juneau"),
 | 
			
		||||
                    ("America/Kentucky/Louisville", "America/Kentucky/Louisville"),
 | 
			
		||||
                    ("America/Kentucky/Monticello", "America/Kentucky/Monticello"),
 | 
			
		||||
                    ("America/Knox_IN", "America/Knox_IN"),
 | 
			
		||||
                    ("America/Kralendijk", "America/Kralendijk"),
 | 
			
		||||
                    ("America/La_Paz", "America/La_Paz"),
 | 
			
		||||
                    ("America/Lima", "America/Lima"),
 | 
			
		||||
                    ("America/Los_Angeles", "America/Los_Angeles"),
 | 
			
		||||
                    ("America/Louisville", "America/Louisville"),
 | 
			
		||||
                    ("America/Lower_Princes", "America/Lower_Princes"),
 | 
			
		||||
                    ("America/Maceio", "America/Maceio"),
 | 
			
		||||
                    ("America/Managua", "America/Managua"),
 | 
			
		||||
                    ("America/Manaus", "America/Manaus"),
 | 
			
		||||
                    ("America/Marigot", "America/Marigot"),
 | 
			
		||||
                    ("America/Martinique", "America/Martinique"),
 | 
			
		||||
                    ("America/Matamoros", "America/Matamoros"),
 | 
			
		||||
                    ("America/Mazatlan", "America/Mazatlan"),
 | 
			
		||||
                    ("America/Mendoza", "America/Mendoza"),
 | 
			
		||||
                    ("America/Menominee", "America/Menominee"),
 | 
			
		||||
                    ("America/Merida", "America/Merida"),
 | 
			
		||||
                    ("America/Metlakatla", "America/Metlakatla"),
 | 
			
		||||
                    ("America/Mexico_City", "America/Mexico_City"),
 | 
			
		||||
                    ("America/Miquelon", "America/Miquelon"),
 | 
			
		||||
                    ("America/Moncton", "America/Moncton"),
 | 
			
		||||
                    ("America/Monterrey", "America/Monterrey"),
 | 
			
		||||
                    ("America/Montevideo", "America/Montevideo"),
 | 
			
		||||
                    ("America/Montreal", "America/Montreal"),
 | 
			
		||||
                    ("America/Montserrat", "America/Montserrat"),
 | 
			
		||||
                    ("America/Nassau", "America/Nassau"),
 | 
			
		||||
                    ("America/New_York", "America/New_York"),
 | 
			
		||||
                    ("America/Nipigon", "America/Nipigon"),
 | 
			
		||||
                    ("America/Nome", "America/Nome"),
 | 
			
		||||
                    ("America/Noronha", "America/Noronha"),
 | 
			
		||||
                    ("America/North_Dakota/Beulah", "America/North_Dakota/Beulah"),
 | 
			
		||||
                    ("America/North_Dakota/Center", "America/North_Dakota/Center"),
 | 
			
		||||
                    (
 | 
			
		||||
                        "America/North_Dakota/New_Salem",
 | 
			
		||||
                        "America/North_Dakota/New_Salem",
 | 
			
		||||
                    ),
 | 
			
		||||
                    ("America/Nuuk", "America/Nuuk"),
 | 
			
		||||
                    ("America/Ojinaga", "America/Ojinaga"),
 | 
			
		||||
                    ("America/Panama", "America/Panama"),
 | 
			
		||||
                    ("America/Pangnirtung", "America/Pangnirtung"),
 | 
			
		||||
                    ("America/Paramaribo", "America/Paramaribo"),
 | 
			
		||||
                    ("America/Phoenix", "America/Phoenix"),
 | 
			
		||||
                    ("America/Port-au-Prince", "America/Port-au-Prince"),
 | 
			
		||||
                    ("America/Port_of_Spain", "America/Port_of_Spain"),
 | 
			
		||||
                    ("America/Porto_Acre", "America/Porto_Acre"),
 | 
			
		||||
                    ("America/Porto_Velho", "America/Porto_Velho"),
 | 
			
		||||
                    ("America/Puerto_Rico", "America/Puerto_Rico"),
 | 
			
		||||
                    ("America/Punta_Arenas", "America/Punta_Arenas"),
 | 
			
		||||
                    ("America/Rainy_River", "America/Rainy_River"),
 | 
			
		||||
                    ("America/Rankin_Inlet", "America/Rankin_Inlet"),
 | 
			
		||||
                    ("America/Recife", "America/Recife"),
 | 
			
		||||
                    ("America/Regina", "America/Regina"),
 | 
			
		||||
                    ("America/Resolute", "America/Resolute"),
 | 
			
		||||
                    ("America/Rio_Branco", "America/Rio_Branco"),
 | 
			
		||||
                    ("America/Rosario", "America/Rosario"),
 | 
			
		||||
                    ("America/Santa_Isabel", "America/Santa_Isabel"),
 | 
			
		||||
                    ("America/Santarem", "America/Santarem"),
 | 
			
		||||
                    ("America/Santiago", "America/Santiago"),
 | 
			
		||||
                    ("America/Santo_Domingo", "America/Santo_Domingo"),
 | 
			
		||||
                    ("America/Sao_Paulo", "America/Sao_Paulo"),
 | 
			
		||||
                    ("America/Scoresbysund", "America/Scoresbysund"),
 | 
			
		||||
                    ("America/Shiprock", "America/Shiprock"),
 | 
			
		||||
                    ("America/Sitka", "America/Sitka"),
 | 
			
		||||
                    ("America/St_Barthelemy", "America/St_Barthelemy"),
 | 
			
		||||
                    ("America/St_Johns", "America/St_Johns"),
 | 
			
		||||
                    ("America/St_Kitts", "America/St_Kitts"),
 | 
			
		||||
                    ("America/St_Lucia", "America/St_Lucia"),
 | 
			
		||||
                    ("America/St_Thomas", "America/St_Thomas"),
 | 
			
		||||
                    ("America/St_Vincent", "America/St_Vincent"),
 | 
			
		||||
                    ("America/Swift_Current", "America/Swift_Current"),
 | 
			
		||||
                    ("America/Tegucigalpa", "America/Tegucigalpa"),
 | 
			
		||||
                    ("America/Thule", "America/Thule"),
 | 
			
		||||
                    ("America/Thunder_Bay", "America/Thunder_Bay"),
 | 
			
		||||
                    ("America/Tijuana", "America/Tijuana"),
 | 
			
		||||
                    ("America/Toronto", "America/Toronto"),
 | 
			
		||||
                    ("America/Tortola", "America/Tortola"),
 | 
			
		||||
                    ("America/Vancouver", "America/Vancouver"),
 | 
			
		||||
                    ("America/Virgin", "America/Virgin"),
 | 
			
		||||
                    ("America/Whitehorse", "America/Whitehorse"),
 | 
			
		||||
                    ("America/Winnipeg", "America/Winnipeg"),
 | 
			
		||||
                    ("America/Yakutat", "America/Yakutat"),
 | 
			
		||||
                    ("America/Yellowknife", "America/Yellowknife"),
 | 
			
		||||
                    ("Antarctica/Casey", "Antarctica/Casey"),
 | 
			
		||||
                    ("Antarctica/Davis", "Antarctica/Davis"),
 | 
			
		||||
                    ("Antarctica/DumontDUrville", "Antarctica/DumontDUrville"),
 | 
			
		||||
                    ("Antarctica/Macquarie", "Antarctica/Macquarie"),
 | 
			
		||||
                    ("Antarctica/Mawson", "Antarctica/Mawson"),
 | 
			
		||||
                    ("Antarctica/McMurdo", "Antarctica/McMurdo"),
 | 
			
		||||
                    ("Antarctica/Palmer", "Antarctica/Palmer"),
 | 
			
		||||
                    ("Antarctica/Rothera", "Antarctica/Rothera"),
 | 
			
		||||
                    ("Antarctica/South_Pole", "Antarctica/South_Pole"),
 | 
			
		||||
                    ("Antarctica/Syowa", "Antarctica/Syowa"),
 | 
			
		||||
                    ("Antarctica/Troll", "Antarctica/Troll"),
 | 
			
		||||
                    ("Antarctica/Vostok", "Antarctica/Vostok"),
 | 
			
		||||
                    ("Arctic/Longyearbyen", "Arctic/Longyearbyen"),
 | 
			
		||||
                    ("Asia/Aden", "Asia/Aden"),
 | 
			
		||||
                    ("Asia/Almaty", "Asia/Almaty"),
 | 
			
		||||
                    ("Asia/Amman", "Asia/Amman"),
 | 
			
		||||
                    ("Asia/Anadyr", "Asia/Anadyr"),
 | 
			
		||||
                    ("Asia/Aqtau", "Asia/Aqtau"),
 | 
			
		||||
                    ("Asia/Aqtobe", "Asia/Aqtobe"),
 | 
			
		||||
                    ("Asia/Ashgabat", "Asia/Ashgabat"),
 | 
			
		||||
                    ("Asia/Ashkhabad", "Asia/Ashkhabad"),
 | 
			
		||||
                    ("Asia/Atyrau", "Asia/Atyrau"),
 | 
			
		||||
                    ("Asia/Baghdad", "Asia/Baghdad"),
 | 
			
		||||
                    ("Asia/Bahrain", "Asia/Bahrain"),
 | 
			
		||||
                    ("Asia/Baku", "Asia/Baku"),
 | 
			
		||||
                    ("Asia/Bangkok", "Asia/Bangkok"),
 | 
			
		||||
                    ("Asia/Barnaul", "Asia/Barnaul"),
 | 
			
		||||
                    ("Asia/Beirut", "Asia/Beirut"),
 | 
			
		||||
                    ("Asia/Bishkek", "Asia/Bishkek"),
 | 
			
		||||
                    ("Asia/Brunei", "Asia/Brunei"),
 | 
			
		||||
                    ("Asia/Calcutta", "Asia/Calcutta"),
 | 
			
		||||
                    ("Asia/Chita", "Asia/Chita"),
 | 
			
		||||
                    ("Asia/Choibalsan", "Asia/Choibalsan"),
 | 
			
		||||
                    ("Asia/Chongqing", "Asia/Chongqing"),
 | 
			
		||||
                    ("Asia/Chungking", "Asia/Chungking"),
 | 
			
		||||
                    ("Asia/Colombo", "Asia/Colombo"),
 | 
			
		||||
                    ("Asia/Dacca", "Asia/Dacca"),
 | 
			
		||||
                    ("Asia/Damascus", "Asia/Damascus"),
 | 
			
		||||
                    ("Asia/Dhaka", "Asia/Dhaka"),
 | 
			
		||||
                    ("Asia/Dili", "Asia/Dili"),
 | 
			
		||||
                    ("Asia/Dubai", "Asia/Dubai"),
 | 
			
		||||
                    ("Asia/Dushanbe", "Asia/Dushanbe"),
 | 
			
		||||
                    ("Asia/Famagusta", "Asia/Famagusta"),
 | 
			
		||||
                    ("Asia/Gaza", "Asia/Gaza"),
 | 
			
		||||
                    ("Asia/Harbin", "Asia/Harbin"),
 | 
			
		||||
                    ("Asia/Hebron", "Asia/Hebron"),
 | 
			
		||||
                    ("Asia/Ho_Chi_Minh", "Asia/Ho_Chi_Minh"),
 | 
			
		||||
                    ("Asia/Hong_Kong", "Asia/Hong_Kong"),
 | 
			
		||||
                    ("Asia/Hovd", "Asia/Hovd"),
 | 
			
		||||
                    ("Asia/Irkutsk", "Asia/Irkutsk"),
 | 
			
		||||
                    ("Asia/Istanbul", "Asia/Istanbul"),
 | 
			
		||||
                    ("Asia/Jakarta", "Asia/Jakarta"),
 | 
			
		||||
                    ("Asia/Jayapura", "Asia/Jayapura"),
 | 
			
		||||
                    ("Asia/Jerusalem", "Asia/Jerusalem"),
 | 
			
		||||
                    ("Asia/Kabul", "Asia/Kabul"),
 | 
			
		||||
                    ("Asia/Kamchatka", "Asia/Kamchatka"),
 | 
			
		||||
                    ("Asia/Karachi", "Asia/Karachi"),
 | 
			
		||||
                    ("Asia/Kashgar", "Asia/Kashgar"),
 | 
			
		||||
                    ("Asia/Kathmandu", "Asia/Kathmandu"),
 | 
			
		||||
                    ("Asia/Katmandu", "Asia/Katmandu"),
 | 
			
		||||
                    ("Asia/Khandyga", "Asia/Khandyga"),
 | 
			
		||||
                    ("Asia/Kolkata", "Asia/Kolkata"),
 | 
			
		||||
                    ("Asia/Krasnoyarsk", "Asia/Krasnoyarsk"),
 | 
			
		||||
                    ("Asia/Kuala_Lumpur", "Asia/Kuala_Lumpur"),
 | 
			
		||||
                    ("Asia/Kuching", "Asia/Kuching"),
 | 
			
		||||
                    ("Asia/Kuwait", "Asia/Kuwait"),
 | 
			
		||||
                    ("Asia/Macao", "Asia/Macao"),
 | 
			
		||||
                    ("Asia/Macau", "Asia/Macau"),
 | 
			
		||||
                    ("Asia/Magadan", "Asia/Magadan"),
 | 
			
		||||
                    ("Asia/Makassar", "Asia/Makassar"),
 | 
			
		||||
                    ("Asia/Manila", "Asia/Manila"),
 | 
			
		||||
                    ("Asia/Muscat", "Asia/Muscat"),
 | 
			
		||||
                    ("Asia/Nicosia", "Asia/Nicosia"),
 | 
			
		||||
                    ("Asia/Novokuznetsk", "Asia/Novokuznetsk"),
 | 
			
		||||
                    ("Asia/Novosibirsk", "Asia/Novosibirsk"),
 | 
			
		||||
                    ("Asia/Omsk", "Asia/Omsk"),
 | 
			
		||||
                    ("Asia/Oral", "Asia/Oral"),
 | 
			
		||||
                    ("Asia/Phnom_Penh", "Asia/Phnom_Penh"),
 | 
			
		||||
                    ("Asia/Pontianak", "Asia/Pontianak"),
 | 
			
		||||
                    ("Asia/Pyongyang", "Asia/Pyongyang"),
 | 
			
		||||
                    ("Asia/Qatar", "Asia/Qatar"),
 | 
			
		||||
                    ("Asia/Qostanay", "Asia/Qostanay"),
 | 
			
		||||
                    ("Asia/Qyzylorda", "Asia/Qyzylorda"),
 | 
			
		||||
                    ("Asia/Rangoon", "Asia/Rangoon"),
 | 
			
		||||
                    ("Asia/Riyadh", "Asia/Riyadh"),
 | 
			
		||||
                    ("Asia/Saigon", "Asia/Saigon"),
 | 
			
		||||
                    ("Asia/Sakhalin", "Asia/Sakhalin"),
 | 
			
		||||
                    ("Asia/Samarkand", "Asia/Samarkand"),
 | 
			
		||||
                    ("Asia/Seoul", "Asia/Seoul"),
 | 
			
		||||
                    ("Asia/Shanghai", "Asia/Shanghai"),
 | 
			
		||||
                    ("Asia/Singapore", "Asia/Singapore"),
 | 
			
		||||
                    ("Asia/Srednekolymsk", "Asia/Srednekolymsk"),
 | 
			
		||||
                    ("Asia/Taipei", "Asia/Taipei"),
 | 
			
		||||
                    ("Asia/Tashkent", "Asia/Tashkent"),
 | 
			
		||||
                    ("Asia/Tbilisi", "Asia/Tbilisi"),
 | 
			
		||||
                    ("Asia/Tehran", "Asia/Tehran"),
 | 
			
		||||
                    ("Asia/Tel_Aviv", "Asia/Tel_Aviv"),
 | 
			
		||||
                    ("Asia/Thimbu", "Asia/Thimbu"),
 | 
			
		||||
                    ("Asia/Thimphu", "Asia/Thimphu"),
 | 
			
		||||
                    ("Asia/Tokyo", "Asia/Tokyo"),
 | 
			
		||||
                    ("Asia/Tomsk", "Asia/Tomsk"),
 | 
			
		||||
                    ("Asia/Ujung_Pandang", "Asia/Ujung_Pandang"),
 | 
			
		||||
                    ("Asia/Ulaanbaatar", "Asia/Ulaanbaatar"),
 | 
			
		||||
                    ("Asia/Ulan_Bator", "Asia/Ulan_Bator"),
 | 
			
		||||
                    ("Asia/Urumqi", "Asia/Urumqi"),
 | 
			
		||||
                    ("Asia/Ust-Nera", "Asia/Ust-Nera"),
 | 
			
		||||
                    ("Asia/Vientiane", "Asia/Vientiane"),
 | 
			
		||||
                    ("Asia/Vladivostok", "Asia/Vladivostok"),
 | 
			
		||||
                    ("Asia/Yakutsk", "Asia/Yakutsk"),
 | 
			
		||||
                    ("Asia/Yangon", "Asia/Yangon"),
 | 
			
		||||
                    ("Asia/Yekaterinburg", "Asia/Yekaterinburg"),
 | 
			
		||||
                    ("Asia/Yerevan", "Asia/Yerevan"),
 | 
			
		||||
                    ("Atlantic/Azores", "Atlantic/Azores"),
 | 
			
		||||
                    ("Atlantic/Bermuda", "Atlantic/Bermuda"),
 | 
			
		||||
                    ("Atlantic/Canary", "Atlantic/Canary"),
 | 
			
		||||
                    ("Atlantic/Cape_Verde", "Atlantic/Cape_Verde"),
 | 
			
		||||
                    ("Atlantic/Faeroe", "Atlantic/Faeroe"),
 | 
			
		||||
                    ("Atlantic/Faroe", "Atlantic/Faroe"),
 | 
			
		||||
                    ("Atlantic/Jan_Mayen", "Atlantic/Jan_Mayen"),
 | 
			
		||||
                    ("Atlantic/Madeira", "Atlantic/Madeira"),
 | 
			
		||||
                    ("Atlantic/Reykjavik", "Atlantic/Reykjavik"),
 | 
			
		||||
                    ("Atlantic/South_Georgia", "Atlantic/South_Georgia"),
 | 
			
		||||
                    ("Atlantic/St_Helena", "Atlantic/St_Helena"),
 | 
			
		||||
                    ("Atlantic/Stanley", "Atlantic/Stanley"),
 | 
			
		||||
                    ("Australia/ACT", "Australia/ACT"),
 | 
			
		||||
                    ("Australia/Adelaide", "Australia/Adelaide"),
 | 
			
		||||
                    ("Australia/Brisbane", "Australia/Brisbane"),
 | 
			
		||||
                    ("Australia/Broken_Hill", "Australia/Broken_Hill"),
 | 
			
		||||
                    ("Australia/Canberra", "Australia/Canberra"),
 | 
			
		||||
                    ("Australia/Currie", "Australia/Currie"),
 | 
			
		||||
                    ("Australia/Darwin", "Australia/Darwin"),
 | 
			
		||||
                    ("Australia/Eucla", "Australia/Eucla"),
 | 
			
		||||
                    ("Australia/Hobart", "Australia/Hobart"),
 | 
			
		||||
                    ("Australia/LHI", "Australia/LHI"),
 | 
			
		||||
                    ("Australia/Lindeman", "Australia/Lindeman"),
 | 
			
		||||
                    ("Australia/Lord_Howe", "Australia/Lord_Howe"),
 | 
			
		||||
                    ("Australia/Melbourne", "Australia/Melbourne"),
 | 
			
		||||
                    ("Australia/NSW", "Australia/NSW"),
 | 
			
		||||
                    ("Australia/North", "Australia/North"),
 | 
			
		||||
                    ("Australia/Perth", "Australia/Perth"),
 | 
			
		||||
                    ("Australia/Queensland", "Australia/Queensland"),
 | 
			
		||||
                    ("Australia/South", "Australia/South"),
 | 
			
		||||
                    ("Australia/Sydney", "Australia/Sydney"),
 | 
			
		||||
                    ("Australia/Tasmania", "Australia/Tasmania"),
 | 
			
		||||
                    ("Australia/Victoria", "Australia/Victoria"),
 | 
			
		||||
                    ("Australia/West", "Australia/West"),
 | 
			
		||||
                    ("Australia/Yancowinna", "Australia/Yancowinna"),
 | 
			
		||||
                    ("Brazil/Acre", "Brazil/Acre"),
 | 
			
		||||
                    ("Brazil/DeNoronha", "Brazil/DeNoronha"),
 | 
			
		||||
                    ("Brazil/East", "Brazil/East"),
 | 
			
		||||
                    ("Brazil/West", "Brazil/West"),
 | 
			
		||||
                    ("CET", "CET"),
 | 
			
		||||
                    ("CST6CDT", "CST6CDT"),
 | 
			
		||||
                    ("Canada/Atlantic", "Canada/Atlantic"),
 | 
			
		||||
                    ("Canada/Central", "Canada/Central"),
 | 
			
		||||
                    ("Canada/Eastern", "Canada/Eastern"),
 | 
			
		||||
                    ("Canada/Mountain", "Canada/Mountain"),
 | 
			
		||||
                    ("Canada/Newfoundland", "Canada/Newfoundland"),
 | 
			
		||||
                    ("Canada/Pacific", "Canada/Pacific"),
 | 
			
		||||
                    ("Canada/Saskatchewan", "Canada/Saskatchewan"),
 | 
			
		||||
                    ("Canada/Yukon", "Canada/Yukon"),
 | 
			
		||||
                    ("Chile/Continental", "Chile/Continental"),
 | 
			
		||||
                    ("Chile/EasterIsland", "Chile/EasterIsland"),
 | 
			
		||||
                    ("Cuba", "Cuba"),
 | 
			
		||||
                    ("EET", "EET"),
 | 
			
		||||
                    ("EST", "EST"),
 | 
			
		||||
                    ("EST5EDT", "EST5EDT"),
 | 
			
		||||
                    ("Egypt", "Egypt"),
 | 
			
		||||
                    ("Eire", "Eire"),
 | 
			
		||||
                    ("Etc/GMT", "Etc/GMT"),
 | 
			
		||||
                    ("Etc/GMT+0", "Etc/GMT+0"),
 | 
			
		||||
                    ("Etc/GMT+1", "Etc/GMT+1"),
 | 
			
		||||
                    ("Etc/GMT+10", "Etc/GMT+10"),
 | 
			
		||||
                    ("Etc/GMT+11", "Etc/GMT+11"),
 | 
			
		||||
                    ("Etc/GMT+12", "Etc/GMT+12"),
 | 
			
		||||
                    ("Etc/GMT+2", "Etc/GMT+2"),
 | 
			
		||||
                    ("Etc/GMT+3", "Etc/GMT+3"),
 | 
			
		||||
                    ("Etc/GMT+4", "Etc/GMT+4"),
 | 
			
		||||
                    ("Etc/GMT+5", "Etc/GMT+5"),
 | 
			
		||||
                    ("Etc/GMT+6", "Etc/GMT+6"),
 | 
			
		||||
                    ("Etc/GMT+7", "Etc/GMT+7"),
 | 
			
		||||
                    ("Etc/GMT+8", "Etc/GMT+8"),
 | 
			
		||||
                    ("Etc/GMT+9", "Etc/GMT+9"),
 | 
			
		||||
                    ("Etc/GMT-0", "Etc/GMT-0"),
 | 
			
		||||
                    ("Etc/GMT-1", "Etc/GMT-1"),
 | 
			
		||||
                    ("Etc/GMT-10", "Etc/GMT-10"),
 | 
			
		||||
                    ("Etc/GMT-11", "Etc/GMT-11"),
 | 
			
		||||
                    ("Etc/GMT-12", "Etc/GMT-12"),
 | 
			
		||||
                    ("Etc/GMT-13", "Etc/GMT-13"),
 | 
			
		||||
                    ("Etc/GMT-14", "Etc/GMT-14"),
 | 
			
		||||
                    ("Etc/GMT-2", "Etc/GMT-2"),
 | 
			
		||||
                    ("Etc/GMT-3", "Etc/GMT-3"),
 | 
			
		||||
                    ("Etc/GMT-4", "Etc/GMT-4"),
 | 
			
		||||
                    ("Etc/GMT-5", "Etc/GMT-5"),
 | 
			
		||||
                    ("Etc/GMT-6", "Etc/GMT-6"),
 | 
			
		||||
                    ("Etc/GMT-7", "Etc/GMT-7"),
 | 
			
		||||
                    ("Etc/GMT-8", "Etc/GMT-8"),
 | 
			
		||||
                    ("Etc/GMT-9", "Etc/GMT-9"),
 | 
			
		||||
                    ("Etc/GMT0", "Etc/GMT0"),
 | 
			
		||||
                    ("Etc/Greenwich", "Etc/Greenwich"),
 | 
			
		||||
                    ("Etc/UCT", "Etc/UCT"),
 | 
			
		||||
                    ("Etc/UTC", "Etc/UTC"),
 | 
			
		||||
                    ("Etc/Universal", "Etc/Universal"),
 | 
			
		||||
                    ("Etc/Zulu", "Etc/Zulu"),
 | 
			
		||||
                    ("Europe/Amsterdam", "Europe/Amsterdam"),
 | 
			
		||||
                    ("Europe/Andorra", "Europe/Andorra"),
 | 
			
		||||
                    ("Europe/Astrakhan", "Europe/Astrakhan"),
 | 
			
		||||
                    ("Europe/Athens", "Europe/Athens"),
 | 
			
		||||
                    ("Europe/Belfast", "Europe/Belfast"),
 | 
			
		||||
                    ("Europe/Belgrade", "Europe/Belgrade"),
 | 
			
		||||
                    ("Europe/Berlin", "Europe/Berlin"),
 | 
			
		||||
                    ("Europe/Bratislava", "Europe/Bratislava"),
 | 
			
		||||
                    ("Europe/Brussels", "Europe/Brussels"),
 | 
			
		||||
                    ("Europe/Bucharest", "Europe/Bucharest"),
 | 
			
		||||
                    ("Europe/Budapest", "Europe/Budapest"),
 | 
			
		||||
                    ("Europe/Busingen", "Europe/Busingen"),
 | 
			
		||||
                    ("Europe/Chisinau", "Europe/Chisinau"),
 | 
			
		||||
                    ("Europe/Copenhagen", "Europe/Copenhagen"),
 | 
			
		||||
                    ("Europe/Dublin", "Europe/Dublin"),
 | 
			
		||||
                    ("Europe/Gibraltar", "Europe/Gibraltar"),
 | 
			
		||||
                    ("Europe/Guernsey", "Europe/Guernsey"),
 | 
			
		||||
                    ("Europe/Helsinki", "Europe/Helsinki"),
 | 
			
		||||
                    ("Europe/Isle_of_Man", "Europe/Isle_of_Man"),
 | 
			
		||||
                    ("Europe/Istanbul", "Europe/Istanbul"),
 | 
			
		||||
                    ("Europe/Jersey", "Europe/Jersey"),
 | 
			
		||||
                    ("Europe/Kaliningrad", "Europe/Kaliningrad"),
 | 
			
		||||
                    ("Europe/Kiev", "Europe/Kiev"),
 | 
			
		||||
                    ("Europe/Kirov", "Europe/Kirov"),
 | 
			
		||||
                    ("Europe/Kyiv", "Europe/Kyiv"),
 | 
			
		||||
                    ("Europe/Lisbon", "Europe/Lisbon"),
 | 
			
		||||
                    ("Europe/Ljubljana", "Europe/Ljubljana"),
 | 
			
		||||
                    ("Europe/London", "Europe/London"),
 | 
			
		||||
                    ("Europe/Luxembourg", "Europe/Luxembourg"),
 | 
			
		||||
                    ("Europe/Madrid", "Europe/Madrid"),
 | 
			
		||||
                    ("Europe/Malta", "Europe/Malta"),
 | 
			
		||||
                    ("Europe/Mariehamn", "Europe/Mariehamn"),
 | 
			
		||||
                    ("Europe/Minsk", "Europe/Minsk"),
 | 
			
		||||
                    ("Europe/Monaco", "Europe/Monaco"),
 | 
			
		||||
                    ("Europe/Moscow", "Europe/Moscow"),
 | 
			
		||||
                    ("Europe/Nicosia", "Europe/Nicosia"),
 | 
			
		||||
                    ("Europe/Oslo", "Europe/Oslo"),
 | 
			
		||||
                    ("Europe/Paris", "Europe/Paris"),
 | 
			
		||||
                    ("Europe/Podgorica", "Europe/Podgorica"),
 | 
			
		||||
                    ("Europe/Prague", "Europe/Prague"),
 | 
			
		||||
                    ("Europe/Riga", "Europe/Riga"),
 | 
			
		||||
                    ("Europe/Rome", "Europe/Rome"),
 | 
			
		||||
                    ("Europe/Samara", "Europe/Samara"),
 | 
			
		||||
                    ("Europe/San_Marino", "Europe/San_Marino"),
 | 
			
		||||
                    ("Europe/Sarajevo", "Europe/Sarajevo"),
 | 
			
		||||
                    ("Europe/Saratov", "Europe/Saratov"),
 | 
			
		||||
                    ("Europe/Simferopol", "Europe/Simferopol"),
 | 
			
		||||
                    ("Europe/Skopje", "Europe/Skopje"),
 | 
			
		||||
                    ("Europe/Sofia", "Europe/Sofia"),
 | 
			
		||||
                    ("Europe/Stockholm", "Europe/Stockholm"),
 | 
			
		||||
                    ("Europe/Tallinn", "Europe/Tallinn"),
 | 
			
		||||
                    ("Europe/Tirane", "Europe/Tirane"),
 | 
			
		||||
                    ("Europe/Tiraspol", "Europe/Tiraspol"),
 | 
			
		||||
                    ("Europe/Ulyanovsk", "Europe/Ulyanovsk"),
 | 
			
		||||
                    ("Europe/Uzhgorod", "Europe/Uzhgorod"),
 | 
			
		||||
                    ("Europe/Vaduz", "Europe/Vaduz"),
 | 
			
		||||
                    ("Europe/Vatican", "Europe/Vatican"),
 | 
			
		||||
                    ("Europe/Vienna", "Europe/Vienna"),
 | 
			
		||||
                    ("Europe/Vilnius", "Europe/Vilnius"),
 | 
			
		||||
                    ("Europe/Volgograd", "Europe/Volgograd"),
 | 
			
		||||
                    ("Europe/Warsaw", "Europe/Warsaw"),
 | 
			
		||||
                    ("Europe/Zagreb", "Europe/Zagreb"),
 | 
			
		||||
                    ("Europe/Zaporozhye", "Europe/Zaporozhye"),
 | 
			
		||||
                    ("Europe/Zurich", "Europe/Zurich"),
 | 
			
		||||
                    ("GB", "GB"),
 | 
			
		||||
                    ("GB-Eire", "GB-Eire"),
 | 
			
		||||
                    ("GMT", "GMT"),
 | 
			
		||||
                    ("GMT+0", "GMT+0"),
 | 
			
		||||
                    ("GMT-0", "GMT-0"),
 | 
			
		||||
                    ("GMT0", "GMT0"),
 | 
			
		||||
                    ("Greenwich", "Greenwich"),
 | 
			
		||||
                    ("HST", "HST"),
 | 
			
		||||
                    ("Hongkong", "Hongkong"),
 | 
			
		||||
                    ("Iceland", "Iceland"),
 | 
			
		||||
                    ("Indian/Antananarivo", "Indian/Antananarivo"),
 | 
			
		||||
                    ("Indian/Chagos", "Indian/Chagos"),
 | 
			
		||||
                    ("Indian/Christmas", "Indian/Christmas"),
 | 
			
		||||
                    ("Indian/Cocos", "Indian/Cocos"),
 | 
			
		||||
                    ("Indian/Comoro", "Indian/Comoro"),
 | 
			
		||||
                    ("Indian/Kerguelen", "Indian/Kerguelen"),
 | 
			
		||||
                    ("Indian/Mahe", "Indian/Mahe"),
 | 
			
		||||
                    ("Indian/Maldives", "Indian/Maldives"),
 | 
			
		||||
                    ("Indian/Mauritius", "Indian/Mauritius"),
 | 
			
		||||
                    ("Indian/Mayotte", "Indian/Mayotte"),
 | 
			
		||||
                    ("Indian/Reunion", "Indian/Reunion"),
 | 
			
		||||
                    ("Iran", "Iran"),
 | 
			
		||||
                    ("Israel", "Israel"),
 | 
			
		||||
                    ("Jamaica", "Jamaica"),
 | 
			
		||||
                    ("Japan", "Japan"),
 | 
			
		||||
                    ("Kwajalein", "Kwajalein"),
 | 
			
		||||
                    ("Libya", "Libya"),
 | 
			
		||||
                    ("MET", "MET"),
 | 
			
		||||
                    ("MST", "MST"),
 | 
			
		||||
                    ("MST7MDT", "MST7MDT"),
 | 
			
		||||
                    ("Mexico/BajaNorte", "Mexico/BajaNorte"),
 | 
			
		||||
                    ("Mexico/BajaSur", "Mexico/BajaSur"),
 | 
			
		||||
                    ("Mexico/General", "Mexico/General"),
 | 
			
		||||
                    ("NZ", "NZ"),
 | 
			
		||||
                    ("NZ-CHAT", "NZ-CHAT"),
 | 
			
		||||
                    ("Navajo", "Navajo"),
 | 
			
		||||
                    ("PRC", "PRC"),
 | 
			
		||||
                    ("PST8PDT", "PST8PDT"),
 | 
			
		||||
                    ("Pacific/Apia", "Pacific/Apia"),
 | 
			
		||||
                    ("Pacific/Auckland", "Pacific/Auckland"),
 | 
			
		||||
                    ("Pacific/Bougainville", "Pacific/Bougainville"),
 | 
			
		||||
                    ("Pacific/Chatham", "Pacific/Chatham"),
 | 
			
		||||
                    ("Pacific/Chuuk", "Pacific/Chuuk"),
 | 
			
		||||
                    ("Pacific/Easter", "Pacific/Easter"),
 | 
			
		||||
                    ("Pacific/Efate", "Pacific/Efate"),
 | 
			
		||||
                    ("Pacific/Enderbury", "Pacific/Enderbury"),
 | 
			
		||||
                    ("Pacific/Fakaofo", "Pacific/Fakaofo"),
 | 
			
		||||
                    ("Pacific/Fiji", "Pacific/Fiji"),
 | 
			
		||||
                    ("Pacific/Funafuti", "Pacific/Funafuti"),
 | 
			
		||||
                    ("Pacific/Galapagos", "Pacific/Galapagos"),
 | 
			
		||||
                    ("Pacific/Gambier", "Pacific/Gambier"),
 | 
			
		||||
                    ("Pacific/Guadalcanal", "Pacific/Guadalcanal"),
 | 
			
		||||
                    ("Pacific/Guam", "Pacific/Guam"),
 | 
			
		||||
                    ("Pacific/Honolulu", "Pacific/Honolulu"),
 | 
			
		||||
                    ("Pacific/Johnston", "Pacific/Johnston"),
 | 
			
		||||
                    ("Pacific/Kanton", "Pacific/Kanton"),
 | 
			
		||||
                    ("Pacific/Kiritimati", "Pacific/Kiritimati"),
 | 
			
		||||
                    ("Pacific/Kosrae", "Pacific/Kosrae"),
 | 
			
		||||
                    ("Pacific/Kwajalein", "Pacific/Kwajalein"),
 | 
			
		||||
                    ("Pacific/Majuro", "Pacific/Majuro"),
 | 
			
		||||
                    ("Pacific/Marquesas", "Pacific/Marquesas"),
 | 
			
		||||
                    ("Pacific/Midway", "Pacific/Midway"),
 | 
			
		||||
                    ("Pacific/Nauru", "Pacific/Nauru"),
 | 
			
		||||
                    ("Pacific/Niue", "Pacific/Niue"),
 | 
			
		||||
                    ("Pacific/Norfolk", "Pacific/Norfolk"),
 | 
			
		||||
                    ("Pacific/Noumea", "Pacific/Noumea"),
 | 
			
		||||
                    ("Pacific/Pago_Pago", "Pacific/Pago_Pago"),
 | 
			
		||||
                    ("Pacific/Palau", "Pacific/Palau"),
 | 
			
		||||
                    ("Pacific/Pitcairn", "Pacific/Pitcairn"),
 | 
			
		||||
                    ("Pacific/Pohnpei", "Pacific/Pohnpei"),
 | 
			
		||||
                    ("Pacific/Ponape", "Pacific/Ponape"),
 | 
			
		||||
                    ("Pacific/Port_Moresby", "Pacific/Port_Moresby"),
 | 
			
		||||
                    ("Pacific/Rarotonga", "Pacific/Rarotonga"),
 | 
			
		||||
                    ("Pacific/Saipan", "Pacific/Saipan"),
 | 
			
		||||
                    ("Pacific/Samoa", "Pacific/Samoa"),
 | 
			
		||||
                    ("Pacific/Tahiti", "Pacific/Tahiti"),
 | 
			
		||||
                    ("Pacific/Tarawa", "Pacific/Tarawa"),
 | 
			
		||||
                    ("Pacific/Tongatapu", "Pacific/Tongatapu"),
 | 
			
		||||
                    ("Pacific/Truk", "Pacific/Truk"),
 | 
			
		||||
                    ("Pacific/Wake", "Pacific/Wake"),
 | 
			
		||||
                    ("Pacific/Wallis", "Pacific/Wallis"),
 | 
			
		||||
                    ("Pacific/Yap", "Pacific/Yap"),
 | 
			
		||||
                    ("Poland", "Poland"),
 | 
			
		||||
                    ("Portugal", "Portugal"),
 | 
			
		||||
                    ("ROC", "ROC"),
 | 
			
		||||
                    ("ROK", "ROK"),
 | 
			
		||||
                    ("Singapore", "Singapore"),
 | 
			
		||||
                    ("Turkey", "Turkey"),
 | 
			
		||||
                    ("UCT", "UCT"),
 | 
			
		||||
                    ("US/Alaska", "US/Alaska"),
 | 
			
		||||
                    ("US/Aleutian", "US/Aleutian"),
 | 
			
		||||
                    ("US/Arizona", "US/Arizona"),
 | 
			
		||||
                    ("US/Central", "US/Central"),
 | 
			
		||||
                    ("US/East-Indiana", "US/East-Indiana"),
 | 
			
		||||
                    ("US/Eastern", "US/Eastern"),
 | 
			
		||||
                    ("US/Hawaii", "US/Hawaii"),
 | 
			
		||||
                    ("US/Indiana-Starke", "US/Indiana-Starke"),
 | 
			
		||||
                    ("US/Michigan", "US/Michigan"),
 | 
			
		||||
                    ("US/Mountain", "US/Mountain"),
 | 
			
		||||
                    ("US/Pacific", "US/Pacific"),
 | 
			
		||||
                    ("US/Samoa", "US/Samoa"),
 | 
			
		||||
                    ("UTC", "UTC"),
 | 
			
		||||
                    ("Universal", "Universal"),
 | 
			
		||||
                    ("W-SU", "W-SU"),
 | 
			
		||||
                    ("WET", "WET"),
 | 
			
		||||
                    ("Zulu", "Zulu"),
 | 
			
		||||
                ],
 | 
			
		||||
                default="America/Los_Angeles",
 | 
			
		||||
                max_length=255,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -182,10 +182,10 @@ class CoreSettings(BaseAuditModel):
 | 
			
		||||
        test: bool = False,
 | 
			
		||||
    ) -> tuple[str, bool]:
 | 
			
		||||
        if test and not self.email_is_configured:
 | 
			
		||||
            return ("There needs to be at least one email recipient configured", False)
 | 
			
		||||
            return "There needs to be at least one email recipient configured", False
 | 
			
		||||
        # return since email must be configured to continue
 | 
			
		||||
        elif not self.email_is_configured:
 | 
			
		||||
            return ("SMTP messaging not configured.", False)
 | 
			
		||||
            return "SMTP messaging not configured.", False
 | 
			
		||||
 | 
			
		||||
        # override email from if alert_template is passed and is set
 | 
			
		||||
        if alert_template and alert_template.email_from:
 | 
			
		||||
@@ -199,7 +199,7 @@ class CoreSettings(BaseAuditModel):
 | 
			
		||||
        elif self.email_alert_recipients:
 | 
			
		||||
            email_recipients = ", ".join(cast(List[str], self.email_alert_recipients))
 | 
			
		||||
        else:
 | 
			
		||||
            return ("There needs to be at least one email recipient configured", False)
 | 
			
		||||
            return "There needs to be at least one email recipient configured", False
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            msg = EmailMessage()
 | 
			
		||||
@@ -226,12 +226,12 @@ class CoreSettings(BaseAuditModel):
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            DebugLog.error(message=f"Sending email failed with error: {e}")
 | 
			
		||||
            if test:
 | 
			
		||||
                return (str(e), False)
 | 
			
		||||
                return str(e), False
 | 
			
		||||
 | 
			
		||||
        if test:
 | 
			
		||||
            return ("Email test ok!", True)
 | 
			
		||||
            return "Email test ok!", True
 | 
			
		||||
 | 
			
		||||
        return ("ok", True)
 | 
			
		||||
        return "ok", True
 | 
			
		||||
 | 
			
		||||
    def send_sms(
 | 
			
		||||
        self,
 | 
			
		||||
@@ -240,7 +240,7 @@ class CoreSettings(BaseAuditModel):
 | 
			
		||||
        test: bool = False,
 | 
			
		||||
    ) -> tuple[str, bool]:
 | 
			
		||||
        if not self.sms_is_configured:
 | 
			
		||||
            return ("Sms alerting is not setup correctly.", False)
 | 
			
		||||
            return "Sms alerting is not setup correctly.", False
 | 
			
		||||
 | 
			
		||||
        # override email recipients if alert_template is passed and is set
 | 
			
		||||
        if alert_template and alert_template.text_recipients:
 | 
			
		||||
@@ -248,7 +248,7 @@ class CoreSettings(BaseAuditModel):
 | 
			
		||||
        elif self.sms_alert_recipients:
 | 
			
		||||
            text_recipients = cast(List[str], self.sms_alert_recipients)
 | 
			
		||||
        else:
 | 
			
		||||
            return ("No sms recipients found", False)
 | 
			
		||||
            return "No sms recipients found", False
 | 
			
		||||
 | 
			
		||||
        tw_client = TwClient(self.twilio_account_sid, self.twilio_auth_token)
 | 
			
		||||
        for num in text_recipients:
 | 
			
		||||
@@ -257,12 +257,12 @@ class CoreSettings(BaseAuditModel):
 | 
			
		||||
            except TwilioRestException as e:
 | 
			
		||||
                DebugLog.error(message=f"SMS failed to send: {e}")
 | 
			
		||||
                if test:
 | 
			
		||||
                    return (str(e), False)
 | 
			
		||||
                    return str(e), False
 | 
			
		||||
 | 
			
		||||
        if test:
 | 
			
		||||
            return ("SMS Test sent successfully!", True)
 | 
			
		||||
            return "SMS Test sent successfully!", True
 | 
			
		||||
 | 
			
		||||
        return ("ok", True)
 | 
			
		||||
        return "ok", True
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def serialize(core):
 | 
			
		||||
 
 | 
			
		||||
@@ -1,39 +1,39 @@
 | 
			
		||||
asgiref==3.5.2
 | 
			
		||||
celery==5.2.7
 | 
			
		||||
certifi==2022.6.15
 | 
			
		||||
certifi==2022.6.15.1
 | 
			
		||||
cffi==1.15.1
 | 
			
		||||
channels==3.0.5
 | 
			
		||||
channels_redis==3.4.1
 | 
			
		||||
chardet==4.0.0
 | 
			
		||||
cryptography==37.0.4
 | 
			
		||||
cryptography==38.0.1
 | 
			
		||||
daphne==3.0.2
 | 
			
		||||
Django==4.0.6
 | 
			
		||||
Django==4.1.1
 | 
			
		||||
django-cors-headers==3.13.0
 | 
			
		||||
django-ipware==4.0.2
 | 
			
		||||
django-rest-knox==4.2.0
 | 
			
		||||
djangorestframework==3.13.1
 | 
			
		||||
future==0.18.2
 | 
			
		||||
msgpack==1.0.4
 | 
			
		||||
nats-py==2.1.4
 | 
			
		||||
psutil==5.9.1
 | 
			
		||||
nats-py==2.1.7
 | 
			
		||||
psutil==5.9.2
 | 
			
		||||
psycopg2-binary==2.9.3
 | 
			
		||||
pycparser==2.21
 | 
			
		||||
pycryptodome==3.15.0
 | 
			
		||||
pyotp==2.6.0
 | 
			
		||||
pyotp==2.7.0
 | 
			
		||||
pyparsing==3.0.9
 | 
			
		||||
pytz==2022.1
 | 
			
		||||
pytz==2022.2.1
 | 
			
		||||
qrcode==7.3.1
 | 
			
		||||
redis==4.3.4
 | 
			
		||||
hiredis==2.0.0
 | 
			
		||||
requests==2.28.1
 | 
			
		||||
six==1.16.0
 | 
			
		||||
sqlparse==0.4.2
 | 
			
		||||
twilio==7.12.0
 | 
			
		||||
urllib3==1.26.11
 | 
			
		||||
twilio==7.14.0
 | 
			
		||||
urllib3==1.26.12
 | 
			
		||||
uWSGI==2.0.20
 | 
			
		||||
validators==0.20.0
 | 
			
		||||
vine==5.0.0
 | 
			
		||||
websockets==10.3
 | 
			
		||||
zipp==3.8.1
 | 
			
		||||
drf_spectacular==0.22.1
 | 
			
		||||
drf-spectacular==0.23.1
 | 
			
		||||
meshctrl==0.1.15
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ def process_nats_response(data: Union[str, Dict]) -> Tuple[bool, bool, str]:
 | 
			
		||||
        else "timeout"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    return (success, natserror, errormsg)
 | 
			
		||||
    return success, natserror, errormsg
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GetServices(APIView):
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
from django.core.management.base import BaseCommand
 | 
			
		||||
 | 
			
		||||
from agents.models import Agent
 | 
			
		||||
from software.models import InstalledSoftware
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Command(BaseCommand):
 | 
			
		||||
@@ -12,22 +12,15 @@ class Command(BaseCommand):
 | 
			
		||||
    def handle(self, *args, **kwargs):
 | 
			
		||||
        search = kwargs["name"].lower()
 | 
			
		||||
 | 
			
		||||
        agents = Agent.objects.all()
 | 
			
		||||
        for agent in agents:
 | 
			
		||||
            try:
 | 
			
		||||
                sw = agent.installedsoftware_set.first().software
 | 
			
		||||
            except:
 | 
			
		||||
                self.stdout.write(
 | 
			
		||||
                    self.style.ERROR(
 | 
			
		||||
                        f"Agent {agent.hostname} missing software list. Try manually refreshing it from the web UI from the software tab."
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
                continue
 | 
			
		||||
            for i in sw:
 | 
			
		||||
                if search in i["name"].lower():
 | 
			
		||||
        all_sw = InstalledSoftware.objects.select_related(
 | 
			
		||||
            "agent", "agent__site", "agent__site__client"
 | 
			
		||||
        )
 | 
			
		||||
        for instance in all_sw.iterator(chunk_size=20):
 | 
			
		||||
            for sw in instance.software:
 | 
			
		||||
                if search in sw["name"].lower():
 | 
			
		||||
                    self.stdout.write(
 | 
			
		||||
                        self.style.SUCCESS(
 | 
			
		||||
                            f"Found {i['name']} installed on {agent.hostname}"
 | 
			
		||||
                            f"Found {sw['name']} installed on: {instance.agent.client.name}\\{instance.agent.site.name}\\{instance.agent.hostname}"
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                    break
 | 
			
		||||
 
 | 
			
		||||
@@ -61,4 +61,4 @@ class APIAuthentication(BaseAuthentication):
 | 
			
		||||
        if apikey.expiration and apikey.expiration < djangotime.now():
 | 
			
		||||
            raise exceptions.AuthenticationFailed(_("The token as expired."))
 | 
			
		||||
 | 
			
		||||
        return (apikey.user, apikey.key)
 | 
			
		||||
        return apikey.user, apikey.key
 | 
			
		||||
 
 | 
			
		||||
@@ -240,6 +240,14 @@ AGENT_DEFER = (
 | 
			
		||||
    "modified_time",
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
AGENT_TABLE_DEFER = (
 | 
			
		||||
    "services",
 | 
			
		||||
    "created_by",
 | 
			
		||||
    "created_time",
 | 
			
		||||
    "modified_by",
 | 
			
		||||
    "modified_time",
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
ONLINE_AGENTS = (
 | 
			
		||||
    "pk",
 | 
			
		||||
    "agent_id",
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ def get_certs() -> tuple[str, str]:
 | 
			
		||||
        cert_file = settings.CERT_FILE
 | 
			
		||||
        key_file = settings.KEY_FILE
 | 
			
		||||
 | 
			
		||||
    return (cert_file, key_file)
 | 
			
		||||
    return cert_file, key_file
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def notify_error(msg: str) -> Response:
 | 
			
		||||
@@ -33,7 +33,7 @@ def get_nats_ports() -> tuple[int, int]:
 | 
			
		||||
    nats_standard_port = getattr(settings, "NATS_STANDARD_PORT", 4222)
 | 
			
		||||
    nats_websocket_port = getattr(settings, "NATS_WEBSOCKET_PORT", 9235)
 | 
			
		||||
 | 
			
		||||
    return (nats_standard_port, nats_websocket_port)
 | 
			
		||||
    return nats_standard_port, nats_websocket_port
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def date_is_in_past(*, datetime_obj: "datetime", agent_tz: str) -> bool:
 | 
			
		||||
 
 | 
			
		||||
@@ -17,26 +17,26 @@ LINUX_AGENT_SCRIPT = BASE_DIR / "core" / "agent_linux.sh"
 | 
			
		||||
AUTH_USER_MODEL = "accounts.User"
 | 
			
		||||
 | 
			
		||||
# latest release
 | 
			
		||||
TRMM_VERSION = "0.14.5"
 | 
			
		||||
TRMM_VERSION = "0.14.8"
 | 
			
		||||
 | 
			
		||||
# https://github.com/amidaware/tacticalrmm-web
 | 
			
		||||
WEB_VERSION = "0.100.7"
 | 
			
		||||
WEB_VERSION = "0.100.9"
 | 
			
		||||
 | 
			
		||||
# bump this version everytime vue code is changed
 | 
			
		||||
# to alert user they need to manually refresh their browser
 | 
			
		||||
APP_VER = "0.0.168"
 | 
			
		||||
APP_VER = "0.0.170"
 | 
			
		||||
 | 
			
		||||
# https://github.com/amidaware/rmmagent
 | 
			
		||||
LATEST_AGENT_VER = "2.2.1"
 | 
			
		||||
LATEST_AGENT_VER = "2.3.1"
 | 
			
		||||
 | 
			
		||||
MESH_VER = "1.0.60"
 | 
			
		||||
MESH_VER = "1.0.85"
 | 
			
		||||
 | 
			
		||||
NATS_SERVER_VER = "2.8.4"
 | 
			
		||||
NATS_SERVER_VER = "2.9.0"
 | 
			
		||||
 | 
			
		||||
# for the update script, bump when need to recreate venv
 | 
			
		||||
PIP_VER = "31"
 | 
			
		||||
PIP_VER = "32"
 | 
			
		||||
 | 
			
		||||
SETUPTOOLS_VER = "62.6.0"
 | 
			
		||||
SETUPTOOLS_VER = "65.2.0"
 | 
			
		||||
WHEEL_VER = "0.37.1"
 | 
			
		||||
 | 
			
		||||
AGENT_BASE_URL = "https://agents.tacticalrmm.com"
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ def check_agent_update_schedule_task() -> None:
 | 
			
		||||
                if last_installed.strftime("%d/%m/%Y") == agent_localtime_now.strftime(
 | 
			
		||||
                    "%d/%m/%Y"
 | 
			
		||||
                ):
 | 
			
		||||
                    return
 | 
			
		||||
                    continue
 | 
			
		||||
 | 
			
		||||
            # check if schedule is set to daily/weekly and if now is the time to run
 | 
			
		||||
            if (
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
FROM nats:2.8.4-alpine
 | 
			
		||||
FROM nats:2.9.0-alpine
 | 
			
		||||
 | 
			
		||||
ENV TACTICAL_DIR /opt/tactical
 | 
			
		||||
ENV TACTICAL_READY_FILE ${TACTICAL_DIR}/tmp/tactical.ready
 | 
			
		||||
 
 | 
			
		||||
@@ -35,8 +35,7 @@ nginxdefaultconf='/etc/nginx/nginx.conf'
 | 
			
		||||
# increase default nginx worker connections
 | 
			
		||||
/bin/bash -c "sed -i 's/worker_connections.*/worker_connections ${WORKER_CONNECTIONS};/g' $nginxdefaultconf"
 | 
			
		||||
 | 
			
		||||
sed -i '1s/^/worker_rlimit_nofile 1000000;\
 | 
			
		||||
/' $nginxdefaultconf
 | 
			
		||||
grep -q -e 'worker_rlimit_nofile' "${nginxdefaultconf}" || sed -i -e '/worker_processes.*/a\' -e 'worker_rlimit_nofile 1000000;' "${nginxdefaultconf}"
 | 
			
		||||
 | 
			
		||||
if [[ $DEV -eq 1 ]]; then
 | 
			
		||||
    API_NGINX="
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
# creates python virtual env
 | 
			
		||||
FROM python:3.10.4-slim AS CREATE_VENV_STAGE
 | 
			
		||||
FROM python:3.10.6-slim AS CREATE_VENV_STAGE
 | 
			
		||||
 | 
			
		||||
ARG DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
 | 
			
		||||
@@ -21,14 +21,14 @@ RUN apt-get update && \
 | 
			
		||||
    pip install --no-cache-dir -r ${TACTICAL_TMP_DIR}/api/requirements.txt
 | 
			
		||||
 | 
			
		||||
# pulls community scripts from git repo
 | 
			
		||||
FROM python:3.10.4-slim AS GET_SCRIPTS_STAGE
 | 
			
		||||
FROM python:3.10.6-slim AS GET_SCRIPTS_STAGE
 | 
			
		||||
 | 
			
		||||
RUN apt-get update && \
 | 
			
		||||
    apt-get install -y --no-install-recommends git && \
 | 
			
		||||
    git clone https://github.com/amidaware/community-scripts.git /community-scripts
 | 
			
		||||
 | 
			
		||||
# runtime image
 | 
			
		||||
FROM python:3.10.4-slim
 | 
			
		||||
FROM python:3.10.6-slim
 | 
			
		||||
 | 
			
		||||
# set env variables
 | 
			
		||||
ENV VIRTUAL_ENV /opt/venv
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								go.mod
									
									
									
									
									
								
							@@ -1,23 +1,25 @@
 | 
			
		||||
module github.com/amidaware/tacticalrmm
 | 
			
		||||
 | 
			
		||||
go 1.18
 | 
			
		||||
go 1.19
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/golang/protobuf v1.5.2 // indirect
 | 
			
		||||
	github.com/jmoiron/sqlx v1.3.5
 | 
			
		||||
	github.com/lib/pq v1.10.6
 | 
			
		||||
	github.com/nats-io/nats-server/v2 v2.8.4 // indirect
 | 
			
		||||
	github.com/nats-io/nats.go v1.16.0
 | 
			
		||||
	github.com/lib/pq v1.10.7
 | 
			
		||||
	github.com/nats-io/nats-server/v2 v2.9.0 // indirect
 | 
			
		||||
	github.com/nats-io/nats.go v1.16.1-0.20220906180156-a1017eec10b0
 | 
			
		||||
	github.com/ugorji/go/codec v1.2.7
 | 
			
		||||
	github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139
 | 
			
		||||
	google.golang.org/protobuf v1.28.0 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require github.com/sirupsen/logrus v1.8.1
 | 
			
		||||
require github.com/sirupsen/logrus v1.9.0
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/nats-io/nkeys v0.3.0 // indirect
 | 
			
		||||
	github.com/nats-io/nuid v1.0.1 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
 | 
			
		||||
	golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b // indirect
 | 
			
		||||
	github.com/stretchr/testify v1.7.1 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
 | 
			
		||||
	golang.org/x/sys v0.0.0-20220906135438-9e1f76180b77 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								go.sum
									
									
									
									
									
								
							@@ -1,3 +1,4 @@
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
 | 
			
		||||
@@ -8,47 +9,53 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
 | 
			
		||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
			
		||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
 | 
			
		||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
 | 
			
		||||
github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4=
 | 
			
		||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
 | 
			
		||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
 | 
			
		||||
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
			
		||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
 | 
			
		||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
 | 
			
		||||
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
 | 
			
		||||
github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a h1:lem6QCvxR0Y28gth9P+wV2K/zYUUAkJ+55U8cpS0p5I=
 | 
			
		||||
github.com/nats-io/nats-server/v2 v2.8.4 h1:0jQzze1T9mECg8YZEl8+WYUXb9JKluJfCBriPUtluB4=
 | 
			
		||||
github.com/nats-io/nats-server/v2 v2.8.4/go.mod h1:8zZa+Al3WsESfmgSs98Fi06dRWLH5Bnq90m5bKD/eT4=
 | 
			
		||||
github.com/nats-io/nats.go v1.16.0 h1:zvLE7fGBQYW6MWaFaRdsgm9qT39PJDQoju+DS8KsO1g=
 | 
			
		||||
github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 | 
			
		||||
github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
 | 
			
		||||
github.com/nats-io/nats-server/v2 v2.9.0 h1:DLWu+7/VgGOoChcDKytnUZPAmudpv7o/MhKmNrnH1RE=
 | 
			
		||||
github.com/nats-io/nats-server/v2 v2.9.0/go.mod h1:BWKY6217RvhI+FDoOLZ2BH+hOC37xeKRBlQ1Lz7teKI=
 | 
			
		||||
github.com/nats-io/nats.go v1.16.1-0.20220906180156-a1017eec10b0 h1:dPUKD6Iv8M1y9MU8PK6H4a4/12yx5/CbaYWz/Z1arY8=
 | 
			
		||||
github.com/nats-io/nats.go v1.16.1-0.20220906180156-a1017eec10b0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 | 
			
		||||
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
 | 
			
		||||
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
 | 
			
		||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
 | 
			
		||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
 | 
			
		||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 | 
			
		||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
 | 
			
		||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
			
		||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
 | 
			
		||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
			
		||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
 | 
			
		||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
			
		||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
 | 
			
		||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
 | 
			
		||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
 | 
			
		||||
github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139 h1:PfOl03o+Y+svWrfXAAu1QWUDePu1yqTq0pf4rpnN8eA=
 | 
			
		||||
github.com/wh1te909/trmm-shared v0.0.0-20220227075846-f9f757361139/go.mod h1:ILUz1utl5KgwrxmNHv0RpgMtKeh8gPAABvK2MiXBqv8=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 | 
			
		||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220906135438-9e1f76180b77 h1:C1tElbkWrsSkn3IRl1GCW/gETw1TywWIPgwZtXTZbYg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220906135438-9e1f76180b77/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
 | 
			
		||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 | 
			
		||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 | 
			
		||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
 | 
			
		||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								install.sh
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								install.sh
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
SCRIPT_VERSION="66"
 | 
			
		||||
SCRIPT_VERSION="68"
 | 
			
		||||
SCRIPT_URL='https://raw.githubusercontent.com/amidaware/tacticalrmm/master/install.sh'
 | 
			
		||||
 | 
			
		||||
sudo apt install -y curl wget dirmngr gnupg lsb-release
 | 
			
		||||
@@ -12,7 +12,7 @@ RED='\033[0;31m'
 | 
			
		||||
NC='\033[0m'
 | 
			
		||||
 | 
			
		||||
SCRIPTS_DIR='/opt/trmm-community-scripts'
 | 
			
		||||
PYTHON_VER='3.10.4'
 | 
			
		||||
PYTHON_VER='3.10.6'
 | 
			
		||||
SETTINGS_FILE='/rmm/api/tacticalrmm/tacticalrmm/settings.py'
 | 
			
		||||
 | 
			
		||||
TMP_FILE=$(mktemp -p "" "rmminstall_XXXXXXXXXX")
 | 
			
		||||
@@ -265,9 +265,12 @@ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-
 | 
			
		||||
sudo apt update
 | 
			
		||||
sudo apt install -y postgresql-14
 | 
			
		||||
sleep 2
 | 
			
		||||
sudo systemctl enable postgresql
 | 
			
		||||
sudo systemctl restart postgresql
 | 
			
		||||
sleep 5
 | 
			
		||||
sudo systemctl enable --now postgresql
 | 
			
		||||
 | 
			
		||||
until pg_isready > /dev/null; do
 | 
			
		||||
  echo -ne "${GREEN}Waiting for PostgreSQL to be ready${NC}\n"
 | 
			
		||||
  sleep 3
 | 
			
		||||
 done
 | 
			
		||||
 | 
			
		||||
print_green 'Creating database for the rmm'
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.go
									
									
									
									
									
								
							@@ -12,7 +12,7 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	version = "3.1.0"
 | 
			
		||||
	version = "3.3.0"
 | 
			
		||||
	log     = logrus.New()
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -74,24 +74,15 @@ func Svc(logger *logrus.Logger, cfg string) {
 | 
			
		||||
					stmt := `
 | 
			
		||||
						UPDATE agents_agent
 | 
			
		||||
						SET hostname=$1, operating_system=$2,
 | 
			
		||||
						plat=$3, total_ram=$4, boot_time=$5, needs_reboot=$6, logged_in_username=$7
 | 
			
		||||
						WHERE agents_agent.agent_id=$8;`
 | 
			
		||||
						plat=$3, total_ram=$4, boot_time=$5, needs_reboot=$6, logged_in_username=$7, goarch=$8
 | 
			
		||||
						WHERE agents_agent.agent_id=$9;`
 | 
			
		||||
 | 
			
		||||
					logger.Debugln("Info", r)
 | 
			
		||||
					_, err = db.Exec(stmt, r.Hostname, r.OS, r.Platform, r.TotalRAM, r.BootTime, r.RebootNeeded, r.Username, r.Agentid)
 | 
			
		||||
					_, err = db.Exec(stmt, r.Hostname, r.OS, r.Platform, r.TotalRAM, r.BootTime, r.RebootNeeded, r.Username, r.GoArch, r.Agentid)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						logger.Errorln(err)
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					// TODO add this to main stmt once agent 2.0.0 has been out for a while
 | 
			
		||||
					if r.GoArch != "" {
 | 
			
		||||
						stmt = `UPDATE agents_agent SET goarch=$1 WHERE agents_agent.agent_id=$2;`
 | 
			
		||||
						_, err = db.Exec(stmt, r.GoArch, r.Agentid)
 | 
			
		||||
						if err != nil {
 | 
			
		||||
							logger.Errorln(err)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if r.Username != "None" {
 | 
			
		||||
						stmt = `UPDATE agents_agent SET last_logged_in_user=$1 WHERE agents_agent.agent_id=$2;`
 | 
			
		||||
						logger.Debugln("Updating last logged in user:", r.Username)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								restore.sh
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								restore.sh
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
SCRIPT_VERSION="40"
 | 
			
		||||
SCRIPT_VERSION="42"
 | 
			
		||||
SCRIPT_URL='https://raw.githubusercontent.com/amidaware/tacticalrmm/master/restore.sh'
 | 
			
		||||
 | 
			
		||||
sudo apt update
 | 
			
		||||
@@ -13,7 +13,7 @@ RED='\033[0;31m'
 | 
			
		||||
NC='\033[0m'
 | 
			
		||||
 | 
			
		||||
SCRIPTS_DIR='/opt/trmm-community-scripts'
 | 
			
		||||
PYTHON_VER='3.10.4'
 | 
			
		||||
PYTHON_VER='3.10.6'
 | 
			
		||||
SETTINGS_FILE='/rmm/api/tacticalrmm/tacticalrmm/settings.py'
 | 
			
		||||
 | 
			
		||||
TMP_FILE=$(mktemp -p "" "rmmrestore_XXXXXXXXXX")
 | 
			
		||||
@@ -175,7 +175,7 @@ print_green 'Restoring systemd services'
 | 
			
		||||
sudo cp $tmp_dir/systemd/* /etc/systemd/system/
 | 
			
		||||
sudo systemctl daemon-reload
 | 
			
		||||
 | 
			
		||||
print_green 'Installing Python 3.10.4'
 | 
			
		||||
print_green "Installing Python ${PYTHON_VER}"
 | 
			
		||||
 | 
			
		||||
sudo apt install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev libbz2-dev
 | 
			
		||||
numprocs=$(nproc)
 | 
			
		||||
@@ -200,8 +200,12 @@ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-
 | 
			
		||||
sudo apt update
 | 
			
		||||
sudo apt install -y postgresql-14
 | 
			
		||||
sleep 2
 | 
			
		||||
sudo systemctl enable postgresql
 | 
			
		||||
sudo systemctl restart postgresql
 | 
			
		||||
sudo systemctl enable --now postgresql
 | 
			
		||||
 | 
			
		||||
until pg_isready > /dev/null; do
 | 
			
		||||
  echo -ne "${GREEN}Waiting for PostgreSQL to be ready${NC}\n"
 | 
			
		||||
  sleep 3
 | 
			
		||||
 done
 | 
			
		||||
 | 
			
		||||
print_green 'Restoring MongoDB'
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -309,9 +309,9 @@ fi
 | 
			
		||||
	printf >&2 "\n\n"
 | 
			
		||||
 | 
			
		||||
#SSL Certificate check
 | 
			
		||||
cert=$(openssl verify -CAfile /etc/letsencrypt/live/$domain/chain.pem /etc/letsencrypt/live/$domain/cert.pem)
 | 
			
		||||
cert=$(sudo certbot certificates)
 | 
			
		||||
 | 
			
		||||
if [[ "$cert" == *"OK"* ]]; then
 | 
			
		||||
if [[ "$cert" != *"INVALID"* ]]; then
 | 
			
		||||
    echo -ne ${GREEN} SSL Certificate for $domain is fine  | tee -a checklog.log
 | 
			
		||||
	printf >&2 "\n\n"
 | 
			
		||||
 | 
			
		||||
@@ -319,6 +319,10 @@ else
 | 
			
		||||
    echo -ne ${RED} SSL Certificate has expired or doesnt exist for $domain  | tee -a checklog.log
 | 
			
		||||
	printf >&2 "\n\n"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Get List of Certbot Certificates
 | 
			
		||||
sudo certbot certificates | tee -a checklog.log
 | 
			
		||||
 | 
			
		||||
	echo -ne ${YELLOW} Getting summary output of logs | tee -a checklog.log  
 | 
			
		||||
 | 
			
		||||
tail /rmm/api/tacticalrmm/tacticalrmm/private/log/django_debug.log  | tee -a checklog.log
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
SCRIPT_VERSION="138"
 | 
			
		||||
SCRIPT_VERSION="139"
 | 
			
		||||
SCRIPT_URL='https://raw.githubusercontent.com/amidaware/tacticalrmm/master/update.sh'
 | 
			
		||||
LATEST_SETTINGS_URL='https://raw.githubusercontent.com/amidaware/tacticalrmm/master/api/tacticalrmm/tacticalrmm/settings.py'
 | 
			
		||||
YELLOW='\033[1;33m'
 | 
			
		||||
@@ -10,7 +10,7 @@ NC='\033[0m'
 | 
			
		||||
THIS_SCRIPT=$(readlink -f "$0")
 | 
			
		||||
 | 
			
		||||
SCRIPTS_DIR='/opt/trmm-community-scripts'
 | 
			
		||||
PYTHON_VER='3.10.4'
 | 
			
		||||
PYTHON_VER='3.10.6'
 | 
			
		||||
SETTINGS_FILE='/rmm/api/tacticalrmm/tacticalrmm/settings.py'
 | 
			
		||||
 | 
			
		||||
TMP_FILE=$(mktemp -p "" "rmmupdate_XXXXXXXXXX")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user