diff --git a/.env b/.env index 05ef05e..7a0f6d6 100644 --- a/.env +++ b/.env @@ -46,7 +46,7 @@ LOCK_DSN=flock ###< symfony/lock ### ###> symfony/mailer ### -# MAILER_DSN=null://null +MAILER_DSN=null://null ###< symfony/mailer ### ###> symfony/messenger ### @@ -60,6 +60,7 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0 MAILER_SENDER_NAME="Domain Watchdog" MAILER_SENDER_EMAIL=notifications@example.com REGISTRATION_ENABLED=true +REGISTRATION_VERIFY_EMAIL=false OAUTH_CLIENT_ID= OAUTH_CLIENT_SECRET= OAUTH_AUTHORIZATION_URL= diff --git a/README.md b/README.md index d745d3d..dc116c5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@

Domain Watchdog

Domain Watchdog

-

Your companion in the quest for domain names
domainwatchdog.eu »

+

Your companion in the quest for domain names
domainwatchdog.eu »


Domain Watchdog is a standalone application that utilizes RDAP to gather publicly accessible information about domain -names, track their history, and automatically purchase them. For more information please check [the wiki](https://github.com/maelgangloff/domain-watchdog/wiki) ! +names, track their history, and automatically purchase them. For more information please +check [the wiki](https://github.com/maelgangloff/domain-watchdog/wiki) ! ## Why use it? @@ -25,17 +26,20 @@ detailed history of events (ownership changes, renewals, etc.) is not feasible w ### Docker Deployment 1. Clone the repository -2. Build the Docker image locally +2. Modify environment variables (.env) and add static files to customize your instance (see [INSTALL.md](/INSTALL.md)) +3. Pull the latest version of the Domain Watchdog image from Docker Hub. ```shell - docker compose -f compose.yaml -f compose.prod.yaml build --pull --no-cache + docker compose pull ``` -3. Modify environment variables and add static files to customize your instance -4. Start the project in production environment +4. Start the project in production environment. If you want, you can also build the Docker image to use yourself. ```shell - docker compose -f compose.yaml -f compose.prod.yaml up + docker compose up ``` -## How it works? +By default, the container listens on http://localhost:8080, but you can configure this in environment variables. +See the [Docker Compose file](./docker-compose.yml). + +## Features ### RDAP search @@ -46,9 +50,9 @@ ICANN launched a global vote in 2023 to propose replacing the WHOIS protocol wit registrars will no longer be required to support WHOIS from 2025 (*WHOIS Sunset Date*).[^2] Domain Watchdog uses the RDAP protocol, which will soon be the new standard for retrieving information concerning domain -names. The data is organized in a SQL database to minimize space by ensuring an entity is not repeated. +names. -### Connector Provider +### Auto-purchase domain A connector is a way to order a domain name. It is important to mention that this project does not act as a payment intermediary. @@ -63,24 +67,19 @@ The table below lists the supported API connector providers: | GANDI | https://api.gandi.net/docs/domains/ | **Yes** | | NAMECHEAP | https://www.namecheap.com/support/api/methods/domains/create/ | | -### Watchlist +If a domain has expired and a connector is linked to the Watchlist, then Domain Watchdog will try to order it via the +connector provider's API. + +Note: If the same domain name is present on several Watchlists, it is not possible to predict in advance which user will +win the domain name. The choice is left to chance. + +### Monitoring A watchlist is a list of domain names, triggers and possibly an API connector. They allow you to follow the life of the listed domain names and send you a notification when a change has been detected. - -If a domain has expired and a connector is linked to the Watchlist, then Domain Watchdog will try to order it via the -connector provider's API. - -Note: If the same domain name is present on several Watchlists, on the same principle as the raise condition, it is not -possible to predict in advance which user will win the domain name. The choice is left to chance. - -## Useful documentation - -> [!NOTE] -> - [RFC 7482 : Registration Data Access Protocol (RDAP) Query Format](https://datatracker.ietf.org/doc/html/rfc7482) -> - [RFC 7483 : JSON Responses for the Registration Data Access Protocol (RDAP)](https://datatracker.ietf.org/doc/html/rfc7483) -> - [RFC 7484 : Finding the Authoritative Registration Data (RDAP) Service](https://datatracker.ietf.org/doc/html/rfc7484) +A notification to the user is sent when a new event occurs on one of the domain names in the Watchlist. This can be an +email or a chat via Webhook. An iCalendar export of events is possible. ## Disclaimer @@ -92,6 +91,13 @@ possible to predict in advance which user will win the domain name. The choice i > * The project installers are responsible for the use of their own instance. > * In no event the owner of this project will not be held responsible for other instances over which he has no control. +## Useful documentation + +> [!NOTE] +> - [RFC 7482 : Registration Data Access Protocol (RDAP) Query Format](https://datatracker.ietf.org/doc/html/rfc7482) +> - [RFC 7483 : JSON Responses for the Registration Data Access Protocol (RDAP)](https://datatracker.ietf.org/doc/html/rfc7483) +> - [RFC 7484 : Finding the Authoritative Registration Data (RDAP) Service](https://datatracker.ietf.org/doc/html/rfc7484) + ## Licensing This source code of this project is licensed under *GNU Affero General Public License v3.0 or later*. diff --git a/compose.override.yaml b/compose.override.yaml deleted file mode 100644 index dca2286..0000000 --- a/compose.override.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# Development environment override -services: - php: - build: - context: . - target: frankenphp_dev - volumes: - - ./:/app - - ./frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro - - ./frankenphp/conf.d/20-app.dev.ini:/usr/local/etc/php/app.conf.d/20-app.dev.ini:ro - # If you develop on Mac or Windows you can remove the vendor/ directory - # from the bind-mount for better performance by enabling the next line: - #- /app/vendor - environment: - # See https://xdebug.org/docs/all_settings#mode - XDEBUG_MODE: "${XDEBUG_MODE:-off}" - extra_hosts: - # Ensure that host.docker.internal is correctly defined on Linux - - host.docker.internal:host-gateway - tty: true - -###> doctrine/doctrine-bundle ### - database: - ports: - - "5432" -###< doctrine/doctrine-bundle ### - -###> symfony/mailer ### - mailer: - image: axllent/mailpit - ports: - - "1025" - - "8025" - environment: - MP_SMTP_AUTH_ACCEPT_ANY: 1 - MP_SMTP_AUTH_ALLOW_INSECURE: 1 -###< symfony/mailer ### diff --git a/compose.prod.yaml b/compose.prod.yaml deleted file mode 100644 index 5c953b8..0000000 --- a/compose.prod.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Production environment override -services: - php: - build: - context: . - target: frankenphp_prod - environment: - APP_SECRET: ${APP_SECRET} - - php-worker: - build: - context: . - target: frankenphp_prod - restart: always - command: php /app/bin/console messenger:consume --all --time-limit=3600 -vvv - environment: - DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@database:5432/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8} - diff --git a/compose.yaml b/compose.yaml deleted file mode 100644 index 564654c..0000000 --- a/compose.yaml +++ /dev/null @@ -1,53 +0,0 @@ -services: - php: - image: ${IMAGES_PREFIX:-}app-php - restart: unless-stopped - environment: - SERVER_NAME: ${SERVER_NAME:-localhost}, php:80 - # Run "composer require symfony/orm-pack" to install and configure Doctrine ORM - DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@database:5432/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8} - # The two next lines can be removed after initial installation - SYMFONY_VERSION: ${SYMFONY_VERSION:-} - STABILITY: ${STABILITY:-stable} - volumes: - - caddy_data:/data - - caddy_config:/config - ports: - # HTTP - - target: 80 - published: ${HTTP_PORT:-80} - protocol: tcp - # HTTPS - - target: 443 - published: ${HTTPS_PORT:-443} - protocol: tcp - # HTTP/3 - - target: 443 - published: ${HTTP3_PORT:-443} - protocol: udp - -###> doctrine/doctrine-bundle ### - database: - image: postgres:${POSTGRES_VERSION:-16}-alpine - environment: - POSTGRES_DB: ${POSTGRES_DB:-app} - # You should definitely change the password in production - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} - POSTGRES_USER: ${POSTGRES_USER:-app} - healthcheck: - test: ["CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}"] - timeout: 5s - retries: 5 - start_period: 60s - volumes: - - database_data:/var/lib/postgresql/data:rw - # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data! - # - ./docker/db/data:/var/lib/postgresql/data:rw -###< doctrine/doctrine-bundle ### - -volumes: - caddy_data: - caddy_config: -###> doctrine/doctrine-bundle ### - database_data: -###< doctrine/doctrine-bundle ### diff --git a/config/services.yaml b/config/services.yaml index fd5f9ad..c7deee0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -8,6 +8,7 @@ parameters: mailer_sender_name: '%env(string:MAILER_SENDER_NAME)%' oauth_enabled: '%env(OAUTH_CLIENT_ID)%' registration_enabled: '%env(bool:REGISTRATION_ENABLED)%' + registration_verify_email: '%env(bool:REGISTRATION_VERIFY_EMAIL)%' limited_features: '%env(bool:LIMITED_FEATURES)%' limit_max_watchlist: '%env(int:LIMIT_MAX_WATCHLIST)%' diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1ec9b7b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,49 @@ +# Please see https://github.com/maelgangloff/domain-watchdog +services: + domainwatchdog: + image: maelgangloff/domain-watchdog:latest + restart: unless-stopped + environment: + SERVER_NAME: http://${SERVER_NAME:-localhost} + DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@${POSTGRES_HOST:-database}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8} + APP_SECRET: ${APP_SECRET:-ChangeMe} + REGISTRATION_ENABLED: ${REGISTRATION_ENABLED:-true} + REGISTRATION_VERIFY_EMAIL: ${REGISTRATION_ENABLED:-false} + LIMITED_FEATURES: ${LIMITED_FEATURES:-false} + LIMIT_MAX_WATCHLIST: ${LIMIT_MAX_WATCHLIST:-0} + LIMIT_MAX_WATCHLIST_DOMAINS: ${LIMIT_MAX_WATCHLIST_DOMAINS:-0} + MAILER_DSN: ${MAILER_DSN:-null://null} + volumes: + - caddy_data:/data + - caddy_config:/config + - ./public/content:/app/public/content + ports: + - 127.0.0.1:8080:80 + + php-worker: + image: maelgangloff/domain-watchdog:latest + restart: always + command: php /app/bin/console messenger:consume --all --time-limit=3600 -vvv + environment: + DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-!ChangeMe!}@${POSTGRES_HOST:-database}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-app}?serverVersion=${POSTGRES_VERSION:-15}&charset=${POSTGRES_CHARSET:-utf8} + APP_SECRET: ${APP_SECRET:-ChangeMe} + MAILER_DSN: ${MAILER_DSN:-null://null} + + database: + image: postgres:${POSTGRES_VERSION:-16}-alpine + environment: + POSTGRES_DB: ${POSTGRES_DB:-app} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!} + POSTGRES_USER: ${POSTGRES_USER:-app} + healthcheck: + test: [ "CMD", "pg_isready", "-d", "${POSTGRES_DB:-app}", "-U", "${POSTGRES_USER:-app}" ] + timeout: 5s + retries: 5 + start_period: 60s + volumes: + - database_data:/var/lib/postgresql/data:rw + +volumes: + caddy_data: + caddy_config: + database_data: diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php index 1b44baf..e5a95cb 100644 --- a/src/Controller/RegistrationController.php +++ b/src/Controller/RegistrationController.php @@ -75,6 +75,25 @@ class RegistrationController extends AbstractController ) ); + if (false === (bool) $this->getParameter('registration_verify_email')) { + $user->setVerified(true); + } else { + $email = $this->emailVerifier->sendEmailConfirmation('app_verify_email', $user, + (new TemplatedEmail()) + ->from(new Address($this->mailerSenderEmail, $this->mailerSenderName)) + ->to($user->getEmail()) + ->locale('en') + ->subject('Please Confirm your Email') + ->htmlTemplate('emails/success/confirmation_email.html.twig') + ); + + $signedUrl = (string) $email->getContext()['signedUrl']; + $this->logger->notice('The validation link for user {username} is {signedUrl}', [ + 'username' => $user->getUserIdentifier(), + 'signedUrl' => $signedUrl, + ]); + } + $this->em->persist($user); $this->em->flush(); @@ -82,21 +101,6 @@ class RegistrationController extends AbstractController 'username' => $user->getUserIdentifier(), ]); - $email = $this->emailVerifier->sendEmailConfirmation('app_verify_email', $user, - (new TemplatedEmail()) - ->from(new Address($this->mailerSenderEmail, $this->mailerSenderName)) - ->to($user->getEmail()) - ->locale('en') - ->subject('Please Confirm your Email') - ->htmlTemplate('emails/success/confirmation_email.html.twig') - ); - - $signedUrl = (string) $email->getContext()['signedUrl']; - $this->logger->notice('The validation link for user {username} is {signedUrl}', [ - 'username' => $user->getUserIdentifier(), - 'signedUrl' => $signedUrl, - ]); - return new Response(null, 201); }