Merge pull request #5 from nathanielksmith/master
welcome emails and other user improvementspull/16/head
commit
9f9d84c548
3
setup.py
3
setup.py
|
@ -17,6 +17,7 @@ setup(
|
||||||
packages=['ttadmin'],
|
packages=['ttadmin'],
|
||||||
install_requires = ['Django==1.10.2',
|
install_requires = ['Django==1.10.2',
|
||||||
'sshpubkeys==2.2.0',
|
'sshpubkeys==2.2.0',
|
||||||
'psycopg2==2.6.2',],
|
'psycopg2==2.6.2',
|
||||||
|
'requests==2.12.5'],
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
FROM='root@tilde.town'
|
||||||
|
|
||||||
|
def send_email(to, body, subject='a message from tilde.town', frum=FROM,):
|
||||||
|
"""Sends an email using mailgun. Logs on failure."""
|
||||||
|
response = requests.post(
|
||||||
|
settings.MAILGUN_URL,
|
||||||
|
auth=('api', settings.MAILGUN_KEY),
|
||||||
|
data={
|
||||||
|
'from': frum,
|
||||||
|
'to': to,
|
||||||
|
'subject': subject,
|
||||||
|
'text': body
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
success = response.status_code == 200
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
logger.error('{}: failed to send email "{}" to {}'.format(
|
||||||
|
response.status_code,
|
||||||
|
subject,
|
||||||
|
to))
|
||||||
|
|
||||||
|
return success
|
|
@ -6,6 +6,7 @@ To run this For Real, you'll want to:
|
||||||
* set a different SECRET_KEY
|
* set a different SECRET_KEY
|
||||||
* change the password for the database or delete the password and use ident
|
* change the password for the database or delete the password and use ident
|
||||||
* change DEBUG to False
|
* change DEBUG to False
|
||||||
|
* set mailgun api info
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -99,3 +100,6 @@ STATIC_URL = '/static/'
|
||||||
|
|
||||||
# Not used during local development, but used in staging+live environments
|
# Not used during local development, but used in staging+live environments
|
||||||
STATIC_ROOT = 'static'
|
STATIC_ROOT = 'static'
|
||||||
|
|
||||||
|
MAILGUN_URL = "OVERWRITE THIS"
|
||||||
|
MAILGUN_KEY = "OVERWRITE THIS"
|
||||||
|
|
|
@ -9,9 +9,20 @@ admin.site.unregister(Group)
|
||||||
|
|
||||||
class PubkeyInline(admin.TabularInline):
|
class PubkeyInline(admin.TabularInline):
|
||||||
model = Pubkey
|
model = Pubkey
|
||||||
|
extra = 1
|
||||||
|
|
||||||
|
def bulk_review(madmin, req, qs):
|
||||||
|
for townie in qs:
|
||||||
|
townie.reviewed = True
|
||||||
|
townie.save()
|
||||||
|
|
||||||
|
bulk_review.short_description = 'mark selected townies as reviewed'
|
||||||
|
|
||||||
@admin.register(Townie)
|
@admin.register(Townie)
|
||||||
class TownieAdmin(admin.ModelAdmin):
|
class TownieAdmin(admin.ModelAdmin):
|
||||||
inlines = [PubkeyInline]
|
inlines = [PubkeyInline]
|
||||||
list_display = ('reviewed', 'username', 'email')
|
list_display = ('username', 'reviewed', 'email')
|
||||||
ordering = ('reviewed',)
|
ordering = ('reviewed',)
|
||||||
|
exclude = ('first_name', 'last_name', 'password', 'groups', 'user_permissions', 'last_login')
|
||||||
|
actions = (bulk_review,)
|
||||||
|
search_fields = ('username', 'email', 'displayname')
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from django.db.models import Model
|
from django.db.models import Model
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import pre_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db.models import TextField, BooleanField, CharField, ForeignKey
|
from django.db.models import TextField, BooleanField, CharField, ForeignKey
|
||||||
|
from django.template.loader import get_template
|
||||||
|
|
||||||
|
from common.mailing import send_email
|
||||||
|
from help.models import Ticket
|
||||||
|
|
||||||
SSH_TYPE_CHOICES = (
|
SSH_TYPE_CHOICES = (
|
||||||
('ssh-rsa', 'ssh-rsa',),
|
('ssh-rsa', 'ssh-rsa',),
|
||||||
|
@ -24,14 +27,22 @@ class Townie(User):
|
||||||
reasons = TextField(blank=True, null=False, default='')
|
reasons = TextField(blank=True, null=False, default='')
|
||||||
displayname = CharField(max_length=100, blank=False, null=False)
|
displayname = CharField(max_length=100, blank=False, null=False)
|
||||||
|
|
||||||
# TODO consider a generic ensure method that syncs this model with the
|
def send_welcome_email(self, admin_name='vilmibm'):
|
||||||
# system. there will likely be things besides shell that we want to keep
|
welcome_tmpl = get_template('users/welcome_email.txt')
|
||||||
# track of in the DB.
|
context = {
|
||||||
def ensure_shell(self):
|
'username': self.username,
|
||||||
"""Runs chsh for the user to set their shell to whatever self.shell
|
'admin_name': admin_name,
|
||||||
is."""
|
}
|
||||||
raise NotImplementedError()
|
text = welcome_tmpl.render(context)
|
||||||
|
from_address = '{}@tilde.town'.format(admin_name)
|
||||||
|
success = send_email(self.email, text, subject='tilde.town!', frum=from_address)
|
||||||
|
if not success:
|
||||||
|
Ticket.objects.create(name='system',
|
||||||
|
email='root@tilde.town',
|
||||||
|
issue_type='other',
|
||||||
|
issue_text='was not able to send welcome email to {} ({})'.format(
|
||||||
|
self.username,
|
||||||
|
self.email))
|
||||||
|
|
||||||
class Pubkey(Model):
|
class Pubkey(Model):
|
||||||
key_type = CharField(max_length=50,
|
key_type = CharField(max_length=50,
|
||||||
|
@ -43,11 +54,11 @@ class Pubkey(Model):
|
||||||
townie = ForeignKey(Townie)
|
townie = ForeignKey(Townie)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Townie)
|
@receiver(pre_save, sender=Townie)
|
||||||
def sync_system_state(sender, instance, created, **kwargs):
|
def on_townie_pre_save(sender, instance, **kwargs):
|
||||||
if created:
|
existing = Townie.objects.filter(username=instance.username)
|
||||||
print('TODO would create new user on system')
|
if not existing: # we're making a new user
|
||||||
else:
|
|
||||||
print('TODO would update existing user on system')
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not existing[0].reviewed and instance.reviewed == True:
|
||||||
|
instance.send_welcome_email()
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
Welcome to tilde.town, ~{{username}}!
|
||||||
|
|
||||||
|
Please take a moment to review our code of conduct: https://tilde.town/~wiki/conduct.html
|
||||||
|
|
||||||
|
and login with:
|
||||||
|
|
||||||
|
ssh -i /path/to/private/key {{username}}@tilde.town
|
||||||
|
|
||||||
|
File a help ticket if you have problems logging in (or other issues): https://cgi.tilde.town/help/tickets
|
||||||
|
|
||||||
|
See you on the server!!
|
||||||
|
|
||||||
|
~{{admin_name}}
|
Loading…
Reference in New Issue