Config Generator and CSS/Doc Improvements (#151)

This commit is contained in:
Chris Caron 2023-11-18 14:55:19 -05:00 committed by GitHub
parent 843685cc55
commit 9ee3fd6ec9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 81 additions and 10 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@ __pycache__/
# Distribution / packaging / virtualenv # Distribution / packaging / virtualenv
.Python .Python
.bash_history
env/ env/
build/ build/
develop-eggs/ develop-eggs/

View File

@ -275,7 +275,7 @@ curl -X POST -d '{"tag":"leaders teamA, leaders teamB", "body":"meeting now"}' \
### API Notes ### API Notes
- `{KEY}` must be 1-128 alphanumeric characters in length. In addition to this, the underscore (`_`) and dash (`-`) are also accepted. - `{KEY}` must be 1-128 alphanumeric characters in length. In addition to this, the underscore (`_`) and dash (`-`) are also accepted.
- Consider using keys like `sha1`, `sha512`, `uuid`, etc to secure shared namespaces if you wish to open your platform to others. Or keep it simple in a controlled environment and just use the default string `apprise` as your key (and as illustrated in the examples above). - Consider using keys like `sha1`, `sha512`, `uuid`, etc to secure shared namespaces if you wish to open your platform to others. Or keep it simple in a controlled environment and just use the default string `apprise` as your key (and as illustrated in the examples above). You can over-ride this default value by setting the `APPRISE_DEFAULT_CONFIG_ID`(see below).
- Specify the `Content-Type` of `application/json` to use the JSON support otherwise the default expected format is `application/x-www-form-urlencoded` (whether it is specified or not). - Specify the `Content-Type` of `application/json` to use the JSON support otherwise the default expected format is `application/x-www-form-urlencoded` (whether it is specified or not).
- There is no authentication (or SSL encryption) required to use this API; this is by design. The intention here is to be a light-weight and fast micro-service. - There is no authentication (or SSL encryption) required to use this API; this is by design. The intention here is to be a light-weight and fast micro-service.
- There are no additional dependencies (such as database requirements, etc) should you choose to use the optional persistent store (mounted as `/config`). - There are no additional dependencies (such as database requirements, etc) should you choose to use the optional persistent store (mounted as `/config`).
@ -287,6 +287,7 @@ The use of environment variables allow you to provide over-rides to default sett
| Variable | Description | | Variable | Description |
|--------------------- | ----------- | |--------------------- | ----------- |
| `APPRISE_DEFAULT_THEME` | Can be set to `light` or `dark`; it defaults to `light` if not otherwise provided. The theme can be toggled from within the website as well. | `APPRISE_DEFAULT_THEME` | Can be set to `light` or `dark`; it defaults to `light` if not otherwise provided. The theme can be toggled from within the website as well.
| `APPRISE_DEFAULT_CONFIG_ID` | Defaults to `apprise`. This is the presumed configuration ID you always default to when accessing the configuration manager via the website.
| `APPRISE_CONFIG_DIR` | Defines an (optional) persistent store location of all configuration files saved. By default:<br/> - Configuration is written to the `apprise_api/var/config` directory when just using the _Django_ `manage runserver` script. However for the path for the container is `/config`. | `APPRISE_CONFIG_DIR` | Defines an (optional) persistent store location of all configuration files saved. By default:<br/> - Configuration is written to the `apprise_api/var/config` directory when just using the _Django_ `manage runserver` script. However for the path for the container is `/config`.
| `APPRISE_ATTACH_DIR` | The directory the uploaded attachments are placed in. By default:<br/> - Attachments are written to the `apprise_api/var/attach` directory when just using the _Django_ `manage runserver` script. However for the path for the container is `/attach`. | `APPRISE_ATTACH_DIR` | The directory the uploaded attachments are placed in. By default:<br/> - Attachments are written to the `apprise_api/var/attach` directory when just using the _Django_ `manage runserver` script. However for the path for the container is `/attach`.
| `APPRISE_ATTACH_SIZE` | Over-ride the attachment size (defined in MB). By default it is set to `200` (Megabytes). You can set this up to a maximum value of `500` which is the restriction in place for NginX (internal hosting ervice) at this time. If you set this to zero (`0`) then attachments will not be passed along even if provided. | `APPRISE_ATTACH_SIZE` | Over-ride the attachment size (defined in MB). By default it is set to `200` (Megabytes). You can set this up to a maximum value of `500` which is the restriction in place for NginX (internal hosting ervice) at this time. If you set this to zero (`0`) then attachments will not be passed along even if provided.

View File

@ -22,6 +22,7 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. # THE SOFTWARE.
from .utils import gen_unique_config_id
from .utils import ConfigCache from .utils import ConfigCache
from django.conf import settings from django.conf import settings
import apprise import apprise
@ -46,3 +47,17 @@ def apprise_version(request):
Returns the current version of apprise loaded under the hood Returns the current version of apprise loaded under the hood
""" """
return {'APPRISE_VERSION': apprise.__version__} return {'APPRISE_VERSION': apprise.__version__}
def default_config_id(request):
"""
Returns a unique config identifier
"""
return {'DEFAULT_CONFIG_ID': settings.APPRISE_DEFAULT_CONFIG_ID}
def unique_config_id(request):
"""
Returns a unique config identifier
"""
return {'UNIQUE_CONFIG_ID': gen_unique_config_id()}

View File

@ -36,7 +36,7 @@
<h1>{% trans "Apprise API" %}</h1> <h1>{% trans "Apprise API" %}</h1>
<ul> <ul>
<li>APPRISE v{{APPRISE_VERSION}}</li> <li>APPRISE v{{APPRISE_VERSION}}</li>
<li class="theme"><a href="{{ request.path }}?theme={{request.next_theme}}"><span class="tiny material-icons">invert_colors</span></a></li> <li class="theme"><a href="{{ request.path }}?theme={{request.next_theme}}"><i class="material-icons">invert_colors</i></a></li>
</ul> </ul>
</div> </div>
</div> </div>
@ -46,8 +46,10 @@
<div class="col s3" style="width:20em"> <div class="col s3" style="width:20em">
{% if STATEFUL_MODE != 'disabled' %} {% if STATEFUL_MODE != 'disabled' %}
<ul class="collection z-depth-1"> <ul class="collection z-depth-1">
<a class="collection-item" href="{% url 'config' 'apprise' %}"><i class="material-icons">settings</i> <a class="collection-item" href="{% url 'config' DEFAULT_CONFIG_ID %}"><i class="material-icons">settings</i>
{% trans "Configuration Manager" %}</a> {% trans "Configuration Manager" %}</a>
<a class="collection-item" href="{% url 'config' UNIQUE_CONFIG_ID %}"><i class="material-icons">refresh</i>
{% trans "New Configuration" %}</a>
</ul> </ul>
{% endif %} {% endif %}
<ul class="collection z-depth-1"> <ul class="collection z-depth-1">

View File

@ -2,7 +2,7 @@
{% load i18n %} {% load i18n %}
{% block body %} {% block body %}
{% if STATEFUL_MODE != 'disabled' %} {% if STATEFUL_MODE != 'disabled' %}
<h4>{% trans "Management for:" %} <em>{{ key }}</em></h4> <h4>{% trans "Management for Config ID:" %} <em>{{ key }}</em></h4>
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<ul class="tabs config-overview"> <ul class="tabs config-overview">
@ -75,12 +75,11 @@
<div class="has-config"> <div class="has-config">
<div class="section"> <div class="section">
<h5>{% trans "Working Remotely With Your Configuration" %}</h5> <h5>{% trans "Working Remotely With Your Configuration" %}</h5>
<h6>{% trans "Using The Apprise CLI" %}</h6>
<p> <p>
{% blocktrans %}The following command would cause apprise to directly notify all of your services:{% endblocktrans %} {% blocktrans %}The following command would cause apprise to directly notify all of your services:{% endblocktrans %}
<br />
<pre><code class="bash">apprise --body="Test Message" \<br/> <pre><code class="bash">apprise --body="Test Message" \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;apprise{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/<em>{{key}}</em>/?tags=all</code></pre> &nbsp;&nbsp;&nbsp;&nbsp;apprise{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/<em>{{key}}</em>/?tags=all</code></pre>
<br />
{% blocktrans %}Send one or more attachments like this:{% endblocktrans %} {% blocktrans %}Send one or more attachments like this:{% endblocktrans %}
<pre><code class="bash">apprise --body="Test Message" \<br/> <pre><code class="bash">apprise --body="Test Message" \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;apprise{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/<em>{{key}}</em>/?tags=all \<br/> &nbsp;&nbsp;&nbsp;&nbsp;apprise{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/<em>{{key}}</em>/?tags=all \<br/>
@ -95,8 +94,28 @@
<br /> <br />
<pre><code class="bash">apprise --body="Test Message" --tag=all \<br/> <pre><code class="bash">apprise --body="Test Message" --tag=all \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;--config={{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/get/<em>{{key}}</em></code></pre> &nbsp;&nbsp;&nbsp;&nbsp;--config={{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/get/<em>{{key}}</em></code></pre>
{% blocktrans %}You may also create an <a href="https://github.com/caronc/apprise/wiki/config#cli" target="_blank">Apprise configuration file</a> that contains this line somewhere in it:{% endblocktrans %}
<pre><code class="bash">include {{request.scheme}}://{{request.META.HTTP_HOST}}{{BASE_URL}}/get/<em>{{key}}</em></code></pre>
{% blocktrans %}By leveraging the <em>include</em> directive, it will automatically be referenced for future calls to the <code>apprise</code> tool. All future calls using Apprise now simplify to:{% endblocktrans %}
<pre><code class="bash">apprise --body="Test Message" --tag=all</em></code></pre>
</p> </p>
{% endif %} {% endif %}
<h6>{% trans "Using CURL" %}</h6>
<p>
{% blocktrans %}The following command would cause the apprise api to notify all of your services:{% endblocktrans %}
<pre><code class="bash">curl&nbsp;-X&nbsp;POST \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;-F "body=Test Message" \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;-F "tags=all" \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;http{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/<em>{{key}}</em></code></pre>
{% blocktrans %}Send one or more attachments like this:{% endblocktrans %}
<pre><code class="bash">curl&nbsp;-X&nbsp;POST \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;-F "tags=all" \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;-F "body=Test Message" \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;-F attach1=@Screenshot-1.png \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;-F attach2=@/my/path/to/Apprise.doc \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;http{% if request.is_secure %}s{% endif %}://{{request.META.HTTP_HOST}}{{BASE_URL}}/notify/<em>{{key}}</em></code></pre>
</p>
</div> </div>
<div class="section"> <div class="section">
<h5>{% trans "Loaded Configuration" %}</h5> <h5>{% trans "Loaded Configuration" %}</h5>

View File

@ -35,6 +35,7 @@ import base64
import requests import requests
from json import dumps from json import dumps
from django.conf import settings from django.conf import settings
from datetime import datetime
# import the logging library # import the logging library
import logging import logging
@ -588,6 +589,17 @@ def apply_global_filters():
' ignoring.', name) ' ignoring.', name)
def gen_unique_config_id():
"""
Generates a unique configuration ID
"""
# our key to use
h = hashlib.sha256()
h.update(datetime.now().strftime('%Y%m%d%H%M%S%f').encode('utf-8'))
h.update(settings.SECRET_KEY.encode('utf-8'))
return h.hexdigest()
def send_webhook(payload): def send_webhook(payload):
""" """
POST our webhook results POST our webhook results

View File

@ -79,6 +79,8 @@ TEMPLATES = [
'context_processors': [ 'context_processors': [
'django.template.context_processors.request', 'django.template.context_processors.request',
'core.context_processors.base_url', 'core.context_processors.base_url',
'api.context_processors.default_config_id',
'api.context_processors.unique_config_id',
'api.context_processors.stateful_mode', 'api.context_processors.stateful_mode',
'api.context_processors.config_lock', 'api.context_processors.config_lock',
'api.context_processors.apprise_version', 'api.context_processors.apprise_version',
@ -120,6 +122,10 @@ WSGI_APPLICATION = 'core.wsgi.application'
# The default value is to be a single slash # The default value is to be a single slash
BASE_URL = os.environ.get('BASE_URL', '') BASE_URL = os.environ.get('BASE_URL', '')
# Define our default configuration ID to use
APPRISE_DEFAULT_CONFIG_ID = \
os.environ.get('APPRISE_DEFAULT_CONFIG_ID', 'apprise')
# Static files relative path (CSS, JavaScript, Images) # Static files relative path (CSS, JavaScript, Images)
STATIC_URL = BASE_URL + '/s/' STATIC_URL = BASE_URL + '/s/'

View File

@ -46,6 +46,15 @@ td, th {
margin-bottom: 0; margin-bottom: 0;
} }
h4 em {
font-size: 2.0rem;
display: inline-block;
margin: 0;
padding: 0;
word-break: break-all;
line-height: 1.0em;
}
em { em {
color: #004d40; color: #004d40;
font-weight:bold; font-weight:bold;
@ -164,3 +173,9 @@ ul.logs li.log_ERROR {
.url-disabled { .url-disabled {
color: #8B0000; color: #8B0000;
} }
h6 {
font-weight: bold;
}
#overview pre {
margin-left: 2.0rem
}

View File

@ -1 +1 @@
.nav.nav-color{background:#4c566a!important}.hljs{display:block;overflow-x:auto;padding:.5em;color:#d8dee9;background:#4c566a;transition:box-shadow .25s,-webkit-box-shadow .25s!important;border-radius:2px!important}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#bf616a}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#a3be8c}.hljs-bullet,.hljs-symbol{color:#b48ead}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.no-config .info{color: #4c566a}.tabs .tab a:hover, .tabs .tab a.active {color: #4c566a}.theme a {color: #d8dee9}.url-enabled{color: #02c7a6}.url-disabled{color:#e00202}.btn, .btn-large,.btn-small {background-color:#333}.btn-large:hover, .btn-small:hover, .btn:hover {background-color:#222}i.material-icons{color:#6e7d9c}i.material-icons:hover{color:#57637a}.nav h1{color:#d8dee9!important} .nav.nav-color{background:#4c566a!important}.hljs{display:block;overflow-x:auto;padding:.5em;color:#d8dee9;background:#4c566a;transition:box-shadow .25s,-webkit-box-shadow .25s!important;border-radius:2px!important}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#4fa1ba;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#7091aa}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#a3be8c}.hljs-bullet,.hljs-symbol{color:#b48ead}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.no-config .info{color: #4c566a}.tabs .tab a:hover, .tabs .tab a.active {color: #4c566a}.theme a {color: #d8dee9}.url-enabled{color: #02c7a6}.url-disabled{color:#e00202}.btn, .btn-large,.btn-small {background-color:#333}.btn-large:hover, .btn-small:hover, .btn:hover {background-color:#222}i.material-icons{color:#6e7d9c}i.material-icons:hover{color:#57637a}.nav h1{color:#d8dee9!important}

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/* GitHub highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org> */ /* GitHub highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org> */
.nav.nav-color{background:#8fbcbb!important}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}a {color: #333} .nav.nav-color{background:#8fbcbb!important}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}a i {color: #333}