mirror of
https://github.com/plausible/analytics.git
synced 2024-12-23 01:22:15 +03:00
Support for docker based self-hosting (#64)
* first commit with test and compile job Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * adding 'prepare' stage Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * updated ci script to include "test" compile phase Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * adding environment variables for connecting to postgresql Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * updated ci config for postgres Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * using non-alpine version of elixir Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * re-using the 'compile' artifacts and added explict env variables for testing Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * removing redundant deps fetching from common code Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * formatting using mix.format -- beware no-code changes! Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * added release config Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * adding consistent env variable for Database Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * more cleaning up of environment variables Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Adding releases config for enabling releases Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * cleaning up env configs Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Cleaned up config and prepared config for releases Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * updated CI script with new config for test Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Added Dockerfile for creating production docker image Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Adding "docker" build job yay! Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * using non-slim version of debian and installing webpack Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Adding overlays for migrations on releases Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * restricting the docker built to master branch only Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * typo fix Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * adding "Hosting.md" to explain hosting instructions Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * removed the default comments Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Added documentation related to env variables * updated documentation and fixed typo Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * updated documentation * Bumping up elixir version as `overlays` are only supported in latest version read release notes: https://github.com/elixir-lang/elixir/releases/tag/v1.10.0 Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Adding tarball assembly during release Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * updated HOSTING.md Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Added support for db migration Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * minor corrections Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * initializing admin user Admin user has been added in the "migration" phase. A default user is automatically created in the process. One can provide the related env variables, else a new one will be automatically created for you. Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Initial base domain update - phase#1 These changes are only meant for correct operating it under self-hosting. There are many other cosmetic changes, that require updates to email, site and other places where the original website and author is used. Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Using dedicated config variable `base_domain` instead Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * adding base_domain to releases config Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * removing the dedicated config "base_domain", relying on endpoint host Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Removed the usage of "Mix" in code! It is bad practice to use "mix" module inside the code as in actual release this module is unavailable. Replacing this with a config environment variable Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Added support for SMTP via Bamboo Smtp Adapter Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Capturing SMTP errors via Sentry Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Minor updates Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * Adding junit formatter -- useful for generating test reports Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * adding documentation for default user * Resolve "Gitlab Adoption: Add supported services in "Security & Compliance"" * bumping up the debian version to fix issues fixing some vulnerabilities identified by the scanning tools * More updates for self-hosting Changes in most of the places to suit self-hosting. Although, there are some which have been left-off. Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * quick-dirty-fix! * bumping up the db connect timeout Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * bumping up the db connect timeout Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * bumping up the db connect timeout Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * bumping up timeout - skipping MRs :-/ * removing restrictions on watching for changes this stuff isn't working * Update HOSTING.md * renamed the module name * reverting formatting-whitespace changes Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * reverting the name to release Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * adding docker-compose.yml and related instructions Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * using `plausible_url` instead of assuming `https` this is because, it is much to test in local dev machines and in most cases there's already a layer above which is capable for `https` termination and http -> https upgrade Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * WIP: merging changes from upstream Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * wip: more changes * Pushing in changes from upstream Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * changes to ci for testing Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * cleaning up and finishing clickhouse integration Signed-off-by: Chandra Tungathurthi <tckb@tgrthi.me> * updating readme with hosting details
This commit is contained in:
parent
89e807b469
commit
5eb8929929
125
.gitlab-ci.yml
Normal file
125
.gitlab-ci.yml
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
include:
|
||||||
|
- template: Container-Scanning.gitlab-ci.yml
|
||||||
|
- template: License-Scanning.gitlab-ci.yml
|
||||||
|
- template: SAST.gitlab-ci.yml
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- prepare
|
||||||
|
- compile
|
||||||
|
- test
|
||||||
|
- build
|
||||||
|
- postbuild
|
||||||
|
|
||||||
|
.commons: &elixir-commons
|
||||||
|
image: elixir:1.10.3
|
||||||
|
cache:
|
||||||
|
key: ${CI_COMMIT_REF_SLUG}
|
||||||
|
paths:
|
||||||
|
- $CI_PROJECT_DIR/.mix
|
||||||
|
- $CI_PROJECT_DIR/priv/plts
|
||||||
|
- ~/.hex/
|
||||||
|
before_script:
|
||||||
|
- mkdir -p $CI_PROJECT_DIR/priv/plts/
|
||||||
|
- mix local.hex --force && mix local.rebar --force
|
||||||
|
- chmod +x .gitlab/build-scripts/*
|
||||||
|
- source .gitlab/build-scripts/docker.gitlab.sh
|
||||||
|
|
||||||
|
deps:
|
||||||
|
<<: *elixir-commons
|
||||||
|
stage: prepare
|
||||||
|
variables:
|
||||||
|
MIX_HOME: $CI_PROJECT_DIR/.mix
|
||||||
|
script:
|
||||||
|
- mix deps.get
|
||||||
|
dependencies: []
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- mix.lock
|
||||||
|
- deps
|
||||||
|
|
||||||
|
compile:
|
||||||
|
<<: *elixir-commons
|
||||||
|
stage: compile
|
||||||
|
script:
|
||||||
|
- mix compile
|
||||||
|
dependencies:
|
||||||
|
- deps
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- mix.lock
|
||||||
|
- _build
|
||||||
|
- deps
|
||||||
|
|
||||||
|
|
||||||
|
license_scanning:
|
||||||
|
stage: compile
|
||||||
|
dependencies:
|
||||||
|
- deps
|
||||||
|
|
||||||
|
sast:
|
||||||
|
stage: compile
|
||||||
|
|
||||||
|
test:ex_unit:
|
||||||
|
<<: *elixir-commons
|
||||||
|
services:
|
||||||
|
- postgres
|
||||||
|
- name: yandex/clickhouse-server:20.3.9.70
|
||||||
|
alias: clickhouse
|
||||||
|
stage: test
|
||||||
|
variables:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
DATABASE_URL: postgres://postgres:postgres@postgres:5432/plausible_test?currentSchema=default
|
||||||
|
CLICKHOUSE_DATABASE_HOST: clickhouse
|
||||||
|
CLICKHOUSE_DATABASE_NAME: plausible_test
|
||||||
|
MIX_HOME: $CI_PROJECT_DIR/.mix
|
||||||
|
before_script:
|
||||||
|
- apt update && apt install -y clickhouse-client
|
||||||
|
- clickhouse-client --host clickhouse --query "CREATE DATABASE IF NOT EXISTS plausible_test"
|
||||||
|
script:
|
||||||
|
- mix test --cover
|
||||||
|
coverage: '/\[TOTAL\]\s+(\d+\.\d+)%/'
|
||||||
|
dependencies:
|
||||||
|
- compile
|
||||||
|
artifacts:
|
||||||
|
reports:
|
||||||
|
junit: plausible-report.xml
|
||||||
|
|
||||||
|
build:docker:
|
||||||
|
<<: *elixir-commons
|
||||||
|
image:
|
||||||
|
name: gcr.io/kaniko-project/executor:debug
|
||||||
|
entrypoint: [""]
|
||||||
|
stage: build
|
||||||
|
variables:
|
||||||
|
MIX_ENV: prod
|
||||||
|
MIX_HOME: $CI_PROJECT_DIR/.mix/
|
||||||
|
APP_VERSION: $CI_COMMIT_SHORT_SHA
|
||||||
|
before_script:
|
||||||
|
- chmod +x .gitlab/build-scripts/*
|
||||||
|
- source .gitlab/build-scripts/docker.gitlab.sh
|
||||||
|
- docker_create_config
|
||||||
|
script:
|
||||||
|
- docker_build_image
|
||||||
|
dependencies:
|
||||||
|
- compile
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
|
||||||
|
deploy:plausible:
|
||||||
|
stage: postbuild
|
||||||
|
script:
|
||||||
|
- "curl -X POST -F token=$PLAUSIBLE_DEPLOY_TOKEN -F ref=master -F variables[IMAGE_TAG]=${CI_COMMIT_REF_SLUG}-${CI_COMMIT_SHORT_SHA} $PLAUSIBLE_DEPLOY_PROJECT"
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
|
||||||
|
container_scanning:
|
||||||
|
stage: postbuild
|
||||||
|
image: registry.gitlab.com/gitlab-org/security-products/analyzers/klar:$CS_MAJOR_VERSION
|
||||||
|
variables:
|
||||||
|
CS_MAJOR_VERSION: 2
|
||||||
|
KLAR_TRACE: "true"
|
||||||
|
CLAIR_TRACE: "true"
|
||||||
|
CLAIR_OUTPUT: "medium"
|
||||||
|
CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE
|
||||||
|
CI_APPLICATION_TAG: ${CI_COMMIT_REF_SLUG}-$CI_COMMIT_SHORT_SHA
|
17
.gitlab/build-scripts/docker-entrypoint.sh
Executable file
17
.gitlab/build-scripts/docker-entrypoint.sh
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
chmod a+x /app/*.sh
|
||||||
|
|
||||||
|
if [[ "$1" = 'run' ]]; then
|
||||||
|
exec gosu plausibleuser /app/bin/plausible start
|
||||||
|
|
||||||
|
elif [[ "$1" = 'db' ]]; then
|
||||||
|
exec gosu plausibleuser /app/"$2".sh
|
||||||
|
else
|
||||||
|
exec "$@"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
|
|
37
.gitlab/build-scripts/docker.gitlab.sh
Normal file
37
.gitlab/build-scripts/docker.gitlab.sh
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
############################
|
||||||
|
function docker_create_config() {
|
||||||
|
############################
|
||||||
|
mkdir -p /kaniko/.docker/
|
||||||
|
echo "###############"
|
||||||
|
echo "Logging into GitLab Container Registry with CI credentials for kaniko..."
|
||||||
|
echo "###############"
|
||||||
|
echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
############################
|
||||||
|
function docker_build_image() {
|
||||||
|
############################
|
||||||
|
if [[ -f Dockerfile ]]; then
|
||||||
|
echo "###############"
|
||||||
|
echo "Building Dockerfile-based application..."
|
||||||
|
echo "###############"
|
||||||
|
|
||||||
|
/kaniko/executor \
|
||||||
|
--cache=true \
|
||||||
|
--context ${CI_PROJECT_DIR} \
|
||||||
|
--dockerfile ${CI_PROJECT_DIR}/Dockerfile \
|
||||||
|
--destination ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}-${CI_COMMIT_SHORT_SHA} \
|
||||||
|
--destination ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}-latest \
|
||||||
|
\
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "No Dockerfile found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
82
Dockerfile
Normal file
82
Dockerfile
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# we can not use the pre-built tar because the distribution is
|
||||||
|
# platform specific, it makes sense to build it in the docker
|
||||||
|
|
||||||
|
#### Builder
|
||||||
|
FROM elixir:1.10.3 as buildcontainer
|
||||||
|
|
||||||
|
# preparation
|
||||||
|
ARG APP_VER=0.0.1
|
||||||
|
ENV GOSU_VERSION 1.11
|
||||||
|
ENV MIX_ENV=prod
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV APP_VERSION=$APP_VER
|
||||||
|
|
||||||
|
RUN mkdir /app
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# install build dependencies
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y git build-essential nodejs yarn python npm --no-install-recommends && \
|
||||||
|
npm install npm@latest -g && \
|
||||||
|
npm install -g webpack
|
||||||
|
|
||||||
|
RUN apt-get install -y --no-install-recommends ca-certificates wget \
|
||||||
|
&& apt-get install -y --install-recommends gnupg2 dirmngr
|
||||||
|
|
||||||
|
# grab gosu for easy step-down from root
|
||||||
|
RUN set -x \
|
||||||
|
&& dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
|
||||||
|
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
|
||||||
|
&& wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc" \
|
||||||
|
&& export GNUPGHOME="$(mktemp -d)" \
|
||||||
|
&& gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
|
||||||
|
&& gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
|
||||||
|
&& command -v gpgconf && gpgconf --kill all || : \
|
||||||
|
&& rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
|
||||||
|
&& chmod +x /usr/local/bin/gosu \
|
||||||
|
&& gosu --version \
|
||||||
|
&& gosu nobody true
|
||||||
|
|
||||||
|
COPY config ./config
|
||||||
|
COPY assets ./assets
|
||||||
|
COPY priv ./priv
|
||||||
|
COPY lib ./lib
|
||||||
|
COPY mix.exs ./
|
||||||
|
COPY mix.lock ./
|
||||||
|
RUN mix local.hex --force && \
|
||||||
|
mix local.rebar --force && \
|
||||||
|
mix deps.get --only prod && \
|
||||||
|
mix deps.compile
|
||||||
|
|
||||||
|
RUN npm audit fix --prefix ./assets && \
|
||||||
|
npm install --prefix ./assets && \
|
||||||
|
npm run deploy --prefix ./assets && \
|
||||||
|
mix phx.digest priv/static
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY rel rel
|
||||||
|
RUN mix release plausible
|
||||||
|
|
||||||
|
|
||||||
|
# Main Docker Image
|
||||||
|
FROM debian:bullseye
|
||||||
|
LABEL maintainer="tckb <tckb@tgrthi.me>"
|
||||||
|
ENV LANG=C.UTF-8
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y bash openssl --no-install-recommends&& \
|
||||||
|
apt-get clean autoclean && \
|
||||||
|
apt-get autoremove --yes && \
|
||||||
|
rm -rf /var/lib/{apt,dpkg,cache,log}/
|
||||||
|
|
||||||
|
COPY .gitlab/build-scripts/docker-entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
|
RUN chmod a+x /entrypoint.sh && \
|
||||||
|
useradd -d /app -u 1000 -s /bin/bash -m plausibleuser
|
||||||
|
|
||||||
|
COPY --from=buildcontainer /usr/local/bin/gosu /usr/local/bin/gosu
|
||||||
|
COPY --from=buildcontainer /app/_build/prod/rel/plausible /app
|
||||||
|
RUN chown -R plausibleuser:plausibleuser /app
|
||||||
|
WORKDIR /app
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
CMD ["run"]
|
152
HOSTING.md
Normal file
152
HOSTING.md
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
# Plausible Analytics
|
||||||
|
Self-hosting is possible based on the docker images and are automatically pushed into [Gitlab hosted docker](registry.gitlab.com/tckb-public/plausible) registry for all commits on `master` branch.
|
||||||
|
All `master-*` tags are considered to be stable and are persisted. Any other tag in the registry is considered to be for development purposes and/or unstable and are auto-deleted after a week.
|
||||||
|
|
||||||
|
|
||||||
|
### Building Docker image
|
||||||
|
Besides the GitlabCI, one can build docker image from [Dockerfile](./Dockerfile).
|
||||||
|
|
||||||
|
#### Up and Running
|
||||||
|
The repo supplies with a [Docker Compose](./docker-compose.yml) file, this serves as a sample for running Plausible with Docker.
|
||||||
|
In this sample, the db migration is done by default on startup, so you need to clean the data up every time you run:
|
||||||
|
|
||||||
|
First run
|
||||||
|
```bash
|
||||||
|
$ docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
subsequent runs--
|
||||||
|
```bash
|
||||||
|
$ docker-compose down
|
||||||
|
$ docker volume rm plausible_db-data -f
|
||||||
|
$ docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
### Non-docker building
|
||||||
|
It is possible to create a release artifact by running a release.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
MIX_ENV=prod mix release plausible
|
||||||
|
```
|
||||||
|
the release will create the pre-packed artifact at `_build/prod/rel/plausible/bin/plausible`, the release will also create a tarball at `_build/prod/` for convenience.
|
||||||
|
|
||||||
|
Note, that you have to feed in the related environment variables (see below `Environment Variables`)
|
||||||
|
|
||||||
|
## Database Migration
|
||||||
|
On the initial setup, a migration step is necessary to create database and table schemas needed for initial bootup.
|
||||||
|
Normally, this done by mix aliases like `ecto.setup` defined in the `mix.exs`. As this not available in "released" artifact, [`plausible_migration.ex`](./lib/plausible_migration.ex) facilitates this process.
|
||||||
|
The overlay [scripts](./rel/overlays) take care of these.
|
||||||
|
|
||||||
|
After the release, these are available under `_build/prod/rel/plausible` --
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
_build/prod/rel/plausible/createdb.sh
|
||||||
|
_build/prod/rel/plausible/migrate.sh
|
||||||
|
_build/prod/rel/plausible/rollback.sh
|
||||||
|
_build/prod/rel/plausible/seed.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
the same is available in the docker images as follows --
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run plausible:master-12add db createdb
|
||||||
|
docker run plausible:master-12add db migrate
|
||||||
|
docker run plausible:master-12add db rollback
|
||||||
|
docker run plausible:master-12add db seed
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
Plausible relies on the several services for operating, the expected environment variables are explaiend below.
|
||||||
|
|
||||||
|
### Server
|
||||||
|
Following are the variables that can be used to configure the availability of the server.
|
||||||
|
|
||||||
|
- HOST (*String*)
|
||||||
|
- The hosting address of the server. For running on local system, this can be set to **localhost**. In production systems, this can be your ingress host.
|
||||||
|
- PORT (*Number*)
|
||||||
|
- The port on which the server is available.
|
||||||
|
- SECRET_KEY_BASE (*String*)
|
||||||
|
- An internal secret key used by [Phoenix Framework](https://www.phoenixframework.org/). Follow the [instructions](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Secret.html#content) to generate one.
|
||||||
|
- ENVIRONMENT (*String*)
|
||||||
|
- The current running environment. _defaults to **prod**_
|
||||||
|
- APP_VERSION (*String*)
|
||||||
|
- The version of the app running. _defaults to current docker tag_
|
||||||
|
|
||||||
|
### Default User Generation
|
||||||
|
For self-hosting, a default user is generated during the [Database Migration](#Database Migration) to access Plausible. To be noted that, a default user is a user whose trial period expires in 100 Years ;).
|
||||||
|
It is *highly* recommended that you configure these parameters.
|
||||||
|
|
||||||
|
- ADMIN_USER_NAME
|
||||||
|
- The default ("admin") username. _if not provided, one will be generated for you_
|
||||||
|
- ADMIN_USER_EMAIL
|
||||||
|
- The default ("admin") user email. _if not provided, one will be generated for you_
|
||||||
|
- ADMIN_USER_PWD
|
||||||
|
- The default ("admin") user password. _if not provided, one will be generated for you_
|
||||||
|
|
||||||
|
### Mailer/SMTP Setup
|
||||||
|
|
||||||
|
- MAILER_ADAPTER (*String*)
|
||||||
|
- The adapter used for sending out e-mails. Available: `Bamboo.PostmarkAdapter` / `Bamboo.SMTPAdapter`
|
||||||
|
- MAILER_EMAIL (*String*)
|
||||||
|
- The email id to use for as _from_ address of all communications from Plausible.
|
||||||
|
|
||||||
|
In case of `Bamboo.SMTPAdapter` you need to supply the following variables:
|
||||||
|
|
||||||
|
- SMTP_HOST_ADDR (*String*)
|
||||||
|
- The host address of your smtp server.
|
||||||
|
- SMTP_HOST_PORT (*Number*)
|
||||||
|
- The port of your smtp server.
|
||||||
|
- SMTP_USER_NAME (*String*)
|
||||||
|
- The username/email for smtp auth.
|
||||||
|
- SMTP_USER_PWD (*String*)
|
||||||
|
- The password for smtp auth.
|
||||||
|
- SMTP_HOST_SSL_ENABLED (*Boolean String*)
|
||||||
|
- If ssl is enabled for connecting to Smtp, _defaults to `false`_
|
||||||
|
- SMTP_RETRIES (*Number*)
|
||||||
|
- Number of retries to make until mailer gives up. _defaults to `2`_
|
||||||
|
- SMTP_MX_LOOKUPS_ENABLED (*Boolean String*)
|
||||||
|
- If MX lookups should be done before sending out emails. _defaults to `false`_
|
||||||
|
|
||||||
|
### Database
|
||||||
|
|
||||||
|
Plausible uses postgresql as database for storing all the user-data. Use the following the variables to configure it.
|
||||||
|
|
||||||
|
- DATABASE_URL (*String*)
|
||||||
|
- The repo Url as dictated [here](https://hexdocs.pm/ecto/Ecto.Repo.html#module-urls)
|
||||||
|
- DATABASE_POOL_SIZE (*Number*)
|
||||||
|
- A default pool size for connecting to the database, defaults to *10*, a higher number is recommended for a production system.
|
||||||
|
- DATABASE_TLS_ENABLED (*Boolean String*)
|
||||||
|
- A flag that says whether to connect to the database via TLS, read [here](https://www.postgresql.org/docs/10/ssl-tcp.html)
|
||||||
|
|
||||||
|
For performance reasons, all the analytics events are stored in clickhouse:
|
||||||
|
|
||||||
|
- CLICKHOUSE_DATABASE_HOST (*String*)
|
||||||
|
- CLICKHOUSE_DATABASE_NAME (*String*)
|
||||||
|
- CLICKHOUSE_DATABASE_USER (*String*)
|
||||||
|
- CLICKHOUSE_DATABASE_PASSWORD (*String*)
|
||||||
|
- CLICKHOUSE_DATABASE_POOLSIZE (*Number*)
|
||||||
|
- A default pool size for connecting to the database, defaults to *10*, a higher number is recommended for a production system.
|
||||||
|
|
||||||
|
### External Services
|
||||||
|
|
||||||
|
- [Google Client](https://developers.google.com/api-client-library)
|
||||||
|
- GOOGLE_CLIENT_ID
|
||||||
|
- GOOGLE_CLIENT_SECRET
|
||||||
|
- [Sentry](https://sentry.io/)
|
||||||
|
- SENTRY_DSN
|
||||||
|
- [Paddle](https://paddle.com/)
|
||||||
|
- PADDLE_VENDOR_AUTH_CODE
|
||||||
|
- [PostMark](https://postmarkapp.com/), only in case of `Bamboo.PostmarkAdapter` mail adapter.
|
||||||
|
- POSTMARK_API_KEY
|
||||||
|
|
||||||
|
Apart from these, there are also the following integrations
|
||||||
|
|
||||||
|
- [Twitter](https://developer.twitter.com/en/docs)
|
||||||
|
- TWITTER_CONSUMER_KEY
|
||||||
|
- TWITTER_CONSUMER_SECRET
|
||||||
|
- TWITTER_ACCESS_TOKEN
|
||||||
|
- TWITTER_ACCESS_TOKEN_SECRET
|
||||||
|
- [Slack](https://api.slack.com/messaging/webhooks)
|
||||||
|
- SLACK_WEBHOOK
|
@ -21,9 +21,7 @@ Interested? [Read more on our website](https://plausible.io)
|
|||||||
|
|
||||||
### Can Plausible Analytics be self-hosted?
|
### Can Plausible Analytics be self-hosted?
|
||||||
|
|
||||||
At the moment we don't provide support for easily self-hosting the code. Currently, the purpose of keeping the code open-source is to be transparent with the community about how we collect and process data.
|
The purpose of keeping the code open-source is to be transparent with the community about how we collect and process however, we do provide an experimental [docker-based self hosting](./HOSTING.md) setup. Please note that this is still in *alpha* stage and care should be taken while using it for production system.
|
||||||
|
|
||||||
Making Plausible Analytics easy to self-host, providing full documentation and support for the process is something we want to see happening in the future. There is [a GitHub thread](https://github.com/plausible-insights/plausible/issues/26) you can join and engage with to follow our progress in making Plausible Analytics easy to self-host.
|
|
||||||
|
|
||||||
### Why is Plausible Analytics not free like Google Analytics?
|
### Why is Plausible Analytics not free like Google Analytics?
|
||||||
|
|
||||||
|
@ -1,19 +1,34 @@
|
|||||||
# This file is responsible for configuring your application
|
|
||||||
# and its dependencies with the aid of the Mix.Config module.
|
|
||||||
#
|
|
||||||
# This configuration file is loaded before any dependency and
|
|
||||||
# is restricted to this project.
|
|
||||||
|
|
||||||
# General application configuration
|
|
||||||
use Mix.Config
|
use Mix.Config
|
||||||
|
|
||||||
config :plausible,
|
config :plausible,
|
||||||
ecto_repos: [Plausible.Repo]
|
admin_user: System.get_env("ADMIN_USER_NAME", "admin"),
|
||||||
|
admin_email: System.get_env("ADMIN_USER_EMAIL", "admin@plausible.local"),
|
||||||
|
mailer_email: System.get_env("MAILER_EMAIL", "hello@plausible.local"),
|
||||||
|
admin_pwd: System.get_env("ADMIN_USER_PWD", "!@d3in"),
|
||||||
|
ecto_repos: [Plausible.Repo],
|
||||||
|
environment: System.get_env(Atom.to_string(Mix.env()), "dev")
|
||||||
|
|
||||||
|
config :plausible, :clickhouse,
|
||||||
|
hostname: System.get_env("CLICKHOUSE_DATABASE_HOST", "localhost"),
|
||||||
|
database: System.get_env("CLICKHOUSE_DATABASE_NAME", "plausible_test"),
|
||||||
|
username: System.get_env("CLICKHOUSE_DATABASE_USER"),
|
||||||
|
password: System.get_env("CLICKHOUSE_DATABASE_PASSWORD"),
|
||||||
|
pool_size: 10
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :plausible, PlausibleWeb.Endpoint,
|
config :plausible, PlausibleWeb.Endpoint,
|
||||||
url: [host: "localhost"],
|
url: [
|
||||||
secret_key_base: "/NJrhNtbyCVAsTyvtk1ZYCwfm981Vpo/0XrVwjJvemDaKC/vsvBRevLwsc6u8RCg",
|
host: System.get_env("HOST", "localhost"),
|
||||||
|
port: String.to_integer(System.get_env("PORT", "8000"))
|
||||||
|
],
|
||||||
|
http: [
|
||||||
|
port: String.to_integer(System.get_env("PORT", "8000"))
|
||||||
|
],
|
||||||
|
secret_key_base:
|
||||||
|
System.get_env(
|
||||||
|
"SECRET_KEY_BASE",
|
||||||
|
"/NJrhNtbyCVAsTyvtk1ZYCwfm981Vpo/0XrVwjJvemDaKC/vsvBRevLwsc6u8RCg"
|
||||||
|
),
|
||||||
render_errors: [
|
render_errors: [
|
||||||
view: PlausibleWeb.ErrorView,
|
view: PlausibleWeb.ErrorView,
|
||||||
accepts: ~w(html json)
|
accepts: ~w(html json)
|
||||||
@ -21,11 +36,13 @@ config :plausible, PlausibleWeb.Endpoint,
|
|||||||
pubsub: [name: Plausible.PubSub, adapter: Phoenix.PubSub.PG2]
|
pubsub: [name: Plausible.PubSub, adapter: Phoenix.PubSub.PG2]
|
||||||
|
|
||||||
config :sentry,
|
config :sentry,
|
||||||
dsn: "https://0350a42aa6234a2eaf1230866788598e@sentry.io/1382353",
|
dsn: System.get_env("SENTRY_DSN"),
|
||||||
included_environments: [:prod, :staging],
|
included_environments: [:prod, :staging],
|
||||||
environment_name: String.to_atom(Map.get(System.get_env(), "APP_ENV", "dev")),
|
environment_name: String.to_atom(Map.get(System.get_env(), "MIX_ENV", "dev")),
|
||||||
enable_source_code_context: true,
|
enable_source_code_context: true,
|
||||||
root_source_code_path: File.cwd!
|
root_source_code_path: File.cwd!(),
|
||||||
|
tags: %{app_version: System.get_env("APP_VERSION", "0.0.1")},
|
||||||
|
context_lines: 5
|
||||||
|
|
||||||
# Configures Elixir's Logger
|
# Configures Elixir's Logger
|
||||||
config :logger, :console,
|
config :logger, :console,
|
||||||
@ -46,6 +63,7 @@ config :plausible,
|
|||||||
google_api: Plausible.Google.Api
|
google_api: Plausible.Google.Api
|
||||||
|
|
||||||
config :plausible,
|
config :plausible,
|
||||||
|
# 30 minutes
|
||||||
session_timeout: 1000 * 60 * 30, # 30 minutes
|
session_timeout: 1000 * 60 * 30, # 30 minutes
|
||||||
session_length_minutes: 30
|
session_length_minutes: 30
|
||||||
|
|
||||||
@ -53,6 +71,58 @@ config :plausible, :paddle,
|
|||||||
vendor_id: "49430",
|
vendor_id: "49430",
|
||||||
vendor_auth_code: System.get_env("PADDLE_VENDOR_AUTH_CODE")
|
vendor_auth_code: System.get_env("PADDLE_VENDOR_AUTH_CODE")
|
||||||
|
|
||||||
|
config :plausible,
|
||||||
|
Plausible.Repo,
|
||||||
|
pool_size: String.to_integer(System.get_env("DATABASE_POOL_SIZE", "10")),
|
||||||
|
timeout: 300_000,
|
||||||
|
connect_timeout: 300_000,
|
||||||
|
handshake_timeout: 300_000,
|
||||||
|
url:
|
||||||
|
System.get_env(
|
||||||
|
"DATABASE_URL",
|
||||||
|
"postgres://postgres:postgres@127.0.0.1:5432/plausible_test?currentSchema=default"
|
||||||
|
),
|
||||||
|
ssl: false
|
||||||
|
|
||||||
|
config :plausible, :google,
|
||||||
|
client_id: System.get_env("GOOGLE_CLIENT_ID"),
|
||||||
|
client_secret: System.get_env("GOOGLE_CLIENT_SECRET")
|
||||||
|
|
||||||
|
config :plausible, :slack, webhook: System.get_env("SLACK_WEBHOOK")
|
||||||
|
|
||||||
|
mailer_adapter = System.get_env("MAILER_ADAPTER", "Bamboo.PostmarkAdapter")
|
||||||
|
|
||||||
|
case mailer_adapter do
|
||||||
|
"Bamboo.PostmarkAdapter" ->
|
||||||
|
config :plausible, Plausible.Mailer,
|
||||||
|
adapter: :"Elixir.#{mailer_adapter}",
|
||||||
|
api_key: System.get_env("POSTMARK_API_KEY")
|
||||||
|
|
||||||
|
"Bamboo.SMTPAdapter" ->
|
||||||
|
config :plausible, Plausible.Mailer,
|
||||||
|
adapter: :"Elixir.#{mailer_adapter}",
|
||||||
|
server: System.fetch_env!("SMTP_HOST_ADDR"),
|
||||||
|
hostname: System.get_env("HOST", "localhost"),
|
||||||
|
port: System.fetch_env!("SMTP_HOST_PORT"),
|
||||||
|
username: System.fetch_env!("SMTP_USER_NAME"),
|
||||||
|
password: System.fetch_env!("SMTP_USER_PWD"),
|
||||||
|
tls: :if_available,
|
||||||
|
allowed_tls_versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"],
|
||||||
|
ssl: System.get_env("SMTP_HOST_SSL_ENABLED") || true,
|
||||||
|
retries: System.get_env("SMTP_RETRIES") || 2,
|
||||||
|
no_mx_lookups: System.get_env("SMTP_MX_LOOKUPS_ENABLED") || true,
|
||||||
|
auth: :always
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
raise "Unknown mailer_adapter; expected SMTPAdapter or PostmarkAdapter"
|
||||||
|
end
|
||||||
|
|
||||||
|
config :plausible, :twitter,
|
||||||
|
consumer_key: System.get_env("TWITTER_CONSUMER_KEY"),
|
||||||
|
consumer_secret: System.get_env("TWITTER_CONSUMER_SECRET"),
|
||||||
|
token: System.get_env("TWITTER_ACCESS_TOKEN"),
|
||||||
|
token_secret: System.get_env("TWITTER_ACCESS_TOKEN_SECRET")
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
import_config "#{Mix.env()}.exs"
|
import_config "#{Mix.env()}.exs"
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
use Mix.Config
|
use Mix.Config
|
||||||
|
|
||||||
# For development, we disable any cache and enable
|
|
||||||
# debugging and code reloading.
|
|
||||||
#
|
|
||||||
# The watchers configuration can be used to run external
|
|
||||||
# watchers to your application. For example, we use it
|
|
||||||
# with webpack to recompile .js and .css sources.
|
|
||||||
config :plausible, PlausibleWeb.Endpoint,
|
config :plausible, PlausibleWeb.Endpoint,
|
||||||
http: [port: 8000],
|
server: true,
|
||||||
debug_errors: true,
|
debug_errors: true,
|
||||||
code_reloader: true,
|
code_reloader: true,
|
||||||
check_origin: false,
|
check_origin: false,
|
||||||
@ -35,21 +29,8 @@ config :logger, :console, format: "[$level] $message\n"
|
|||||||
config :phoenix, :stacktrace_depth, 20
|
config :phoenix, :stacktrace_depth, 20
|
||||||
config :phoenix, :plug_init_mode, :runtime
|
config :phoenix, :plug_init_mode, :runtime
|
||||||
|
|
||||||
config :plausible, :clickhouse,
|
|
||||||
hostname: "localhost",
|
|
||||||
database: "plausible_dev",
|
|
||||||
pool_size: 10
|
|
||||||
|
|
||||||
config :plausible, Plausible.Repo,
|
|
||||||
username: "postgres",
|
|
||||||
password: "postgres",
|
|
||||||
database: "plausible_dev",
|
|
||||||
hostname: "localhost",
|
|
||||||
pool_size: 10
|
|
||||||
|
|
||||||
config :plausible, Plausible.Mailer,
|
|
||||||
adapter: Bamboo.LocalAdapter
|
|
||||||
|
|
||||||
if File.exists?("config/dev.secret.exs") do
|
if File.exists?("config/dev.secret.exs") do
|
||||||
import_config "dev.secret.exs"
|
import_config "dev.secret.exs"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config :logger, level: :debug
|
||||||
|
106
config/prod.exs
106
config/prod.exs
@ -1,105 +1,7 @@
|
|||||||
use Mix.Config
|
use Mix.Config
|
||||||
|
|
||||||
# For production, don't forget to configure the url host
|
# For the actual-production deployments we will use releases,
|
||||||
# to something meaningful, Phoenix uses this information
|
# i.e., "releases.exs" is the _actual_ production config
|
||||||
# when generating URLs.
|
# see "releases.exs"
|
||||||
#
|
|
||||||
# Note we also include the path to a cache manifest
|
|
||||||
# containing the digested version of static files. This
|
|
||||||
# manifest is generated by the `mix phx.digest` task,
|
|
||||||
# which you should run after static files are built and
|
|
||||||
# before starting your production server.
|
|
||||||
config :plausible, PlausibleWeb.Endpoint,
|
|
||||||
http: [:inet6, port: System.get_env("PORT") || 4000],
|
|
||||||
url: [host: System.get_env("HOST"), scheme: "https", port: 443],
|
|
||||||
cache_static_manifest: "priv/static/cache_manifest.json"
|
|
||||||
|
|
||||||
# Do not print debug messages in production
|
import_config "releases.exs"
|
||||||
config :logger, level: :info
|
|
||||||
|
|
||||||
# ## SSL Support
|
|
||||||
#
|
|
||||||
# To get SSL working, you will need to add the `https` key
|
|
||||||
# to the previous section and set your `:url` port to 443:
|
|
||||||
#
|
|
||||||
# config :plausible, PlausibleWeb.Endpoint,
|
|
||||||
# ...
|
|
||||||
# url: [host: "example.com", port: 443],
|
|
||||||
# https: [
|
|
||||||
# :inet6,
|
|
||||||
# port: 443,
|
|
||||||
# cipher_suite: :strong,
|
|
||||||
# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
|
|
||||||
# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")
|
|
||||||
# ]
|
|
||||||
#
|
|
||||||
# The `cipher_suite` is set to `:strong` to support only the
|
|
||||||
# latest and more secure SSL ciphers. This means old browsers
|
|
||||||
# and clients may not be supported. You can set it to
|
|
||||||
# `:compatible` for wider support.
|
|
||||||
#
|
|
||||||
# `:keyfile` and `:certfile` expect an absolute path to the key
|
|
||||||
# and cert in disk or a relative path inside priv, for example
|
|
||||||
# "priv/ssl/server.key". For all supported SSL configuration
|
|
||||||
# options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1
|
|
||||||
#
|
|
||||||
# We also recommend setting `force_ssl` in your endpoint, ensuring
|
|
||||||
# no data is ever sent via http, always redirecting to https:
|
|
||||||
#
|
|
||||||
# config :plausible, PlausibleWeb.Endpoint,
|
|
||||||
# force_ssl: [hsts: true]
|
|
||||||
#
|
|
||||||
# Check `Plug.SSL` for all available options in `force_ssl`.
|
|
||||||
|
|
||||||
# ## Using releases (distillery)
|
|
||||||
#
|
|
||||||
# If you are doing OTP releases, you need to instruct Phoenix
|
|
||||||
# to start the server for all endpoints:
|
|
||||||
#
|
|
||||||
# config :phoenix, :serve_endpoints, true
|
|
||||||
#
|
|
||||||
# Alternatively, you can configure exactly which server to
|
|
||||||
# start per endpoint:
|
|
||||||
#
|
|
||||||
# config :plausible, PlausibleWeb.Endpoint, server: true
|
|
||||||
#
|
|
||||||
# Note you can't rely on `System.get_env/1` when using releases.
|
|
||||||
# See the releases documentation accordingly.
|
|
||||||
|
|
||||||
# Finally import the config/prod.secret.exs which should be versioned
|
|
||||||
# separately.
|
|
||||||
config :plausible, PlausibleWeb.Endpoint,
|
|
||||||
secret_key_base: System.get_env("SECRET_KEY_BASE")
|
|
||||||
|
|
||||||
config :plausible, :clickhouse,
|
|
||||||
hostname: System.get_env("CLICKHOUSE_DATABASE_HOST"),
|
|
||||||
database: System.get_env("CLICKHOUSE_DATABASE_NAME"),
|
|
||||||
username: System.get_env("CLICKHOUSE_DATABASE_USER"),
|
|
||||||
password: System.get_env("CLICKHOUSE_DATABASE_PASSWORD"),
|
|
||||||
pool_size: 30
|
|
||||||
|
|
||||||
# Configure your database
|
|
||||||
config :plausible, Plausible.Repo,
|
|
||||||
adapter: Ecto.Adapters.Postgres,
|
|
||||||
url: System.get_env("AVIEN_DATABASE_URL"),
|
|
||||||
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
|
|
||||||
timeout: 10_000,
|
|
||||||
ssl: true
|
|
||||||
|
|
||||||
config :plausible, :google,
|
|
||||||
client_id: System.get_env("GOOGLE_CLIENT_ID"),
|
|
||||||
client_secret: System.get_env("GOOGLE_CLIENT_SECRET")
|
|
||||||
|
|
||||||
config :plausible, :slack,
|
|
||||||
webhook: System.get_env("SLACK_WEBHOOK")
|
|
||||||
|
|
||||||
config :plausible, Plausible.Mailer,
|
|
||||||
adapter: Bamboo.PostmarkAdapter,
|
|
||||||
api_key: System.get_env("POSTMARK_API_KEY")
|
|
||||||
|
|
||||||
config :plausible, :twitter, [
|
|
||||||
consumer_key: System.get_env("TWITTER_CONSUMER_KEY"),
|
|
||||||
consumer_secret: System.get_env("TWITTER_CONSUMER_SECRET"),
|
|
||||||
token: System.get_env("TWITTER_ACCESS_TOKEN"),
|
|
||||||
token_secret: System.get_env("TWITTER_ACCESS_TOKEN_SECRET")
|
|
||||||
]
|
|
||||||
|
128
config/releases.exs
Normal file
128
config/releases.exs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import Config
|
||||||
|
|
||||||
|
### Mandatory params Start
|
||||||
|
# it is highly recommended to change this parameters in production systems
|
||||||
|
# params are made optional to facilitate smooth release
|
||||||
|
|
||||||
|
port = System.get_env("PORT") || 8000
|
||||||
|
host = System.get_env("HOST", "localhost")
|
||||||
|
|
||||||
|
secret_key_base =
|
||||||
|
System.get_env(
|
||||||
|
"SECRET_KEY_BASE",
|
||||||
|
"/NJrhNtbyCVAsTyvtk1ZYCwfm981Vpo/0XrVwjJvemDaKC/vsvBRevLwsc6u8RCg"
|
||||||
|
)
|
||||||
|
|
||||||
|
db_pool_size = String.to_integer(System.get_env("DATABASE_POOL_SIZE", "10"))
|
||||||
|
|
||||||
|
db_url =
|
||||||
|
System.get_env(
|
||||||
|
"DATABASE_URL",
|
||||||
|
"postgres://postgres:postgres@127.0.0.1:5432/plausible_test?currentSchema=default"
|
||||||
|
)
|
||||||
|
|
||||||
|
db_tls_enabled? = String.to_existing_atom(System.get_env("DATABASE_TLS_ENABLED", "false"))
|
||||||
|
admin_user = System.get_env("ADMIN_USER_NAME")
|
||||||
|
admin_email = System.get_env("ADMIN_USER_EMAIL")
|
||||||
|
admin_pwd = System.get_env("ADMIN_USER_PWD")
|
||||||
|
env = System.get_env("ENVIRONMENT", "prod")
|
||||||
|
mailer_adapter = System.get_env("MAILER_ADAPTER", "Bamboo.PostmarkAdapter")
|
||||||
|
mailer_email = System.get_env("MAILER_EMAIL", "hello@plausible.local")
|
||||||
|
app_version = System.get_env("APP_VERSION", "0.0.1")
|
||||||
|
ck_host = System.get_env("CLICKHOUSE_DATABASE_HOST", "localhost")
|
||||||
|
ck_db = System.get_env("CLICKHOUSE_DATABASE_NAME", "plausible_dev")
|
||||||
|
ck_db_user = System.get_env("CLICKHOUSE_DATABASE_USER")
|
||||||
|
ck_db_pwd = System.get_env("CLICKHOUSE_DATABASE_PASSWORD")
|
||||||
|
ck_db_pool = System.get_env("CLICKHOUSE_DATABASE_POOLSIZE") || 10
|
||||||
|
### Mandatory params End
|
||||||
|
|
||||||
|
sentry_dsn = System.get_env("SENTRY_DSN")
|
||||||
|
paddle_auth_code = System.get_env("PADDLE_VENDOR_AUTH_CODE")
|
||||||
|
google_cid = System.get_env("GOOGLE_CLIENT_ID")
|
||||||
|
google_secret = System.get_env("GOOGLE_CLIENT_SECRET")
|
||||||
|
slack_hook_url = System.get_env("SLACK_WEBHOOK")
|
||||||
|
twitter_consumer_key = System.get_env("TWITTER_CONSUMER_KEY")
|
||||||
|
twitter_consumer_secret = System.get_env("TWITTER_CONSUMER_SECRET")
|
||||||
|
twitter_token = System.get_env("TWITTER_ACCESS_TOKEN")
|
||||||
|
twitter_token_secret = System.get_env("TWITTER_ACCESS_TOKEN_SECRET")
|
||||||
|
postmark_api_key = System.get_env("POSTMARK_API_KEY")
|
||||||
|
|
||||||
|
config :plausible,
|
||||||
|
admin_user: admin_user,
|
||||||
|
admin_email: admin_email,
|
||||||
|
admin_pwd: admin_pwd,
|
||||||
|
environment: env,
|
||||||
|
mailer_email: mailer_email
|
||||||
|
|
||||||
|
config :plausible, PlausibleWeb.Endpoint,
|
||||||
|
url: [host: host, port: port],
|
||||||
|
http: [
|
||||||
|
port: port
|
||||||
|
],
|
||||||
|
secret_key_base: secret_key_base,
|
||||||
|
cache_static_manifest: "priv/static/cache_manifest.json",
|
||||||
|
check_origin: false,
|
||||||
|
load_from_system_env: true,
|
||||||
|
server: true,
|
||||||
|
code_reloader: false
|
||||||
|
|
||||||
|
config :plausible,
|
||||||
|
Plausible.Repo,
|
||||||
|
pool_size: db_pool_size,
|
||||||
|
url: db_url,
|
||||||
|
adapter: Ecto.Adapters.Postgres,
|
||||||
|
ssl: db_tls_enabled?
|
||||||
|
|
||||||
|
config :sentry,
|
||||||
|
dsn: sentry_dsn,
|
||||||
|
environment_name: env,
|
||||||
|
release: app_version,
|
||||||
|
tags: %{app_version: app_version}
|
||||||
|
|
||||||
|
config :plausible, :paddle, vendor_auth_code: paddle_auth_code
|
||||||
|
|
||||||
|
config :plausible, :google,
|
||||||
|
client_id: google_cid,
|
||||||
|
client_secret: google_secret
|
||||||
|
|
||||||
|
config :plausible, :slack, webhook: slack_hook_url
|
||||||
|
|
||||||
|
config :plausible, :clickhouse,
|
||||||
|
hostname: ck_host,
|
||||||
|
database: ck_db,
|
||||||
|
username: ck_db_user,
|
||||||
|
password: ck_db_pwd,
|
||||||
|
pool_size: ck_db_pool
|
||||||
|
|
||||||
|
case mailer_adapter do
|
||||||
|
"Bamboo.PostmarkAdapter" ->
|
||||||
|
config :plausible, Plausible.Mailer,
|
||||||
|
adapter: :"Elixir.#{mailer_adapter}",
|
||||||
|
api_key: System.get_env("POSTMARK_API_KEY")
|
||||||
|
|
||||||
|
"Bamboo.SMTPAdapter" ->
|
||||||
|
config :plausible, Plausible.Mailer,
|
||||||
|
adapter: :"Elixir.#{mailer_adapter}",
|
||||||
|
server: System.fetch_env!("SMTP_HOST_ADDR"),
|
||||||
|
hostname: System.get_env("HOST", "localhost"),
|
||||||
|
port: System.fetch_env!("SMTP_HOST_PORT"),
|
||||||
|
username: System.fetch_env!("SMTP_USER_NAME"),
|
||||||
|
password: System.fetch_env!("SMTP_USER_PWD"),
|
||||||
|
tls: :if_available,
|
||||||
|
allowed_tls_versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"],
|
||||||
|
ssl: System.get_env("SMTP_HOST_SSL_ENABLED") || true,
|
||||||
|
retries: System.get_env("SMTP_RETRIES") || 2,
|
||||||
|
no_mx_lookups: System.get_env("SMTP_MX_LOOKUPS_ENABLED") || true,
|
||||||
|
auth: :always
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
raise "Unknown mailer_adapter; expected SMTPAdapter or PostmarkAdapter"
|
||||||
|
end
|
||||||
|
|
||||||
|
config :plausible, :twitter,
|
||||||
|
consumer_key: twitter_consumer_key,
|
||||||
|
consumer_secret: twitter_consumer_secret,
|
||||||
|
token: twitter_token,
|
||||||
|
token_secret: twitter_token_secret
|
||||||
|
|
||||||
|
config :logger, level: :warn
|
@ -13,24 +13,23 @@ config :logger, level: :warn
|
|||||||
config :bcrypt_elixir, :log_rounds, 4
|
config :bcrypt_elixir, :log_rounds, 4
|
||||||
|
|
||||||
# Configure your database
|
# Configure your database
|
||||||
config :plausible, Plausible.Repo,
|
config :plausible,
|
||||||
username: "postgres",
|
Plausible.Repo,
|
||||||
password: "postgres",
|
pool: Ecto.Adapters.SQL.Sandbox
|
||||||
database: "plausible_test",
|
|
||||||
hostname: "localhost",
|
|
||||||
pool: Ecto.Adapters.SQL.Sandbox
|
|
||||||
|
|
||||||
config :plausible, :clickhouse,
|
config :plausible, Plausible.Mailer, adapter: Bamboo.TestAdapter
|
||||||
hostname: "localhost",
|
|
||||||
database: "plausible_test",
|
|
||||||
pool_size: 10
|
|
||||||
|
|
||||||
config :plausible, Plausible.Mailer,
|
|
||||||
adapter: Bamboo.TestAdapter
|
|
||||||
|
|
||||||
config :plausible,
|
config :plausible,
|
||||||
paddle_api: Plausible.PaddleApi.Mock,
|
paddle_api: Plausible.PaddleApi.Mock,
|
||||||
google_api: Plausible.Google.Api.Mock
|
google_api: Plausible.Google.Api.Mock
|
||||||
|
|
||||||
|
|
||||||
|
config :junit_formatter,
|
||||||
|
report_file: "report.xml",
|
||||||
|
report_dir: File.cwd!(),
|
||||||
|
print_report_file: true,
|
||||||
|
prepend_project_name?: true,
|
||||||
|
include_filename?: true
|
||||||
|
|
||||||
config :plausible,
|
config :plausible,
|
||||||
session_timeout: 0
|
session_timeout: 0
|
||||||
|
79
docker-compose.yml
Normal file
79
docker-compose.yml
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# NOTE:
|
||||||
|
# This Docker-compose file is created as a sample and should not be used directly for production
|
||||||
|
# You can adjust the settings as-per your environment
|
||||||
|
version: "3.3"
|
||||||
|
services:
|
||||||
|
|
||||||
|
# As it says, this service is a fake smtp server which accepts SMTP connections
|
||||||
|
# the inbox is available at localhost:8025, in actuality, you need to use a proper smtp server
|
||||||
|
fakesmtp_server:
|
||||||
|
container_name: fakesmtp_server
|
||||||
|
image: mailhog/mailhog:v1.0.0
|
||||||
|
ports:
|
||||||
|
- 1025:1025
|
||||||
|
- 8025:8025
|
||||||
|
healthcheck:
|
||||||
|
test: echo | telnet 127.0.0.1 1025
|
||||||
|
|
||||||
|
|
||||||
|
plausible_db:
|
||||||
|
container_name: plausible_db
|
||||||
|
image: postgres:9.4
|
||||||
|
command: ["postgres", "-c", "log_statement=all", "-c", "log_destination=stderr"]
|
||||||
|
volumes:
|
||||||
|
- db-data:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
- POSTGRES_PASSWORD=postgres
|
||||||
|
- POSTGRES_DB=plausible_db
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
|
||||||
|
plausible_events_db:
|
||||||
|
container_name: plausible_events_db
|
||||||
|
image: yandex/clickhouse-server
|
||||||
|
ports:
|
||||||
|
- 8123:8123
|
||||||
|
|
||||||
|
plausible:
|
||||||
|
container_name: plausible
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./Dockerfile
|
||||||
|
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate &&/entrypoint.sh run"
|
||||||
|
environment:
|
||||||
|
- ENVIRONMENT=production
|
||||||
|
- PORT=8080
|
||||||
|
- SECRET_KEY_BASE=iYb1mP5cnmY+gUxo7C/h6XMigossPhzwd8/ic6LFnQ9Y58Fl1xduSWaPq0fHDdbn
|
||||||
|
- SIGNING_SALT=PL/THF0VMOzuv1bOcldjDzYFBLryvXNs
|
||||||
|
- HOST=localhost
|
||||||
|
- DATABASE_URL=postgres://postgres:postgres@plausible_db:5432/plausible
|
||||||
|
- DATABASE_TLS_ENABLED=false
|
||||||
|
- ADMIN_USER_NAME=admin
|
||||||
|
- ADMIN_USER_EMAIL=admin@plausible.local
|
||||||
|
- ADMIN_USER_PWD=admin@1234!
|
||||||
|
- APP_VERSION=test
|
||||||
|
- MAILER_ADAPTER=Bamboo.SMTPAdapter
|
||||||
|
- SMTP_HOST_ADDR=fakesmtp_server
|
||||||
|
- SMTP_HOST_PORT=1025
|
||||||
|
- SMTP_USER_NAME=fakeuser@plausible.local
|
||||||
|
- SMTP_USER_PWD=password
|
||||||
|
- SMTP_HOST_SSL_ENABLED=false
|
||||||
|
- SMTP_MX_LOOKUPS_ENABLED=false
|
||||||
|
- CLICKHOUSE_DATABASE_HOST=plausible_events_db
|
||||||
|
- CLICKHOUSE_DATABASE_NAME=plausible_events_db
|
||||||
|
depends_on:
|
||||||
|
- plausible_events_db
|
||||||
|
- plausible_db
|
||||||
|
- fakesmtp_server
|
||||||
|
ports:
|
||||||
|
- 80:8080
|
||||||
|
links:
|
||||||
|
- plausible_db
|
||||||
|
- plausible_events_db
|
||||||
|
- fakesmtp_server
|
||||||
|
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db-data:
|
||||||
|
driver: local
|
@ -20,6 +20,7 @@ defmodule Mix.Tasks.HydrateClickhouse do
|
|||||||
hydrate_events(repo)
|
hydrate_events(repo)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def create_events() do
|
def create_events() do
|
||||||
ddl = """
|
ddl = """
|
||||||
CREATE TABLE IF NOT EXISTS events (
|
CREATE TABLE IF NOT EXISTS events (
|
||||||
|
@ -39,7 +39,7 @@ defmodule Mix.Tasks.SendCheckStatsEmails do
|
|||||||
|
|
||||||
defp send_check_stats_email(_, user) do
|
defp send_check_stats_email(_, user) do
|
||||||
PlausibleWeb.Email.check_stats_email(user)
|
PlausibleWeb.Email.check_stats_email(user)
|
||||||
|> Plausible.Mailer.deliver_now()
|
|> Plausible.Mailer.send_email()
|
||||||
|
|
||||||
Repo.insert_all("check_stats_emails", [%{
|
Repo.insert_all("check_stats_emails", [%{
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
|
@ -91,7 +91,8 @@ defmodule Mix.Tasks.SendEmailReports do
|
|||||||
pages: pages,
|
pages: pages,
|
||||||
query: query,
|
query: query,
|
||||||
name: name
|
name: name
|
||||||
) |> Plausible.Mailer.deliver_now()
|
)
|
||||||
|
|> Plausible.Mailer.send_email()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp weekly_report_sent(site, time) do
|
defp weekly_report_sent(site, time) do
|
||||||
|
@ -80,7 +80,7 @@ defmodule Mix.Tasks.SendSiteSetupEmails do
|
|||||||
|
|
||||||
defp send_create_site_email(_, user) do
|
defp send_create_site_email(_, user) do
|
||||||
PlausibleWeb.Email.create_site_email(user)
|
PlausibleWeb.Email.create_site_email(user)
|
||||||
|> Plausible.Mailer.deliver_now()
|
|> Plausible.Mailer.send_email()
|
||||||
|
|
||||||
Repo.insert_all("create_site_emails", [%{
|
Repo.insert_all("create_site_emails", [%{
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
@ -94,7 +94,7 @@ defmodule Mix.Tasks.SendSiteSetupEmails do
|
|||||||
|
|
||||||
defp send_setup_success_email(_, user, site) do
|
defp send_setup_success_email(_, user, site) do
|
||||||
PlausibleWeb.Email.site_setup_success(user, site)
|
PlausibleWeb.Email.site_setup_success(user, site)
|
||||||
|> Plausible.Mailer.deliver_now()
|
|> Plausible.Mailer.send_email()
|
||||||
|
|
||||||
Repo.insert_all("setup_success_emails", [%{
|
Repo.insert_all("setup_success_emails", [%{
|
||||||
site_id: site.id,
|
site_id: site.id,
|
||||||
@ -108,7 +108,7 @@ defmodule Mix.Tasks.SendSiteSetupEmails do
|
|||||||
|
|
||||||
defp send_setup_help_email(_, user, site) do
|
defp send_setup_help_email(_, user, site) do
|
||||||
PlausibleWeb.Email.site_setup_help(user, site)
|
PlausibleWeb.Email.site_setup_help(user, site)
|
||||||
|> Plausible.Mailer.deliver_now()
|
|> Plausible.Mailer.send_email()
|
||||||
|
|
||||||
Repo.insert_all("setup_help_emails", [%{
|
Repo.insert_all("setup_help_emails", [%{
|
||||||
site_id: site.id,
|
site_id: site.id,
|
||||||
|
@ -52,7 +52,7 @@ defmodule Mix.Tasks.SendTrialNotifications do
|
|||||||
|
|
||||||
defp send_one_week_reminder(_, user) do
|
defp send_one_week_reminder(_, user) do
|
||||||
PlausibleWeb.Email.trial_one_week_reminder(user)
|
PlausibleWeb.Email.trial_one_week_reminder(user)
|
||||||
|> Plausible.Mailer.deliver_now()
|
|> Plausible.Mailer.send_email()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp send_tomorrow_reminder(["--dry-run"], user) do
|
defp send_tomorrow_reminder(["--dry-run"], user) do
|
||||||
@ -63,7 +63,7 @@ defmodule Mix.Tasks.SendTrialNotifications do
|
|||||||
usage = Plausible.Billing.usage(user)
|
usage = Plausible.Billing.usage(user)
|
||||||
|
|
||||||
PlausibleWeb.Email.trial_upgrade_email(user, "tomorrow", usage)
|
PlausibleWeb.Email.trial_upgrade_email(user, "tomorrow", usage)
|
||||||
|> Plausible.Mailer.deliver_now()
|
|> Plausible.Mailer.send_email()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp send_today_reminder(["--dry-run"], user) do
|
defp send_today_reminder(["--dry-run"], user) do
|
||||||
@ -74,7 +74,7 @@ defmodule Mix.Tasks.SendTrialNotifications do
|
|||||||
usage = Plausible.Billing.usage(user)
|
usage = Plausible.Billing.usage(user)
|
||||||
|
|
||||||
PlausibleWeb.Email.trial_upgrade_email(user, "today", usage)
|
PlausibleWeb.Email.trial_upgrade_email(user, "today", usage)
|
||||||
|> Plausible.Mailer.deliver_now()
|
|> Plausible.Mailer.send_email()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp send_over_reminder(["--dry-run"], user) do
|
defp send_over_reminder(["--dry-run"], user) do
|
||||||
|
@ -3,7 +3,7 @@ defmodule Plausible.Google.Api do
|
|||||||
@verified_permission_levels ["siteOwner", "siteFullUser", "siteRestrictedUser"]
|
@verified_permission_levels ["siteOwner", "siteFullUser", "siteRestrictedUser"]
|
||||||
|
|
||||||
def authorize_url(site_id) do
|
def authorize_url(site_id) do
|
||||||
if Mix.env() == :test do
|
if Application.get_env(:plausible, :environment) == "test" do
|
||||||
""
|
""
|
||||||
else
|
else
|
||||||
"https://accounts.google.com/o/oauth2/v2/auth?client_id=#{client_id()}&redirect_uri=#{redirect_uri()}&prompt=consent&response_type=code&access_type=offline&scope=#{@scope}&state=#{site_id}"
|
"https://accounts.google.com/o/oauth2/v2/auth?client_id=#{client_id()}&redirect_uri=#{redirect_uri()}&prompt=consent&response_type=code&access_type=offline&scope=#{@scope}&state=#{site_id}"
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
defmodule Plausible.Mailer do
|
defmodule Plausible.Mailer do
|
||||||
use Bamboo.Mailer, otp_app: :plausible
|
use Bamboo.Mailer, otp_app: :plausible
|
||||||
|
|
||||||
|
def send_email(email) do
|
||||||
|
try do
|
||||||
|
Plausible.Mailer.deliver_now(email)
|
||||||
|
rescue
|
||||||
|
error ->
|
||||||
|
Sentry.capture_exception(error,
|
||||||
|
stacktrace: __STACKTRACE__,
|
||||||
|
extra: %{extra: "Error while sending email"}
|
||||||
|
)
|
||||||
|
|
||||||
|
raise error
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
234
lib/plausible_release.ex
Normal file
234
lib/plausible_release.ex
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
defmodule Plausible.Release do
|
||||||
|
use Plausible.Repo
|
||||||
|
@app :plausible
|
||||||
|
@start_apps [
|
||||||
|
:postgrex,
|
||||||
|
:ecto
|
||||||
|
]
|
||||||
|
alias Mix.Tasks.HydrateClickhouse, as: Clickhouse
|
||||||
|
|
||||||
|
def init_admin do
|
||||||
|
{admin_email, admin_user, admin_pwd} =
|
||||||
|
validate_admin(
|
||||||
|
{Application.get_env(:plausible, :admin_email),
|
||||||
|
Application.get_env(:plausible, :admin_user),
|
||||||
|
Application.get_env(:plausible, :admin_pwd)}
|
||||||
|
)
|
||||||
|
|
||||||
|
{:ok, admin} = Plausible.Auth.create_user(admin_user, admin_email)
|
||||||
|
# set the password
|
||||||
|
{:ok, admin} = Plausible.Auth.User.set_password(admin, admin_pwd) |> Repo.update()
|
||||||
|
# bump-up the trail period
|
||||||
|
admin
|
||||||
|
|> Ecto.Changeset.cast(%{trial_expiry_date: Timex.today() |> Timex.shift(years: 100)}, [
|
||||||
|
:trial_expiry_date
|
||||||
|
])
|
||||||
|
|> Repo.update()
|
||||||
|
|
||||||
|
IO.puts("Admin user created successful!")
|
||||||
|
end
|
||||||
|
|
||||||
|
def migrate do
|
||||||
|
prepare()
|
||||||
|
Enum.each(repos(), &run_migrations_for/1)
|
||||||
|
init_admin()
|
||||||
|
IO.puts("Migrations successful!")
|
||||||
|
end
|
||||||
|
|
||||||
|
def seed do
|
||||||
|
prepare()
|
||||||
|
# Run seed script
|
||||||
|
Enum.each(repos(), &run_seeds_for/1)
|
||||||
|
|
||||||
|
# Signal shutdown
|
||||||
|
IO.puts("Success!")
|
||||||
|
end
|
||||||
|
|
||||||
|
def createdb do
|
||||||
|
prepare()
|
||||||
|
do_create_db()
|
||||||
|
IO.puts("Creation of Db successful!")
|
||||||
|
end
|
||||||
|
|
||||||
|
def rollback do
|
||||||
|
prepare()
|
||||||
|
|
||||||
|
get_step =
|
||||||
|
IO.gets("Enter the number of steps: ")
|
||||||
|
|> String.trim()
|
||||||
|
|> Integer.parse()
|
||||||
|
|
||||||
|
case get_step do
|
||||||
|
{int, _trailing} ->
|
||||||
|
Enum.each(repos(), fn repo -> run_rollbacks_for(repo, int) end)
|
||||||
|
IO.puts("Rollback successful!")
|
||||||
|
|
||||||
|
:error ->
|
||||||
|
IO.puts("Invalid integer")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##############################
|
||||||
|
|
||||||
|
defp validate_admin({nil, nil, nil}) do
|
||||||
|
random_user = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
|
||||||
|
random_pwd = :crypto.strong_rand_bytes(20) |> Base.encode64() |> binary_part(0, 20)
|
||||||
|
random_email = "#{random_user}@#{System.get_env("HOST")}"
|
||||||
|
IO.puts("generated admin user/password: #{random_email} / #{random_pwd}")
|
||||||
|
{random_email, random_user, random_pwd}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp validate_admin({admin_email, admin_user, admin_password}) do
|
||||||
|
{admin_email, admin_user, admin_password}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp repos do
|
||||||
|
Application.fetch_env!(@app, :ecto_repos)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp run_seeds_for(repo) do
|
||||||
|
# Run the seed script if it exists
|
||||||
|
seed_script = seeds_path(repo)
|
||||||
|
|
||||||
|
if File.exists?(seed_script) do
|
||||||
|
IO.puts("Running seed script..")
|
||||||
|
Code.eval_file(seed_script)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp run_migrations_for(repo) do
|
||||||
|
app = Keyword.get(repo.config, :otp_app)
|
||||||
|
IO.puts("Running migrations for #{app}")
|
||||||
|
{:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp do_create_db do
|
||||||
|
for repo <- repos() do
|
||||||
|
:ok = ensure_repo_created(repo)
|
||||||
|
end
|
||||||
|
do_create_ch_db()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
defp do_create_ch_db() do
|
||||||
|
db_to_create = Keyword.get(Application.get_env(:plausible, :clickhouse),:database)
|
||||||
|
|
||||||
|
IO.puts("create #{inspect(db_to_create)} clickhouse database/tables if it doesn't exist")
|
||||||
|
|
||||||
|
Clickhousex.query(:clickhouse, "CREATE DATABASE IF NOT EXISTS #{db_to_create}", [])
|
||||||
|
|
||||||
|
tb_events = """
|
||||||
|
CREATE TABLE IF NOT EXISTS #{db_to_create}.events (
|
||||||
|
timestamp DateTime,
|
||||||
|
name String,
|
||||||
|
domain String,
|
||||||
|
user_id UInt64,
|
||||||
|
session_id UInt64,
|
||||||
|
hostname String,
|
||||||
|
pathname String,
|
||||||
|
referrer String,
|
||||||
|
referrer_source String,
|
||||||
|
initial_referrer String,
|
||||||
|
initial_referrer_source String,
|
||||||
|
country_code LowCardinality(FixedString(2)),
|
||||||
|
screen_size LowCardinality(String),
|
||||||
|
operating_system LowCardinality(String),
|
||||||
|
browser LowCardinality(String)
|
||||||
|
) ENGINE = MergeTree()
|
||||||
|
PARTITION BY toYYYYMM(timestamp)
|
||||||
|
ORDER BY (name, domain, user_id, timestamp)
|
||||||
|
SETTINGS index_granularity = 8192
|
||||||
|
"""
|
||||||
|
|
||||||
|
Clickhousex.query(:clickhouse, tb_events, [])
|
||||||
|
|
||||||
|
tb_sessions = """
|
||||||
|
CREATE TABLE IF NOT EXISTS #{db_to_create}.sessions (
|
||||||
|
session_id UInt64,
|
||||||
|
sign Int8,
|
||||||
|
domain String,
|
||||||
|
user_id UInt64,
|
||||||
|
hostname String,
|
||||||
|
timestamp DateTime,
|
||||||
|
start DateTime,
|
||||||
|
is_bounce UInt8,
|
||||||
|
entry_page String,
|
||||||
|
exit_page String,
|
||||||
|
pageviews Int32,
|
||||||
|
events Int32,
|
||||||
|
duration UInt32,
|
||||||
|
referrer String,
|
||||||
|
referrer_source String,
|
||||||
|
country_code LowCardinality(FixedString(2)),
|
||||||
|
screen_size LowCardinality(String),
|
||||||
|
operating_system LowCardinality(String),
|
||||||
|
browser LowCardinality(String)
|
||||||
|
) ENGINE = CollapsingMergeTree(sign)
|
||||||
|
PARTITION BY toYYYYMM(start)
|
||||||
|
ORDER BY (domain, user_id, session_id, start)
|
||||||
|
SETTINGS index_granularity = 8192
|
||||||
|
"""
|
||||||
|
|
||||||
|
Clickhousex.query(:clickhouse, tb_sessions, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
defp ensure_repo_created(repo) do
|
||||||
|
IO.puts("create #{inspect(repo)} database if it doesn't exist")
|
||||||
|
|
||||||
|
case repo.__adapter__.storage_up(repo.config) do
|
||||||
|
:ok -> :ok
|
||||||
|
{:error, :already_up} -> :ok
|
||||||
|
{:error, term} -> {:error, term}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp run_rollbacks_for(repo, step) do
|
||||||
|
app = Keyword.get(repo.config, :otp_app)
|
||||||
|
IO.puts("Running rollbacks for #{app} (STEP=#{step})")
|
||||||
|
|
||||||
|
{:ok, _, _} =
|
||||||
|
Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, all: false, step: step))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp prepare do
|
||||||
|
IO.puts("Loading #{@app}..")
|
||||||
|
# Load the code for myapp, but don't start it
|
||||||
|
:ok = Application.load(@app)
|
||||||
|
|
||||||
|
prepare_clickhouse()
|
||||||
|
|
||||||
|
IO.puts("Starting dependencies..")
|
||||||
|
# Start apps necessary for executing migrations
|
||||||
|
Enum.each(@start_apps, &Application.ensure_all_started/1)
|
||||||
|
|
||||||
|
|
||||||
|
# Start the Repo(s) for myapp
|
||||||
|
IO.puts("Starting repos..")
|
||||||
|
Enum.each(repos(), & &1.start_link(pool_size: 2))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
defp prepare_clickhouse do
|
||||||
|
Application.ensure_all_started(:db_connection)
|
||||||
|
Application.ensure_all_started(:hackney)
|
||||||
|
Clickhousex.start_link([
|
||||||
|
scheme: :http,
|
||||||
|
port: 8123,
|
||||||
|
name: :clickhouse,
|
||||||
|
database: "default",
|
||||||
|
hostname: Keyword.get(Application.get_env(:plausible,:clickhouse),:hostname)
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
defp seeds_path(repo), do: priv_path_for(repo, "seeds.exs")
|
||||||
|
|
||||||
|
defp priv_path_for(repo, filename) do
|
||||||
|
app = Keyword.get(repo.config, :otp_app)
|
||||||
|
IO.puts("App: #{app}")
|
||||||
|
repo_underscore = repo |> Module.split() |> List.last() |> Macro.underscore()
|
||||||
|
Path.join([priv_dir(app), repo_underscore, filename])
|
||||||
|
end
|
||||||
|
|
||||||
|
defp priv_dir(app), do: "#{:code.priv_dir(app)}"
|
||||||
|
end
|
@ -21,7 +21,7 @@ defmodule PlausibleWeb.AuthController do
|
|||||||
url = PlausibleWeb.Endpoint.clean_url() <> "/claim-activation?token=#{token}"
|
url = PlausibleWeb.Endpoint.clean_url() <> "/claim-activation?token=#{token}"
|
||||||
Logger.info(url)
|
Logger.info(url)
|
||||||
email_template = PlausibleWeb.Email.activation_email(user, url)
|
email_template = PlausibleWeb.Email.activation_email(user, url)
|
||||||
Plausible.Mailer.deliver_now(email_template)
|
Plausible.Mailer.send_email(email_template)
|
||||||
conn |> render("register_success.html", email: user.email, layout: {PlausibleWeb.LayoutView, "focus.html"})
|
conn |> render("register_success.html", email: user.email, layout: {PlausibleWeb.LayoutView, "focus.html"})
|
||||||
{:error, changeset} ->
|
{:error, changeset} ->
|
||||||
render(conn, "register_form.html", changeset: changeset, layout: {PlausibleWeb.LayoutView, "focus.html"})
|
render(conn, "register_form.html", changeset: changeset, layout: {PlausibleWeb.LayoutView, "focus.html"})
|
||||||
@ -34,7 +34,7 @@ defmodule PlausibleWeb.AuthController do
|
|||||||
case Auth.create_user(name, email) do
|
case Auth.create_user(name, email) do
|
||||||
{:ok, user} ->
|
{:ok, user} ->
|
||||||
PlausibleWeb.Email.welcome_email(user)
|
PlausibleWeb.Email.welcome_email(user)
|
||||||
|> Plausible.Mailer.deliver_now()
|
|> Plausible.Mailer.send_email()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_session(:current_user_id, user.id)
|
|> put_session(:current_user_id, user.id)
|
||||||
|
@ -6,6 +6,10 @@ defmodule PlausibleWeb.BillingController do
|
|||||||
|
|
||||||
plug PlausibleWeb.RequireAccountPlug
|
plug PlausibleWeb.RequireAccountPlug
|
||||||
|
|
||||||
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
def change_plan_form(conn, _params) do
|
def change_plan_form(conn, _params) do
|
||||||
subscription = Billing.active_subscription_for(conn.assigns[:current_user].id)
|
subscription = Billing.active_subscription_for(conn.assigns[:current_user].id)
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ defmodule PlausibleWeb.PageController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def submit_contact_form(conn, %{"text" => text, "email" => email}) do
|
def submit_contact_form(conn, %{"text" => text, "email" => email}) do
|
||||||
PlausibleWeb.Email.feedback(email, text) |> Plausible.Mailer.deliver_now
|
PlausibleWeb.Email.feedback(email, text) |> Plausible.Mailer.send_email()
|
||||||
render(conn, "contact_thanks.html")
|
render(conn, "contact_thanks.html")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,6 +6,10 @@ defmodule PlausibleWeb.StatsController do
|
|||||||
|
|
||||||
plug PlausibleWeb.AuthorizeStatsPlug when action in [:stats, :csv_export]
|
plug PlausibleWeb.AuthorizeStatsPlug when action in [:stats, :csv_export]
|
||||||
|
|
||||||
|
def base_domain() do
|
||||||
|
PlausibleWeb.Endpoint.host()
|
||||||
|
end
|
||||||
|
|
||||||
def stats(conn, _params) do
|
def stats(conn, _params) do
|
||||||
site = conn.assigns[:site]
|
site = conn.assigns[:site]
|
||||||
user = conn.assigns[:current_user]
|
user = conn.assigns[:current_user]
|
||||||
@ -14,7 +18,7 @@ defmodule PlausibleWeb.StatsController do
|
|||||||
redirect(conn, to: "/billing/upgrade")
|
redirect(conn, to: "/billing/upgrade")
|
||||||
else
|
else
|
||||||
if Stats.has_pageviews?(site) do
|
if Stats.has_pageviews?(site) do
|
||||||
demo = site.domain == "plausible.io"
|
demo = site.domain == base_domain()
|
||||||
offer_email_report = get_session(conn, site.domain <> "_offer_email_report")
|
offer_email_report = get_session(conn, site.domain <> "_offer_email_report")
|
||||||
|
|
||||||
conn
|
conn
|
||||||
@ -108,4 +112,3 @@ defmodule PlausibleWeb.StatsController do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2,10 +2,18 @@ defmodule PlausibleWeb.Email do
|
|||||||
use Bamboo.Phoenix, view: PlausibleWeb.EmailView
|
use Bamboo.Phoenix, view: PlausibleWeb.EmailView
|
||||||
import Bamboo.PostmarkHelper
|
import Bamboo.PostmarkHelper
|
||||||
|
|
||||||
|
def mailer_email_from do
|
||||||
|
Application.get_env(:plausible, :mailer_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
def activation_email(user, link) do
|
def activation_email(user, link) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user.email)
|
|> to(user.email)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("activation-email")
|
|> tag("activation-email")
|
||||||
|> subject("Activate your Plausible free trial")
|
|> subject("Activate your Plausible free trial")
|
||||||
|> render("activation_email.html", name: user.name, link: link)
|
|> render("activation_email.html", name: user.name, link: link)
|
||||||
@ -14,7 +22,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def welcome_email(user) do
|
def welcome_email(user) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user)
|
|> to(user)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("welcome-email")
|
|> tag("welcome-email")
|
||||||
|> subject("Welcome to Plausible")
|
|> subject("Welcome to Plausible")
|
||||||
|> render("welcome_email.html", user: user)
|
|> render("welcome_email.html", user: user)
|
||||||
@ -23,7 +31,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def create_site_email(user) do
|
def create_site_email(user) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user)
|
|> to(user)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("create-site-email")
|
|> tag("create-site-email")
|
||||||
|> subject("Your Plausible setup: Add your website details")
|
|> subject("Your Plausible setup: Add your website details")
|
||||||
|> render("create_site_email.html", user: user)
|
|> render("create_site_email.html", user: user)
|
||||||
@ -32,7 +40,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def site_setup_help(user, site) do
|
def site_setup_help(user, site) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user)
|
|> to(user)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("help-email")
|
|> tag("help-email")
|
||||||
|> subject("Your Plausible setup: Waiting for the first page views")
|
|> subject("Your Plausible setup: Waiting for the first page views")
|
||||||
|> render("site_setup_help_email.html", user: user, site: site)
|
|> render("site_setup_help_email.html", user: user, site: site)
|
||||||
@ -41,7 +49,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def site_setup_success(user, site) do
|
def site_setup_success(user, site) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user)
|
|> to(user)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("setup-success-email")
|
|> tag("setup-success-email")
|
||||||
|> subject("Plausible is now tracking your website stats")
|
|> subject("Plausible is now tracking your website stats")
|
||||||
|> render("site_setup_success_email.html", user: user, site: site)
|
|> render("site_setup_success_email.html", user: user, site: site)
|
||||||
@ -50,7 +58,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def check_stats_email(user) do
|
def check_stats_email(user) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user)
|
|> to(user)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("check-stats-email")
|
|> tag("check-stats-email")
|
||||||
|> subject("Check your Plausible website stats")
|
|> subject("Check your Plausible website stats")
|
||||||
|> render("check_stats_email.html", user: user)
|
|> render("check_stats_email.html", user: user)
|
||||||
@ -59,7 +67,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def password_reset_email(email, reset_link) do
|
def password_reset_email(email, reset_link) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(email)
|
|> to(email)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("password-reset-email")
|
|> tag("password-reset-email")
|
||||||
|> subject("Plausible password reset")
|
|> subject("Plausible password reset")
|
||||||
|> render("password_reset_email.html", reset_link: reset_link)
|
|> render("password_reset_email.html", reset_link: reset_link)
|
||||||
@ -68,7 +76,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def trial_one_week_reminder(user) do
|
def trial_one_week_reminder(user) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user)
|
|> to(user)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("trial-one-week-reminder")
|
|> tag("trial-one-week-reminder")
|
||||||
|> subject("Your Plausible trial expires next week")
|
|> subject("Your Plausible trial expires next week")
|
||||||
|> render("trial_one_week_reminder.html", user: user)
|
|> render("trial_one_week_reminder.html", user: user)
|
||||||
@ -77,7 +85,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def trial_upgrade_email(user, day, pageviews) do
|
def trial_upgrade_email(user, day, pageviews) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user)
|
|> to(user)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("trial-upgrade-email")
|
|> tag("trial-upgrade-email")
|
||||||
|> subject("Your Plausible trial ends #{day}")
|
|> subject("Your Plausible trial ends #{day}")
|
||||||
|> render("trial_upgrade_email.html", user: user, day: day, pageviews: pageviews)
|
|> render("trial_upgrade_email.html", user: user, day: day, pageviews: pageviews)
|
||||||
@ -86,7 +94,7 @@ defmodule PlausibleWeb.Email do
|
|||||||
def trial_over_email(user) do
|
def trial_over_email(user) do
|
||||||
base_email()
|
base_email()
|
||||||
|> to(user)
|
|> to(user)
|
||||||
|> from("Uku Taht <uku@plausible.io>")
|
|> from(mailer_email_from())
|
||||||
|> tag("trial-over-email")
|
|> tag("trial-over-email")
|
||||||
|> subject("Your Plausible trial has ended")
|
|> subject("Your Plausible trial has ended")
|
||||||
|> render("trial_over_email.html", user: user)
|
|> render("trial_over_email.html", user: user)
|
||||||
|
@ -44,11 +44,11 @@ defmodule PlausibleWeb.Endpoint do
|
|||||||
|
|
||||||
def clean_url() do
|
def clean_url() do
|
||||||
url = PlausibleWeb.Endpoint.url
|
url = PlausibleWeb.Endpoint.url
|
||||||
|
case Application.get_env(:plausible, :environment) do
|
||||||
if Mix.env() == :prod do
|
# do not truncate the port in case of dev or test environment
|
||||||
URI.parse(url) |> Map.put(:port, nil) |> URI.to_string()
|
env when env in ["dev", "test"] -> url
|
||||||
else
|
# in most deployments, there's a layer above the above
|
||||||
url
|
_ -> URI.parse(url) |> Map.put(:port, nil) |> URI.to_string()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -29,7 +29,7 @@ defmodule PlausibleWeb.Router do
|
|||||||
plug :fetch_session
|
plug :fetch_session
|
||||||
end
|
end
|
||||||
|
|
||||||
if Mix.env == :dev do
|
if Application.get_env(:plausible, :environment) == "dev" do
|
||||||
forward "/sent-emails", Bamboo.SentEmailViewerPlug
|
forward "/sent-emails", Bamboo.SentEmailViewerPlug
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ Hey <%= user_salutation(@user) %>,
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
Plausible is tracking your website stats without compromising the user experience and the privacy of your visitors.
|
Plausible is tracking your website stats without compromising the user experience and the privacy of your visitors.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<%= link("View your Plausible dashboard now", to: "https://plausible.io/") %> for the most valuable traffic insights at a glance.
|
<%= link("View your Plausible dashboard now", to: "#{plausible_url()}") %> for the most valuable traffic insights at a glance.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Do reply back to this email if you have any questions or need some guidance.
|
Do reply back to this email if you have any questions or need some guidance.
|
||||||
<br /></br>
|
<br /></br>
|
||||||
@ -11,4 +11,4 @@ Uku Taht
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
--
|
--
|
||||||
<br /><br />
|
<br /><br />
|
||||||
https://plausible.io
|
<%= plausible_url() %>
|
||||||
|
@ -2,7 +2,7 @@ Hey <%= user_salutation(@user) %>,
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
You've activated your free 30-day trial of Plausible, a simple and privacy-friendly website analytics tool.
|
You've activated your free 30-day trial of Plausible, a simple and privacy-friendly website analytics tool.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<%= link("Click here", to: "https://plausible.io/sites/new") %> to add your website URL, your timezone and install our one-line JavaScript snippet to start collecting visitor statistics.
|
<%= link("Click here", to: "#{plausible_url()}/sites/new") %> to add your website URL, your timezone and install our one-line JavaScript snippet to start collecting visitor statistics.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Do reply back to this email if you have any questions or need some guidance.
|
Do reply back to this email if you have any questions or need some guidance.
|
||||||
<br /></br>
|
<br /></br>
|
||||||
@ -11,4 +11,4 @@ Uku Taht
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
--
|
--
|
||||||
<br /><br />
|
<br /><br />
|
||||||
https://plausible.io
|
<%= plausible_url() %>
|
||||||
|
@ -4,7 +4,7 @@ Hey <%= user_salutation(@user) %>,
|
|||||||
You signed up for a free 30-day trial of Plausible, a simple and privacy-friendly website analytics tool.
|
You signed up for a free 30-day trial of Plausible, a simple and privacy-friendly website analytics tool.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<% end %>
|
<% end %>
|
||||||
To finish your setup for <%= @site.domain %>, you need to install <%= link("this lightweight line of JavaScript code", to: "https://plausible.io/#{URI.encode_www_form(@site.domain)}/snippet") %> into your site to start collecting visitor statistics.
|
To finish your setup for <%= @site.domain %>, you need to install <%= link("this lightweight line of JavaScript code", to: "#{plausible_url()}/#{URI.encode_www_form(@site.domain)}/snippet") %> into your site to start collecting visitor statistics.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
This Plausible script is 14 times smaller than Google Analytics script so you’ll have a fast loading site while getting all the important traffic insights on one single page.
|
This Plausible script is 14 times smaller than Google Analytics script so you’ll have a fast loading site while getting all the important traffic insights on one single page.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
@ -15,4 +15,4 @@ Uku Taht
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
--
|
--
|
||||||
<br /><br />
|
<br /><br />
|
||||||
https://plausible.io
|
<%= plausible_url() %>
|
||||||
|
@ -2,13 +2,13 @@ Hey <%= user_salutation(@user) %>,
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
Congrats! The Plausible script has been installed correctly on <%= link(@site.domain, to: "https://#{@site.domain}") %>. Your website traffic is now being tracked without compromising the user experience and the privacy of your visitors.
|
Congrats! The Plausible script has been installed correctly on <%= link(@site.domain, to: "https://#{@site.domain}") %>. Your website traffic is now being tracked without compromising the user experience and the privacy of your visitors.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<%= link("Check your stats", to: "https://plausible.io/#{URI.encode_www_form(@site.domain)}") %>
|
<%= link("Check your stats", to: "#{plausible_url()}/#{URI.encode_www_form(@site.domain)}") %>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<%= if Plausible.Billing.on_trial?(@user) do %>
|
<%= if Plausible.Billing.on_trial?(@user) do %>
|
||||||
You're on a 30-day unlimited-use free trial with no obligations so do take your time to explore your simple and privacy-friendly website analytics dashboard.
|
You're on a 30-day unlimited-use free trial with no obligations so do take your time to explore your simple and privacy-friendly website analytics dashboard.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<% end %>
|
<% end %>
|
||||||
PS: Plausible is fully open-source and our public roadmap is defined by the community. <%= link("Leave your feedback", to: "https://plausible.io/feedback") %> and have your say on metrics and features we should be adding next.
|
PS: Plausible is fully open-source and our public roadmap is defined by the community. <%= link("Leave your feedback", to: "#{plausible_url()}/feedback") %> and have your say on metrics and features we should be adding next.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Do reply back to this email if you have any questions.
|
Do reply back to this email if you have any questions.
|
||||||
<br /></br>
|
<br /></br>
|
||||||
@ -17,4 +17,5 @@ Uku Taht
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
--
|
--
|
||||||
<br /><br />
|
<br /><br />
|
||||||
https://plausible.io
|
<%= plausible_url() %>
|
||||||
|
|
||||||
|
@ -4,10 +4,10 @@ Time flies! Your 30-day free trial of Plausible will end next week.
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
Over the last three weeks, I hope you got to experience the potential benefits of having website stats in a simple dashboard while respecting the privacy of your visitors, not annoying them with the cookie and privacy notices and still having a fast loading site.
|
Over the last three weeks, I hope you got to experience the potential benefits of having website stats in a simple dashboard while respecting the privacy of your visitors, not annoying them with the cookie and privacy notices and still having a fast loading site.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
In order to continue receiving valuable website traffic insights at a glance, you’ll need to <%= link("Upgrade your account", to: "https://plausible.io/billing/upgrade") %>.
|
In order to continue receiving valuable website traffic insights at a glance, you’ll need to <%= link("Upgrade your account", to: "#{plausible_url()}/billing/upgrade") %>.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
If you have any questions or feedback for me, feel free to reply to this email.
|
If you have any questions or feedback for me, feel free to reply to this email.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Thanks,<br />
|
Thanks,<br />
|
||||||
Uku Taht<br />
|
Uku Taht<br />
|
||||||
https://plausible.io
|
<%= plausible_url() %>
|
||||||
|
@ -2,7 +2,7 @@ Hey <%= user_salutation(@user) %>,
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
Your free Plausible trial has now expired. Upgrade your account to continue receiving valuable website traffic insights at a glance while respecting the privacy of your visitors and still having a fast loading site. <br /><br />
|
Your free Plausible trial has now expired. Upgrade your account to continue receiving valuable website traffic insights at a glance while respecting the privacy of your visitors and still having a fast loading site. <br /><br />
|
||||||
|
|
||||||
<%= link("Upgrade now", to: "https://plausible.io/billing/upgrade") %>
|
<%= link("Upgrade now", to: "#{plausible_url()}/billing/upgrade") %>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
|
|
||||||
We will keep recording stats for another month to give you time to upgrade.
|
We will keep recording stats for another month to give you time to upgrade.
|
||||||
@ -14,4 +14,4 @@ Founder, Plausible Insights
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
--
|
--
|
||||||
<br /><br />
|
<br /><br />
|
||||||
https://plausible.io
|
<%= plausible_url() %>
|
@ -6,11 +6,11 @@ In the last month, your account has used <%= PlausibleWeb.AuthView.delimit_integ
|
|||||||
Based on that we recommend you select the <%= suggested_plan_name(@pageviews) %> plan which runs at <%= suggested_plan_cost(@pageviews) %>.
|
Based on that we recommend you select the <%= suggested_plan_name(@pageviews) %> plan which runs at <%= suggested_plan_cost(@pageviews) %>.
|
||||||
You can also go with yearly billing to get 33% off on your plan.
|
You can also go with yearly billing to get 33% off on your plan.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<%= link("Upgrade now", to: "https://plausible.io/billing/upgrade") %>
|
<%= link("Upgrade now", to: "#{plausible_url()}/billing/upgrade") %>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Have a question, feedback or need some guidance? Just reply to this email to get in touch!
|
Have a question, feedback or need some guidance? Just reply to this email to get in touch!
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Thanks,<br />
|
Thanks,<br />
|
||||||
Uku Taht<br />
|
Uku Taht<br />
|
||||||
https://plausible.io
|
<%= plausible_url() %>
|
||||||
|
@ -3,7 +3,7 @@ Hey <%= user_salutation(@user) %>,
|
|||||||
I'm building Plausible to provide a simple and ethical approach to tracking website visitors.
|
I'm building Plausible to provide a simple and ethical approach to tracking website visitors.
|
||||||
I'm super excited to have you on board!
|
I'm super excited to have you on board!
|
||||||
<br /><br />
|
<br /><br />
|
||||||
To start collecting stats, you need to <%= link("add a site on Plausible", to: "https://plausible.io/sites/new") %>.
|
To start collecting stats, you need to <%= link("add a site on Plausible", to: "#{plausible_url()}/sites/new") %>.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Have a question, feedback or need some guidance? Do reply back to this email.
|
Have a question, feedback or need some guidance? Do reply back to this email.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
@ -12,4 +12,4 @@ Uku Taht
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
--
|
--
|
||||||
<br /><br />
|
<br /><br />
|
||||||
https://plausible.io
|
<%= plausible_url() %>
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="text-center md:text-left my-4 md:m-0">
|
<ul class="text-center md:text-left my-4 md:m-0">
|
||||||
<li>Read our <a href="/blog/" class="light-text font-medium mr-4 underline">Blog</a></li>
|
<li>Read our <a href="/blog/" class="light-text font-medium mr-4 underline">Blog</a></li>
|
||||||
<li>Study the <a href="https://docs.plausible.io" target="_blank" class="light-text font-medium mr-4 underline">Documentation</a></li>
|
<li>Study the <%= link("Documentation", to: "https://docs.#{base_domain()}",target: "_blank",class: "light-text font-medium mr-4 underline") %></li>
|
||||||
<li>Check out the <a href="/plausible.io" class="light-text font-medium underline">Live Demo</a></li>
|
<li>Check out the <%= link("Live Demo", to: "/plausible.io",class: "light-text font-medium underline") %></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="text-center md:text-left my-4 md:m-0">
|
<ul class="text-center md:text-left my-4 md:m-0">
|
||||||
<li>Give us <a href="/feedback" target="_blank" class="light-text font-medium mr-4 underline">Feedback</a></li>
|
<li>Give us <a href="/feedback" target="_blank" class="light-text font-medium mr-4 underline">Feedback</a></li>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<%= if !@conn.assigns[:skip_plausible_tracking] do %>
|
<%= if !@conn.assigns[:skip_plausible_tracking] do %>
|
||||||
<script async defer src="https://plausible.io/js/plausible.js"></script>
|
<script async defer src="<%="#{plausible_url()}/js/plausible.js"%>"></script>
|
||||||
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
|
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
|
||||||
<% end %>
|
<% end %>
|
@ -1,6 +1,6 @@
|
|||||||
<div class="max-w-md mx-auto py-12 just-text">
|
<div class="max-w-md mx-auto py-12 just-text">
|
||||||
<h1 class="text-xl font-black mb-4">Privacy Policy</h1>
|
<h1 class="text-xl font-black mb-4">Privacy Policy</h1>
|
||||||
<p>Your privacy is important to us. It is Plausible Insights' policy to respect your privacy regarding any information we may collect from you across our website, <a href="http://plausible.io">http://plausible.io</a>, and other sites we own and operate.</p>
|
<p>Your privacy is important to us. It is Plausible Analytics' policy to respect your privacy regarding any information we may collect from you across our website, <%= link(plausible_url(), to: plausible_url()) %>, and other sites we own and operate.</p>
|
||||||
<p>We only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.</p>
|
<p>We only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.</p>
|
||||||
<p>We only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorised access, disclosure, copying, use or modification.</p>
|
<p>We only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorised access, disclosure, copying, use or modification.</p>
|
||||||
<p>We don’t share any personally identifying information publicly or with third-parties, except when required to by law.</p>
|
<p>We don’t share any personally identifying information publicly or with third-parties, except when required to by law.</p>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="max-w-2xl mx-auto leading-normal py-12 just-text">
|
<div class="max-w-2xl mx-auto leading-normal py-12 just-text">
|
||||||
<h1 class="text-2xl font-black mb-4">Terms of Service</h1>
|
<h1 class="text-2xl font-black mb-4">Terms of Service</h1>
|
||||||
<h3 class="text-lg font-black">1. Terms</h3>
|
<h3 class="text-lg font-black">1. Terms</h3>
|
||||||
<p>By accessing the website at <a href="http://plausible.io">http://plausible.io</a>, you are agreeing to be bound by these terms of service, all applicable laws and regulations, and agree that you are responsible for compliance with any applicable local laws. If you do not agree with any of these terms, you are prohibited from using or accessing this site. The materials contained in this website are protected by applicable copyright and trademark law.</p>
|
<p>By accessing the website at <%= link(plausible_url(), to: plausible_url()) %>, you are agreeing to be bound by these terms of service, all applicable laws and regulations, and agree that you are responsible for compliance with any applicable local laws. If you do not agree with any of these terms, you are prohibited from using or accessing this site. The materials contained in this website are protected by applicable copyright and trademark law.</p>
|
||||||
<h3 class="text-lg font-black">2. Use License</h3>
|
<h3 class="text-lg font-black">2. Use License</h3>
|
||||||
<ol type="a" class="list-decimal pl-4">
|
<ol type="a" class="list-decimal pl-4">
|
||||||
<li>Permission is granted to temporarily download one copy of the materials (information or software) on Plausible Insights' website for personal, non-commercial transitory viewing only. This is the grant of a license, not a transfer of title, and under this license you may not:
|
<li>Permission is granted to temporarily download one copy of the materials (information or software) on Plausible Insights' website for personal, non-commercial transitory viewing only. This is the grant of a license, not a transfer of title, and under this license you may not:
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
<ol class="list-disc pl-4 my-4">
|
<ol class="list-disc pl-4 my-4">
|
||||||
<li>Go to your DNS provider’s website</li>
|
<li>Go to your DNS provider’s website</li>
|
||||||
<li class="mt-4">Create a new CNAME record for <code><%= @site.custom_domain.domain %></code></li>
|
<li class="mt-4">Create a new CNAME record for <code><%= @site.custom_domain.domain %></code></li>
|
||||||
<li class="mt-4">Point the record to <code>custom.plausible.io.</code> (including the dot)</li>
|
<li class="mt-4">Point the record to <code>custom.<%= plausible_url() %>.</code> (including the dot)</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<%= link("Done ->", to: "/sites/#{URI.encode_www_form(@site.domain)}/custom-domains/snippet", class: "button w-full mt-6") %>
|
<%= link("Done ->", to: "/sites/#{URI.encode_www_form(@site.domain)}/custom-domains/snippet", class: "button w-full mt-6") %>
|
||||||
</div>
|
</div>
|
@ -35,7 +35,7 @@
|
|||||||
<%= if @site.public do %>
|
<%= if @site.public do %>
|
||||||
Stats for <%= @site.domain %> are currently <b>public</b>. Anyone with the following link can view the stats:
|
Stats for <%= @site.domain %> are currently <b>public</b>. Anyone with the following link can view the stats:
|
||||||
<div class="relative text-sm mt-4">
|
<div class="relative text-sm mt-4">
|
||||||
<input type="text" id="public-link" value="https://plausible.io/<%= URI.encode_www_form(@site.domain) %>" class="transition bg-gray-100 appearance-none border border-transparent rounded w-full p-2 pr-16 text-gray-700 appearance-none focus:outline-none" />
|
<input type="text" id="public-link" value="<%= base_domain() <> "/" <> URI.encode_www_form(@site.domain)%>" class="transition bg-gray-100 appearance-none border border-transparent rounded w-full p-2 pr-16 text-gray-700 appearance-none focus:outline-none" />
|
||||||
<a onclick="var input = document.getElementById('public-link'); input.focus(); input.select(); document.execCommand('copy');" href="javascript:void(0)" class="absolute right-0 text-indigo-700 font-bold p-2">
|
<a onclick="var input = document.getElementById('public-link'); input.focus(); input.select(); document.execCommand('copy');" href="javascript:void(0)" class="absolute right-0 text-indigo-700 font-bold p-2">
|
||||||
<svg class="feather-sm"><use xlink:href="#feather-copy" /></svg>
|
<svg class="feather-sm"><use xlink:href="#feather-copy" /></svg>
|
||||||
</a>
|
</a>
|
||||||
@ -112,7 +112,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p class="text-gray-700 mt-6">
|
<p class="text-gray-700 mt-6">
|
||||||
Select the Google Search Console property you would like to pull keyword data from. If you don't see your domain, <%= link("set it up and verify", to: "https://docs.plausible.io/google-search-console-integration#1-add-your-site-on-the-search-console", class: "text-indigo-500") %> on Search Console first.
|
Select the Google Search Console property you would like to pull keyword data from. If you don't see your domain, <%= link("set it up and verify", to: "https://docs.#{base_domain()}/google-search-console-integration#1-add-your-site-on-the-search-console", class: "text-indigo-500") %> on Search Console first.
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
@ -132,7 +132,7 @@
|
|||||||
<%= button("Continue with Google", to: Plausible.Google.Api.authorize_url(@site.id), class: "button mt-4") %>
|
<%= button("Continue with Google", to: Plausible.Google.Api.authorize_url(@site.id), class: "button mt-4") %>
|
||||||
|
|
||||||
<div class="text-gray-700 mt-8">
|
<div class="text-gray-700 mt-8">
|
||||||
NB: You also need to set up your site on <%= link("Google Search Console", to: "https://search.google.com/search-console/about") %> for the integration to work. <%= link("Read the docs", to: "https://docs.plausible.io/google-search-console-integration", class: "text-indigo-500") %>
|
NB: You also need to set up your site on <%= link("Google Search Console", to: "https://search.google.com/search-console/about") %> for the integration to work. <%= link("Read the docs", to: "https://docs.#{base_domain()}/google-search-console-integration", class: "text-indigo-500") %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,6 +11,18 @@ defmodule PlausibleWeb.AuthView do
|
|||||||
"free_10k" => "10k / free"
|
"free_10k" => "10k / free"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_domain do
|
||||||
|
PlausibleWeb.Endpoint.host()
|
||||||
|
end
|
||||||
|
|
||||||
|
def plausible_url do
|
||||||
|
PlausibleWeb.Endpoint.clean_url()
|
||||||
|
end
|
||||||
|
|
||||||
def subscription_name(subscription) do
|
def subscription_name(subscription) do
|
||||||
@subscription_names[subscription.paddle_plan_id]
|
@subscription_names[subscription.paddle_plan_id]
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
defmodule PlausibleWeb.BillingView do
|
defmodule PlausibleWeb.BillingView do
|
||||||
use PlausibleWeb, :view
|
use PlausibleWeb, :view
|
||||||
|
|
||||||
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_domain do
|
||||||
|
PlausibleWeb.Endpoint.host()
|
||||||
|
end
|
||||||
|
|
||||||
|
def plausible_url do
|
||||||
|
PlausibleWeb.Endpoint.clean_url()
|
||||||
|
end
|
||||||
|
|
||||||
def present_date(date) do
|
def present_date(date) do
|
||||||
Date.from_iso8601!(date)
|
Date.from_iso8601!(date)
|
||||||
|> Timex.format!("{D} {Mshort} {YYYY}")
|
|> Timex.format!("{D} {Mshort} {YYYY}")
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
defmodule PlausibleWeb.EmailView do
|
defmodule PlausibleWeb.EmailView do
|
||||||
use PlausibleWeb, :view
|
use PlausibleWeb, :view
|
||||||
|
|
||||||
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
def plausible_url do
|
||||||
|
PlausibleWeb.Endpoint.clean_url()
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_domain() do
|
||||||
|
PlausibleWeb.Endpoint.host()
|
||||||
|
end
|
||||||
|
|
||||||
def user_salutation(user) do
|
def user_salutation(user) do
|
||||||
if user.name do
|
if user.name do
|
||||||
String.split(user.name) |> List.first
|
String.split(user.name) |> List.first
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
defmodule PlausibleWeb.LayoutView do
|
defmodule PlausibleWeb.LayoutView do
|
||||||
use PlausibleWeb, :view
|
use PlausibleWeb, :view
|
||||||
|
|
||||||
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_domain do
|
||||||
|
PlausibleWeb.Endpoint.host()
|
||||||
|
end
|
||||||
|
|
||||||
|
def plausible_url do
|
||||||
|
PlausibleWeb.Endpoint.clean_url()
|
||||||
|
end
|
||||||
|
|
||||||
def home_dest(conn) do
|
def home_dest(conn) do
|
||||||
if conn.assigns[:current_user] do
|
if conn.assigns[:current_user] do
|
||||||
"/sites"
|
"/sites"
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
defmodule PlausibleWeb.PageView do
|
defmodule PlausibleWeb.PageView do
|
||||||
use PlausibleWeb, :view
|
use PlausibleWeb, :view
|
||||||
|
|
||||||
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_domain do
|
||||||
|
PlausibleWeb.Endpoint.host()
|
||||||
|
end
|
||||||
|
|
||||||
|
def plausible_url do
|
||||||
|
PlausibleWeb.Endpoint.clean_url()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,19 @@
|
|||||||
defmodule PlausibleWeb.SiteView do
|
defmodule PlausibleWeb.SiteView do
|
||||||
use PlausibleWeb, :view
|
use PlausibleWeb, :view
|
||||||
|
|
||||||
def goal_name(%Plausible.Goal{page_path: page_path}) when is_binary(page_path) do
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
def plausible_url do
|
||||||
|
PlausibleWeb.Endpoint.clean_url()
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_domain() do
|
||||||
|
PlausibleWeb.Endpoint.host()
|
||||||
|
end
|
||||||
|
|
||||||
|
def goal_name(%Plausible.Goal{page_path: page_path}) when is_binary(page_path) do
|
||||||
"Visit " <> page_path
|
"Visit " <> page_path
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -14,11 +26,12 @@ defmodule PlausibleWeb.SiteView do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def snippet(site) do
|
def snippet(site) do
|
||||||
tracker = if site.custom_domain do
|
tracker =
|
||||||
"https://" <> site.custom_domain.domain <> "/js/index.js"
|
if site.custom_domain do
|
||||||
else
|
"https://" <> site.custom_domain.domain <> "/js/index.js"
|
||||||
"https://plausible.io/js/plausible.js"
|
else
|
||||||
end
|
"#{plausible_url()}/js/plausible.js"
|
||||||
|
end
|
||||||
|
|
||||||
"""
|
"""
|
||||||
<script async defer data-domain="#{site.domain}" src="#{tracker}"></script>
|
<script async defer data-domain="#{site.domain}" src="#{tracker}"></script>
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
defmodule PlausibleWeb.StatsView do
|
defmodule PlausibleWeb.StatsView do
|
||||||
use PlausibleWeb, :view
|
use PlausibleWeb, :view
|
||||||
|
|
||||||
|
def admin_email do
|
||||||
|
Application.get_env(:plausible, :admin_email)
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_domain do
|
||||||
|
PlausibleWeb.Endpoint.host()
|
||||||
|
end
|
||||||
|
|
||||||
|
def plausible_url do
|
||||||
|
PlausibleWeb.Endpoint.clean_url()
|
||||||
|
end
|
||||||
|
|
||||||
def large_number_format(n) do
|
def large_number_format(n) do
|
||||||
cond do
|
cond do
|
||||||
n >= 1_000 && n < 1_000_000 ->
|
n >= 1_000 && n < 1_000_000 ->
|
||||||
|
37
mix.exs
37
mix.exs
@ -4,13 +4,23 @@ defmodule Plausible.MixProject do
|
|||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :plausible,
|
app: :plausible,
|
||||||
version: "0.1.0",
|
version: System.get_env("APP_VERSION", "0.0.1"),
|
||||||
elixir: "~> 1.5",
|
elixir: "~> 1.10",
|
||||||
elixirc_paths: elixirc_paths(Mix.env()), compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
elixirc_paths: elixirc_paths(Mix.env()),
|
||||||
|
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
||||||
start_permanent: Mix.env() == :prod,
|
start_permanent: Mix.env() == :prod,
|
||||||
aliases: aliases(),
|
aliases: aliases(),
|
||||||
deps: deps(),
|
deps: deps(),
|
||||||
test_coverage: [tool: ExCoveralls]
|
test_coverage: [
|
||||||
|
tool: ExCoveralls
|
||||||
|
],
|
||||||
|
releases: [
|
||||||
|
plausible: [
|
||||||
|
include_executables_for: [:unix],
|
||||||
|
applications: [plausible: :permanent],
|
||||||
|
steps: [:assemble, :tar]
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -20,7 +30,16 @@ defmodule Plausible.MixProject do
|
|||||||
def application do
|
def application do
|
||||||
[
|
[
|
||||||
mod: {Plausible.Application, []},
|
mod: {Plausible.Application, []},
|
||||||
extra_applications: [:logger, :sentry, :runtime_tools, :timex, :ua_inspector, :ref_inspector, :bamboo]
|
extra_applications: [
|
||||||
|
:logger,
|
||||||
|
:sentry,
|
||||||
|
:runtime_tools,
|
||||||
|
:timex,
|
||||||
|
:ua_inspector,
|
||||||
|
:ref_inspector,
|
||||||
|
:bamboo,
|
||||||
|
:bamboo_smtp
|
||||||
|
]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -33,7 +52,8 @@ defmodule Plausible.MixProject do
|
|||||||
# Type `mix help deps` for examples and options.
|
# Type `mix help deps` for examples and options.
|
||||||
defp deps do
|
defp deps do
|
||||||
[
|
[
|
||||||
{:browser, "~> 0.4.3"}, # remove
|
# remove
|
||||||
|
{:browser, "~> 0.4.3"},
|
||||||
{:bcrypt_elixir, "~> 2.0"},
|
{:bcrypt_elixir, "~> 2.0"},
|
||||||
{:cors_plug, "~> 1.5"},
|
{:cors_plug, "~> 1.5"},
|
||||||
{:ecto_sql, "~> 3.0"},
|
{:ecto_sql, "~> 3.0"},
|
||||||
@ -47,17 +67,20 @@ defmodule Plausible.MixProject do
|
|||||||
{:phoenix_pubsub, "~> 1.1"},
|
{:phoenix_pubsub, "~> 1.1"},
|
||||||
{:plug_cowboy, "~> 2.0"},
|
{:plug_cowboy, "~> 2.0"},
|
||||||
{:postgrex, ">= 0.0.0"},
|
{:postgrex, ">= 0.0.0"},
|
||||||
{:poison, "~> 3.1"}, # Used in paddle_api, can remove
|
# Used in paddle_api, can remove
|
||||||
|
{:poison, "~> 3.1"},
|
||||||
{:ref_inspector, "~> 1.3"},
|
{:ref_inspector, "~> 1.3"},
|
||||||
{:timex, "~> 3.6"},
|
{:timex, "~> 3.6"},
|
||||||
{:ua_inspector, "~> 0.18"},
|
{:ua_inspector, "~> 0.18"},
|
||||||
{:bamboo, "~> 1.3"},
|
{:bamboo, "~> 1.3"},
|
||||||
{:bamboo_postmark, "~> 0.5"},
|
{:bamboo_postmark, "~> 0.5"},
|
||||||
|
{:bamboo_smtp, "~> 2.1.0"},
|
||||||
{:sentry, "~> 7.0"},
|
{:sentry, "~> 7.0"},
|
||||||
{:httpoison, "~> 1.4"},
|
{:httpoison, "~> 1.4"},
|
||||||
{:ex_machina, "~> 2.3", only: :test},
|
{:ex_machina, "~> 2.3", only: :test},
|
||||||
{:excoveralls, "~> 0.10", only: :test},
|
{:excoveralls, "~> 0.10", only: :test},
|
||||||
{:double, "~> 0.7.0", only: :test},
|
{:double, "~> 0.7.0", only: :test},
|
||||||
|
{:junit_formatter, "~> 3.1", only: [:test]},
|
||||||
{:joken, "~> 2.0"},
|
{:joken, "~> 2.0"},
|
||||||
{:php_serializer, "~> 0.9.0"},
|
{:php_serializer, "~> 0.9.0"},
|
||||||
{:csv, "~> 2.3"},
|
{:csv, "~> 2.3"},
|
||||||
|
33
mix.lock
33
mix.lock
@ -1,11 +1,10 @@
|
|||||||
%{
|
%{
|
||||||
"bamboo": {:hex, :bamboo, "1.4.0", "7b9201c49a843e4802061cf45692405b2c00efcf1cebf8b7b64f015ead072392", [:mix], [{:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "b9cad03bf38c7f37b6308876039355665b6ce09fefb46dc529cef4def912cffa"},
|
"bamboo": {:hex, :bamboo, "1.5.0", "1926107d58adba6620450f254dfe8a3686637a291851fba125686fa8574842af", [:mix], [{:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d5f3d04d154e80176fd685e2531e73870d8700679f14d25a567e448abce6298d"},
|
||||||
"bamboo_postmark": {:hex, :bamboo_postmark, "0.6.0", "429ee3153497e2f1081f8741242450be13cdca52e2c56166e8eda5ebfcb23c0a", [:mix], [{:bamboo, ">= 1.2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:hackney, ">= 1.6.5", [hex: :hackney, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "badb3c7677440f641d920e0900ff0cd13c01d517e76562aa5c00e560f46f36ba"},
|
"bamboo_postmark": {:hex, :bamboo_postmark, "0.6.0", "429ee3153497e2f1081f8741242450be13cdca52e2c56166e8eda5ebfcb23c0a", [:mix], [{:bamboo, ">= 1.2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:hackney, ">= 1.6.5", [hex: :hackney, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "badb3c7677440f641d920e0900ff0cd13c01d517e76562aa5c00e560f46f36ba"},
|
||||||
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm", "fab09b20e3f5db886725544cbcf875b8e73ec93363954eb8a1a9ed834aa8c1f9"},
|
"bamboo_smtp": {:hex, :bamboo_smtp, "2.1.0", "4be58f3c51d9f7875dc169ae58a1d2f08e5b718bf3895f70d130548c0598f422", [:mix], [{:bamboo, "~> 1.2", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 0.15.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "0aad00ef93d0e0c83a0e1ca6998fea070c8a720a990fbda13ce834136215ee49"},
|
||||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.2.0", "3df902b81ce7fa8867a2ae30d20a1da6877a2c056bfb116fd0bc8a5f0190cea4", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "762be3fcb779f08207531bc6612cca480a338e4b4357abb49f5ce00240a77d1e"},
|
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.2.0", "3df902b81ce7fa8867a2ae30d20a1da6877a2c056bfb116fd0bc8a5f0190cea4", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "762be3fcb779f08207531bc6612cca480a338e4b4357abb49f5ce00240a77d1e"},
|
||||||
"browser": {:hex, :browser, "0.4.4", "bd6436961a6b2299c6cb38d0e49761c1161d869cd0db46369cef2bf6b77c3665", [:mix], [{:plug, "~> 1.2", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "d476ca309d4a4b19742b870380390aabbcb323c1f6f8745e2da2dfd079b4f8d7"},
|
"browser": {:hex, :browser, "0.4.4", "bd6436961a6b2299c6cb38d0e49761c1161d869cd0db46369cef2bf6b77c3665", [:mix], [{:plug, "~> 1.2", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "d476ca309d4a4b19742b870380390aabbcb323c1f6f8745e2da2dfd079b4f8d7"},
|
||||||
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"},
|
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "805abd97539caf89ec6d4732c91e62ba9da0cda51ac462380bbd28ee697a8c42"},
|
||||||
"clickhouse_ecto": {:git, "git@github.com:appodeal/clickhouse_ecto.git", "c4fa1c3d2b73e4be698e205ad6e9ace22ac23f7d", []},
|
|
||||||
"clickhousex": {:git, "https://github.com/atlas-forks/clickhousex.git", "e010c4eaa6cb6b659e44790a3bea2ec7703ceb31", []},
|
"clickhousex": {:git, "https://github.com/atlas-forks/clickhousex.git", "e010c4eaa6cb6b659e44790a3bea2ec7703ceb31", []},
|
||||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||||
"comeonin": {:hex, :comeonin, "5.3.1", "7fe612b739c78c9c1a75186ef2d322ce4d25032d119823269d0aa1e2f1e20025", [:mix], [], "hexpm", "d6222483060c17f0977fad1b7401ef0c5863c985a64352755f366aee3799c245"},
|
"comeonin": {:hex, :comeonin, "5.3.1", "7fe612b739c78c9c1a75186ef2d322ce4d25032d119823269d0aa1e2f1e20025", [:mix], [], "hexpm", "d6222483060c17f0977fad1b7401ef0c5863c985a64352755f366aee3799c245"},
|
||||||
@ -17,50 +16,50 @@
|
|||||||
"db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"},
|
"db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"},
|
||||||
"decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"},
|
"decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"},
|
||||||
"double": {:hex, :double, "0.7.0", "a7ee4c3488a0acc6d2ad9b69b6c7d3ddf3da2b54488d0f7c2d6ceb3a995887ca", [:mix], [], "hexpm", "f0c387a2266b4452da7bab03598feec11aef8b2acab061ea947dae81bb257329"},
|
"double": {:hex, :double, "0.7.0", "a7ee4c3488a0acc6d2ad9b69b6c7d3ddf3da2b54488d0f7c2d6ceb3a995887ca", [:mix], [], "hexpm", "f0c387a2266b4452da7bab03598feec11aef8b2acab061ea947dae81bb257329"},
|
||||||
"ecto": {:hex, :ecto, "3.4.2", "6890af71025769bd27ef62b1ed1925cfe23f7f0460bcb3041da4b705215ff23e", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3959b8a83e086202a4bd86b4b5e6e71f9f1840813de14a57d502d3fc2ef7132"},
|
"ecto": {:hex, :ecto, "3.4.4", "a2c881e80dc756d648197ae0d936216c0308370332c5e77a2325a10293eef845", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4bd3ad62abc3b21fb629f0f7a3dab23a192fca837d257dd08449fba7373561"},
|
||||||
"ecto_sql": {:hex, :ecto_sql, "3.4.2", "3d842665a81ba2137b62aa70151afe81dae44824cd09b2076a255937ab4e2dc9", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f2b064102467e1525314a464b6fea0707ff28ee132a15006727ccf51b73492ff"},
|
"ecto_sql": {:hex, :ecto_sql, "3.4.4", "d28bac2d420f708993baed522054870086fd45016a9d09bb2cd521b9c48d32ea", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "edb49af715dd72f213b66adfd0f668a43c17ed510b5d9ac7528569b23af57fe8"},
|
||||||
"elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm", "d522695b93b7f0b4c0fcb2dfe73a6b905b1c301226a5a55cb42e5b14d509e050"},
|
"elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm", "d522695b93b7f0b4c0fcb2dfe73a6b905b1c301226a5a55cb42e5b14d509e050"},
|
||||||
"elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"},
|
"elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"},
|
||||||
"ex_machina": {:hex, :ex_machina, "2.4.0", "09a34c5d371bfb5f78399029194a8ff67aff340ebe8ba19040181af35315eabb", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "a20bc9ddc721b33ea913b93666c5d0bdca5cbad7a67540784ae277228832d72c"},
|
"ex_machina": {:hex, :ex_machina, "2.4.0", "09a34c5d371bfb5f78399029194a8ff67aff340ebe8ba19040181af35315eabb", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "a20bc9ddc721b33ea913b93666c5d0bdca5cbad7a67540784ae277228832d72c"},
|
||||||
"excoveralls": {:hex, :excoveralls, "0.12.3", "2142be7cb978a3ae78385487edda6d1aff0e482ffc6123877bb7270a8ffbcfe0", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "568a3e616c264283f5dea5b020783ae40eef3f7ee2163f7a67cbd7b35bcadada"},
|
"excoveralls": {:hex, :excoveralls, "0.12.3", "2142be7cb978a3ae78385487edda6d1aff0e482ffc6123877bb7270a8ffbcfe0", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "568a3e616c264283f5dea5b020783ae40eef3f7ee2163f7a67cbd7b35bcadada"},
|
||||||
"extwitter": {:hex, :extwitter, "0.11.0", "9472e19f1711bc60bc7efa594353164532475d7c47ea9f1bb66d4faa889b079e", [:mix], [{:oauther, "~> 1.1", [hex: :oauther, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
|
||||||
"file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"},
|
"file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"},
|
||||||
"gettext": {:hex, :gettext, "0.17.4", "f13088e1ec10ce01665cf25f5ff779e7df3f2dc71b37084976cf89d1aa124d5c", [:mix], [], "hexpm", "3c75b5ea8288e2ee7ea503ff9e30dfe4d07ad3c054576a6e60040e79a801e14d"},
|
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
|
||||||
|
"gettext": {:hex, :gettext, "0.18.0", "406d6b9e0e3278162c2ae1de0a60270452c553536772167e2d701f028116f870", [:mix], [], "hexpm", "c3f850be6367ebe1a08616c2158affe4a23231c70391050bf359d5f92f66a571"},
|
||||||
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "e0100f8ef7d1124222c11ad362c857d3df7cb5f4204054f9f0f4a728666591fc"},
|
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "e0100f8ef7d1124222c11ad362c857d3df7cb5f4204054f9f0f4a728666591fc"},
|
||||||
"httpoison": {:hex, :httpoison, "1.6.2", "ace7c8d3a361cebccbed19c283c349b3d26991eff73a1eaaa8abae2e3c8089b6", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "aa2c74bd271af34239a3948779612f87df2422c2fdcfdbcec28d9c105f0773fe"},
|
"httpoison": {:hex, :httpoison, "1.6.2", "ace7c8d3a361cebccbed19c283c349b3d26991eff73a1eaaa8abae2e3c8089b6", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "aa2c74bd271af34239a3948779612f87df2422c2fdcfdbcec28d9c105f0773fe"},
|
||||||
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
|
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
|
||||||
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"},
|
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"},
|
||||||
"joken": {:hex, :joken, "2.2.0", "2daa1b12be05184aff7b5ace1d43ca1f81345962285fff3f88db74927c954d3a", [:mix], [{:jose, "~> 1.9", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "b4f92e30388206f869dd25d1af628a1d99d7586e5cf0672f64d4df84c4d2f5e9"},
|
"joken": {:hex, :joken, "2.2.0", "2daa1b12be05184aff7b5ace1d43ca1f81345962285fff3f88db74927c954d3a", [:mix], [{:jose, "~> 1.9", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "b4f92e30388206f869dd25d1af628a1d99d7586e5cf0672f64d4df84c4d2f5e9"},
|
||||||
"jose": {:hex, :jose, "1.10.1", "16d8e460dae7203c6d1efa3f277e25b5af8b659febfc2f2eb4bacf87f128b80a", [:mix, :rebar3], [], "hexpm", "3c7ddc8a9394b92891db7c2771da94bf819834a1a4c92e30857b7d582e2f8257"},
|
"jose": {:hex, :jose, "1.10.1", "16d8e460dae7203c6d1efa3f277e25b5af8b659febfc2f2eb4bacf87f128b80a", [:mix, :rebar3], [], "hexpm", "3c7ddc8a9394b92891db7c2771da94bf819834a1a4c92e30857b7d582e2f8257"},
|
||||||
|
"junit_formatter": {:hex, :junit_formatter, "3.1.0", "3f69c61c5413750f9c45e367d77aabbeac9b395acf478d8e70b4ee9d1989c709", [:mix], [], "hexpm", "da52401a93f711fc4f77ffabdda68f9a16fcad5d96f5fce4ae606ab1d73b72f4"},
|
||||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||||
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"},
|
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"},
|
||||||
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
|
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
|
||||||
"myxql": {:hex, :myxql, "0.4.0", "d95582db9e4b4707eb3a6a7002b8869a5240247931775f82d811ad450ca06503", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:geo, "~> 3.3", [hex: :geo, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "27a7ebaf7822cf7c89ea796371e70b942c8ec5e2c4eedcb8cd8e043f014014ad"},
|
|
||||||
"nanoid": {:hex, :nanoid, "2.0.2", "f3f7b4bf103ab6667f22beb00b6315825ee3f30100dd2c93d534e5c02164e857", [:mix], [], "hexpm", "3095cb1fac7bbc78843a8ccd99f1af375d0da1d3ebaa8552e846b73438c0c44f"},
|
"nanoid": {:hex, :nanoid, "2.0.2", "f3f7b4bf103ab6667f22beb00b6315825ee3f30100dd2c93d534e5c02164e857", [:mix], [], "hexpm", "3095cb1fac7bbc78843a8ccd99f1af375d0da1d3ebaa8552e846b73438c0c44f"},
|
||||||
"oauther": {:hex, :oauther, "1.1.1", "7d8b16167bb587ecbcddd3f8792beb9ec3e7b65c1f8ebd86b8dd25318d535752", [:mix], [], "hexpm", "9374f4302045321874cccdc57eb975893643bd69c3b22bf1312dab5f06e5788e"},
|
"oauther": {:hex, :oauther, "1.1.1", "7d8b16167bb587ecbcddd3f8792beb9ec3e7b65c1f8ebd86b8dd25318d535752", [:mix], [], "hexpm", "9374f4302045321874cccdc57eb975893643bd69c3b22bf1312dab5f06e5788e"},
|
||||||
"parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm", "639b2e8749e11b87b9eb42f2ad325d161c170b39b288ac8d04c4f31f8f0823eb"},
|
"parallel_stream": {:hex, :parallel_stream, "1.0.6", "b967be2b23f0f6787fab7ed681b4c45a215a81481fb62b01a5b750fa8f30f76c", [:mix], [], "hexpm", "639b2e8749e11b87b9eb42f2ad325d161c170b39b288ac8d04c4f31f8f0823eb"},
|
||||||
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
|
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
|
||||||
"phoenix": {:hex, :phoenix, "1.4.16", "2cbbe0c81e6601567c44cc380c33aa42a1372ac1426e3de3d93ac448a7ec4308", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "856cc1a032fa53822737413cf51aa60e750525d7ece7d1c0576d90d7c0f05c24"},
|
"phoenix": {:hex, :phoenix, "1.4.17", "1b1bd4cff7cfc87c94deaa7d60dd8c22e04368ab95499483c50640ef3bd838d8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a8e5d7a3d76d452bb5fb86e8b7bd115f737e4f8efe202a463d4aeb4a5809611"},
|
||||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"},
|
"phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"},
|
||||||
"phoenix_html": {:hex, :phoenix_html, "2.14.1", "7dabafadedb552db142aacbd1f11de1c0bbaa247f90c449ca549d5e30bbc66b4", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "536d5200ad37fecfe55b3241d90b7a8c3a2ca60cd012fc065f776324fa9ab0a9"},
|
"phoenix_html": {:hex, :phoenix_html, "2.14.2", "b8a3899a72050f3f48a36430da507dd99caf0ac2d06c77529b1646964f3d563e", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "58061c8dfd25da5df1ea0ca47c972f161beb6c875cd293917045b92ffe1bf617"},
|
||||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.1", "274a4b07c4adbdd7785d45a8b0bb57634d0b4f45b18d2c508b26c0344bd59b8f", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "41b4103a2fa282cfd747d377233baf213c648fdcc7928f432937676532490eee"},
|
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.2", "38d94c30df5e2ef11000697a4fbe2b38d0fbf79239d492ff1be87bbc33bc3a84", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "a3dec3d28ddb5476c96a7c8a38ea8437923408bc88da43e5c45d97037b396280"},
|
||||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm", "1f13f9f0f3e769a667a6b6828d29dec37497a082d195cc52dbef401a9b69bf38"},
|
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm", "1f13f9f0f3e769a667a6b6828d29dec37497a082d195cc52dbef401a9b69bf38"},
|
||||||
"php_serializer": {:hex, :php_serializer, "0.9.2", "59c5fd6bd3096671fd89358fb8229341ac7423b50ad8d45a15213b02ea2edab2", [:mix], [], "hexpm", "34eb835a460944f7fc216773b363c02e7dcf8ac0390c9e9ccdbd92b31a7ca59a"},
|
"php_serializer": {:hex, :php_serializer, "0.9.2", "59c5fd6bd3096671fd89358fb8229341ac7423b50ad8d45a15213b02ea2edab2", [:mix], [], "hexpm", "34eb835a460944f7fc216773b363c02e7dcf8ac0390c9e9ccdbd92b31a7ca59a"},
|
||||||
"plug": {:hex, :plug, "1.10.0", "6508295cbeb4c654860845fb95260737e4a8838d34d115ad76cd487584e2fc4d", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "422a9727e667be1bf5ab1de03be6fa0ad67b775b2d84ed908f3264415ef29d4a"},
|
"plug": {:hex, :plug, "1.10.1", "c56a6d9da7042d581159bcbaef873ba9d87f15dce85420b0d287bca19f40f9bd", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "b5cd52259817eb8a31f2454912ba1cff4990bca7811918878091cb2ab9e52cb8"},
|
||||||
"plug_cowboy": {:hex, :plug_cowboy, "2.1.2", "8b0addb5908c5238fac38e442e81b6fcd32788eaa03246b4d55d147c47c5805e", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "7d722581ce865a237e14da6d946f92704101740a256bd13ec91e63c0b122fc70"},
|
"plug_cowboy": {:hex, :plug_cowboy, "2.2.1", "fcf58aa33227a4322a050e4783ee99c63c031a2e7f9a2eb7340d55505e17f30f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3b43de24460d87c0971887286e7a20d40462e48eb7235954681a20cee25ddeb6"},
|
||||||
"plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"},
|
"plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"},
|
||||||
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},
|
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},
|
||||||
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
|
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
|
||||||
"postgrex": {:hex, :postgrex, "0.15.3", "5806baa8a19a68c4d07c7a624ccdb9b57e89cbc573f1b98099e3741214746ae4", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "4737ce62a31747b4c63c12b20c62307e51bb4fcd730ca0c32c280991e0606c90"},
|
"postgrex": {:hex, :postgrex, "0.15.4", "5d691c25fc79070705a2ff0e35ce0822b86a0ee3c6fdb7a4fb354623955e1aed", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "306515b9d975fcb2478dc337a1d27dc3bf8af7cd71017c333fe9db3a3d211b0a"},
|
||||||
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
|
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
|
||||||
"ref_inspector": {:hex, :ref_inspector, "1.3.0", "a02b89647440d084f2867ecece7a99895bcd4683482397fe086508bb22a165f3", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "d2069ae6b371112ac696a3cd116fd1e08d5726249b8d1357f377e67f0716cc10"},
|
"ref_inspector": {:hex, :ref_inspector, "1.3.1", "bb0489a4c4299dcd633f2b7a60c41a01f5590789d0b28225a60be484e1fbe777", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "3172eb1b08e5c69966f796e3fe0e691257546fa143a5eb0ecc18a6e39b233854"},
|
||||||
"sentry": {:hex, :sentry, "7.2.4", "b5bc90b594d40c2e653581e797a5fd2fdf994f2568f6bd66b7fa4971598be8d5", [:mix], [{:hackney, "~> 1.8 or 1.6.5", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "4ee4d368b5013076afcc8b73ed028bdc8ee9db84ea987e3591101e194c1fc24b"},
|
"sentry": {:hex, :sentry, "7.2.4", "b5bc90b594d40c2e653581e797a5fd2fdf994f2568f6bd66b7fa4971598be8d5", [:mix], [{:hackney, "~> 1.8 or 1.6.5", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "4ee4d368b5013076afcc8b73ed028bdc8ee9db84ea987e3591101e194c1fc24b"},
|
||||||
"siphash": {:hex, :siphash, "3.2.0", "ec03fd4066259218c85e2a4b8eec4bb9663bc02b127ea8a0836db376ba73f2ed", [:make, :mix], [], "hexpm", "ba3810701c6e95637a745e186e8a4899087c3b079ba88fb8f33df054c3b0b7c3"},
|
"siphash": {:hex, :siphash, "3.2.0", "ec03fd4066259218c85e2a4b8eec4bb9663bc02b127ea8a0836db376ba73f2ed", [:make, :mix], [], "hexpm", "ba3810701c6e95637a745e186e8a4899087c3b079ba88fb8f33df054c3b0b7c3"},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"},
|
||||||
"telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"},
|
"telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"},
|
||||||
"timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "f354efb2400dd7a80fd9eb6c8419068c4f632da4ac47f3d8822d6e33f08bc852"},
|
"timex": {:hex, :timex, "3.6.2", "845cdeb6119e2fef10751c0b247b6c59d86d78554c83f78db612e3290f819bc2", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "26030b46199d02a590be61c2394b37ea25a3664c02fafbeca0b24c972025d47a"},
|
||||||
"tzdata": {:hex, :tzdata, "1.0.3", "73470ad29dde46e350c60a66e6b360d3b99d2d18b74c4c349dbebbc27a09a3eb", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a6e1ee7003c4d04ecbd21dd3ec690d4c6662db5d3bbdd7262d53cdf5e7c746c1"},
|
"tzdata": {:hex, :tzdata, "1.0.3", "73470ad29dde46e350c60a66e6b360d3b99d2d18b74c4c349dbebbc27a09a3eb", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a6e1ee7003c4d04ecbd21dd3ec690d4c6662db5d3bbdd7262d53cdf5e7c746c1"},
|
||||||
"ua_inspector": {:hex, :ua_inspector, "0.20.0", "01939baf5706f7d6c2dc0affbbd7f5e14309ba43ebf8967aa6479ee2204f23bc", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.0", [hex: :poolboy, repo: "hexpm", optional: false]}, {:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "30e8623b9f55e7d58be12fc2afd50be8792ec14192c289701d3cc93ad6027f26"},
|
"ua_inspector": {:hex, :ua_inspector, "0.20.0", "01939baf5706f7d6c2dc0affbbd7f5e14309ba43ebf8967aa6479ee2204f23bc", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.0", [hex: :poolboy, repo: "hexpm", optional: false]}, {:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "30e8623b9f55e7d58be12fc2afd50be8792ec14192c289701d3cc93ad6027f26"},
|
||||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"},
|
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm", "1d1848c40487cdb0b30e8ed975e34e025860c02e419cb615d255849f3427439d"},
|
||||||
"yamerl": {:hex, :yamerl, "0.7.0", "e51dba652dce74c20a88294130b48051ebbbb0be7d76f22de064f0f3ccf0aaf5", [:rebar3], [], "hexpm", "cb5a4481e2e2ad36db83bd9962153e1a9208e2b2484185e33fc2caac6a50b108"},
|
"yamerl": {:hex, :yamerl, "0.8.0", "8214cfe16bbabe5d1d6c14a14aea11c784b9a21903dd6a7c74f8ce180adae5c7", [:rebar3], [], "hexpm", "010634477bf9c208a0767dcca89116c2442cf0b5e87f9c870f85cd1c3e0c2aab"},
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
defmodule Plausible.Repo.Migrations.AddPublicSites do
|
defmodule Plausible.Repo.Migrations.AddPublicSites do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
@host Application.get_env(:plausible, :url, :host)
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
alter table(:sites) do
|
alter table(:sites) do
|
||||||
add :public, :boolean, null: false, default: false
|
add :public, :boolean, null: false, default: false
|
||||||
end
|
end
|
||||||
|
|
||||||
execute "update sites set public=true where domain='plausible.io'"
|
execute "update sites set public=true where domain='#{@host}'"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
6
rel/env.bat.eex
Normal file
6
rel/env.bat.eex
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
@echo off
|
||||||
|
rem Set the release to work across nodes. If using the long name format like
|
||||||
|
rem the one below (my_app@127.0.0.1), you need to also uncomment the
|
||||||
|
rem RELEASE_DISTRIBUTION variable below. Must be "sname", "name" or "none".
|
||||||
|
rem set RELEASE_DISTRIBUTION=name
|
||||||
|
rem set RELEASE_NODE=<%= @release.name %>@127.0.0.1
|
18
rel/env.sh.eex
Normal file
18
rel/env.sh.eex
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Sets and enables heart (recommended only in daemon mode)
|
||||||
|
# case $RELEASE_COMMAND in
|
||||||
|
# daemon*)
|
||||||
|
# HEART_COMMAND="$RELEASE_ROOT/bin/$RELEASE_NAME $RELEASE_COMMAND"
|
||||||
|
# export HEART_COMMAND
|
||||||
|
# export ELIXIR_ERL_OPTIONS="-heart"
|
||||||
|
# ;;
|
||||||
|
# *)
|
||||||
|
# ;;
|
||||||
|
# esac
|
||||||
|
|
||||||
|
# Set the release to work across nodes. If using the long name format like
|
||||||
|
# the one below (my_app@127.0.0.1), you need to also uncomment the
|
||||||
|
# RELEASE_DISTRIBUTION variable below. Must be "sname", "name" or "none".
|
||||||
|
# export RELEASE_DISTRIBUTION=name
|
||||||
|
# export RELEASE_NODE=<%= @release.name %>@127.0.0.1
|
7
rel/overlays/createdb.sh
Executable file
7
rel/overlays/createdb.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Creates the database if needed
|
||||||
|
|
||||||
|
|
||||||
|
BIN_DIR=`dirname "$0"`
|
||||||
|
|
||||||
|
${BIN_DIR}/bin/plausible eval Plausible.Release.createdb
|
6
rel/overlays/migrate.sh
Executable file
6
rel/overlays/migrate.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# starts the db migration
|
||||||
|
|
||||||
|
BIN_DIR=`dirname "$0"`
|
||||||
|
|
||||||
|
${BIN_DIR}/bin/plausible eval Plausible.Release.migrate
|
5
rel/overlays/rollback.sh
Executable file
5
rel/overlays/rollback.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
BIN_DIR=`dirname "$0"`
|
||||||
|
|
||||||
|
${BIN_DIR}/bin/plausible eval Plausible.Release.rollback
|
5
rel/overlays/seed.sh
Executable file
5
rel/overlays/seed.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
BIN_DIR=`dirname "$0"`
|
||||||
|
|
||||||
|
${BIN_DIR}/bin/plausible eval Plausible.Release.seed
|
11
rel/vm.args.eex
Normal file
11
rel/vm.args.eex
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
## Customize flags given to the VM: http://erlang.org/doc/man/erl.html
|
||||||
|
## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here
|
||||||
|
|
||||||
|
## Number of dirty schedulers doing IO work (file, sockets, and others)
|
||||||
|
##+SDio 5
|
||||||
|
|
||||||
|
## Increase number of concurrent ports/sockets
|
||||||
|
##+Q 65536
|
||||||
|
|
||||||
|
## Tweak GC to run more often
|
||||||
|
##-env ERL_FULLSWEEP_AFTER 10
|
@ -1,4 +1,5 @@
|
|||||||
{:ok, _} = Application.ensure_all_started(:ex_machina)
|
{:ok, _} = Application.ensure_all_started(:ex_machina)
|
||||||
|
ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter])
|
||||||
Plausible.Test.ClickhouseSetup.run()
|
Plausible.Test.ClickhouseSetup.run()
|
||||||
ExUnit.start()
|
ExUnit.start()
|
||||||
Application.ensure_all_started(:double)
|
Application.ensure_all_started(:double)
|
||||||
|
Loading…
Reference in New Issue
Block a user