From e8ad3f98d6938c92227dacc15b9a7d820d7b29fa Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Sun, 19 Apr 2020 22:35:51 +0100 Subject: [PATCH] added option to send invite to an address The admin page now has the option to send an invite to an email address. Since there are now two email types (invites and pw resets), the new sections have been added to config.ini, and email_template and email_plaintext have been renamed to email_html and email_text respectively. --- README.md | 41 ++++-- data/config-default.ini | 34 +++-- data/email.html | 2 +- data/email.mjml | 2 +- data/invite-email.html | 239 ++++++++++++++++++++++++++++++++++ data/invite-email.mjml | 33 +++++ data/invite-email.txt | 8 ++ data/static/admin.js | 15 ++- data/templates/admin.html | 85 +++++++----- data/templates/form.html | 7 +- images/admin.png | Bin 43361 -> 51579 bytes images/create.png | Bin 63521 -> 63923 bytes images/jfa.gif | Bin 2216013 -> 1593226 bytes jellyfin_accounts/email.py | 166 +++++++++++++++++++++++ jellyfin_accounts/pw_reset.py | 150 ++------------------- jellyfin_accounts/web.py | 15 ++- jellyfin_accounts/web_api.py | 36 +++-- jf-accounts | 28 +++- setup.py | 5 +- 19 files changed, 644 insertions(+), 222 deletions(-) create mode 100644 data/invite-email.html create mode 100644 data/invite-email.mjml create mode 100644 data/invite-email.txt create mode 100644 jellyfin_accounts/email.py diff --git a/README.md b/README.md index c96ad21..6938d5e 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ optional arguments: For detailed descriptions of each setting, see [setup](https://github.com/hrfee/jellyfin-accounts/wiki/Setup). On first run, the default configuration is copied to `~/.jf-accounts/config.ini`. + ``` [jellyfin] ; It is reccommended to create a limited admin account for this program. @@ -98,7 +99,7 @@ device = jf-accounts device_id = jf-accounts-0.1 [ui] -; Set to 0.0.0.0 to run localhost +; Set 0.0.0.0 to run localhost host = 0.0.0.0 port = 8056 username = your username @@ -127,28 +128,42 @@ number = 1 special = 0 [email] -; Enable to store provided email addresses, monitor jellyfin directory for pw-resets, and send pin -enabled = true -; Directory to monitor for passwordReset*.json files. Usually the jellyfin config directory -watch_directory = /path/to/jellyfin +; Leave this whole section if you aren't using any email-related features. use_24h = true ; Date format follows datetime's strftime. date_format = %-d/%-m/%-y -; Path to custom email html. If blank, uses the internal template. -email_template = -; Path to alternate plaintext email. If blank, uses the internal template. -email_plaintext = ; Displayed at bottom of emails message = Need help? contact me. ; Mail methods: mailgun, smtp -method = mailgun -; Subject of emails -subject = Password Reset - Jellyfin +method = smtp ; Address to send from address = jellyfin@jellyf.in ; The name of the sender from = Jellyfin +[password_resets] +; Enable to store provided email addresses, monitor jellyfin directory for pw-resets, and send pin +enabled = true +; Directory to monitor for passwordReset*.json files. Usually the jellyfin config directory +watch_directory = /path/to/jellyfin +; Path to custom email html. If blank, uses the internal template. +email_html = +; Path to alternate plaintext email. If blank, uses the internal template. +email_text = +; Subject of emails +subject = Password Reset - Jellyfin + +[invite_emails] +; If enabled, allows one to send an invite directly to an email address. +enabled = true +; Path to custom email html. If blank, uses the internal template. +email_html = +; Path to alternate plaintext email. If blank, uses the internal template. +email_text = +subject = Invite - Jellyfin +; Base url for jf-accounts. This necessary because most will use a reverse proxy, so the program has no other way of knowing what URL to send. +url_base = http://accounts.jellyf.in:8056/invite + [mailgun] api_url = https://api.mailgun.net... @@ -167,7 +182,7 @@ password = smtp password ; Path to store valid invites. invites = -; Path to store email addresses in JSON +; Path to store emails addresses in JSON emails = ; Path to the user policy template. Can be acquired with get-template. user_template = diff --git a/data/config-default.ini b/data/config-default.ini index 47f0a53..c55319c 100644 --- a/data/config-default.ini +++ b/data/config-default.ini @@ -39,28 +39,42 @@ number = 1 special = 0 [email] -; Enable to store provided email addresses, monitor jellyfin directory for pw-resets, and send pin -enabled = true -; Directory to monitor for passwordReset*.json files. Usually the jellyfin config directory -watch_directory = /path/to/jellyfin +; Leave this whole section if you aren't using any email-related features. use_24h = true ; Date format follows datetime's strftime. date_format = %-d/%-m/%-y -; Path to custom email html. If blank, uses the internal template. -email_template = -; Path to alternate plaintext email. If blank, uses the internal template. -email_plaintext = ; Displayed at bottom of emails message = Need help? contact me. ; Mail methods: mailgun, smtp method = smtp -; Subject of emails -subject = Password Reset - Jellyfin ; Address to send from address = jellyfin@jellyf.in ; The name of the sender from = Jellyfin +[password_resets] +; Enable to store provided email addresses, monitor jellyfin directory for pw-resets, and send pin +enabled = true +; Directory to monitor for passwordReset*.json files. Usually the jellyfin config directory +watch_directory = /path/to/jellyfin +; Path to custom email html. If blank, uses the internal template. +email_html = +; Path to alternate plaintext email. If blank, uses the internal template. +email_text = +; Subject of emails +subject = Password Reset - Jellyfin + +[invite_emails] +; If enabled, allows one to send an invite directly to an email address. +enabled = true +; Path to custom email html. If blank, uses the internal template. +email_html = +; Path to alternate plaintext email. If blank, uses the internal template. +email_text = +subject = Invite - Jellyfin +; Base url for jf-accounts. This necessary because most will use a reverse proxy, so the program has no other way of knowing what URL to send. +url_base = http://accounts.jellyf.in:8056/invite + [mailgun] api_url = https://api.mailgun.net... diff --git a/data/email.html b/data/email.html index 4aa7822..992c36d 100644 --- a/data/email.html +++ b/data/email.html @@ -149,7 +149,7 @@
-
+

Hi {{ username }},

Someone has recently requested a password reset on Jellyfin.

If this was you, enter the below pin into the prompt.

diff --git a/data/email.mjml b/data/email.mjml index 2b17e48..ef78141 100644 --- a/data/email.mjml +++ b/data/email.mjml @@ -12,7 +12,7 @@ - +

Hi {{ username }},

Someone has recently requested a password reset on Jellyfin.

If this was you, enter the below pin into the prompt.

diff --git a/data/invite-email.html b/data/invite-email.html new file mode 100644 index 0000000..3a3281a --- /dev/null +++ b/data/invite-email.html @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + +
+
Jellyfin
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + + + + + + +
+
+

Hi,

+

You've been invited to Jellyfin.

+

To join, click the button below.

+

This invite will expire on {{ expiry_date }}, at {{ expiry_time }}, which is in {{ expires_in }}, so act quick.

+
+
+ + + + +
+ Setup your account +
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + + + +
+
{{ message }}
+
+
+ +
+
+ +
+ + + diff --git a/data/invite-email.mjml b/data/invite-email.mjml new file mode 100644 index 0000000..4564e21 --- /dev/null +++ b/data/invite-email.mjml @@ -0,0 +1,33 @@ + + + + + + + + + Jellyfin + + + + + + +

Hi,

+

You've been invited to Jellyfin.

+

To join, click the button below.

+

This invite will expire on {{ expiry_date }}, at {{ expiry_time }}, which is in {{ expires_in }}, so act quick.

+
+ Setup your account +
+
+ + + + {{ message }} + + + + +
+ diff --git a/data/invite-email.txt b/data/invite-email.txt new file mode 100644 index 0000000..601e4a6 --- /dev/null +++ b/data/invite-email.txt @@ -0,0 +1,8 @@ +Hi, +You've been invited to Jellyfin. +To join, follow the below link. +This invite will expire on {{ expiry_date }}, at {{ expiry_time }}, which is in {{ expires_in }}, so act quick. + +{{ invite_link }} + +{{ message }} diff --git a/data/static/admin.js b/data/static/admin.js index fc1470c..a05551f 100644 --- a/data/static/admin.js +++ b/data/static/admin.js @@ -2,7 +2,7 @@ function parseInvite(invite, empty = false) { if (empty === true) { return ["None", "", "1"] } else { - var i = ["", "", "0"]; + var i = ["", "", "0", invite['email']]; i[0] = invite['code']; if (invite['hours'] == 0) { i[1] = invite['minutes'] + 'm'; @@ -40,6 +40,13 @@ function addItem(invite) { codeCopy.onclick = function(){toClipboard(inviteCode)}; codeCopy.classList.add('fa', 'fa-clipboard'); listCode.appendChild(codeCopy); + console.log(invite[3]); + if (typeof(invite[3]) != 'undefined') { + var sentTo = document.createElement('span'); + sentTo.setAttribute('style', 'color: grey; margin-left: 2%; font-style: italic; font-size: 75%;'); + sentTo.appendChild(document.createTextNode('Sent to ' + invite[3])); + listCode.appendChild(sentTo); + }; var listDelete = document.createElement('button'); listDelete.onclick = function(){deleteInvite(invite[0])}; listDelete.classList.add('btn', 'btn-outline-danger'); @@ -153,7 +160,11 @@ function toClipboard(str) { } }; $("form#inviteForm").submit(function() { - var send = $("form#inviteForm").serializeJSON(); + var send_object = $("form#inviteForm").serializeObject(); + if (document.getElementById('send_to_address_enabled').checked) { + send_object['email'] = document.getElementById('send_to_address').value; + } + var send = JSON.stringify(send_object); $.ajax('/generateInvite', { data : send, contentType : 'application/json', diff --git a/data/templates/admin.html b/data/templates/admin.html index 5acfcd8..d81f89c 100644 --- a/data/templates/admin.html +++ b/data/templates/admin.html @@ -14,22 +14,30 @@