Skip to content

Commit

Permalink
Feature/invite users (#14)
Browse files Browse the repository at this point in the history
* * Merge in the start of the invite users code.

* * Add the invite user section to documents.

* * Add invite users to organizations page.
* Cleanup some templates.
* Remove the unneeded storages stuff.y

* * Add the email template to the project.
* Wire in the views to call the correct template.

* * Almost got the invite users stuff all wrapped up, still gotta figure out one bug.

* * See if this fixes running tests.

* * Add the email invites and the password reset views.
  • Loading branch information
bgroff committed Jun 27, 2018
1 parent e9acdf6 commit fb77f57
Show file tree
Hide file tree
Showing 53 changed files with 1,048 additions and 124 deletions.
1 change: 1 addition & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ compile:
test:
pre:
- rm -rf /home/ubuntu/kala-app/django_kala/build/lib/django_kala
- rm -rf /home/ubuntu/kala-app/django_kala/django_kala/static/debug_toolbar
override:
- tox

Expand Down
12 changes: 11 additions & 1 deletion django_kala/auth/forms/invite_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@


class InviteUserForm(forms.ModelForm):
user_type = forms.ChoiceField(choices=[['User', 'User'], ['Admin', 'Admin']])

class Meta:
model = get_user_model()
fields = ['email', 'organizations']
fields = ['email', 'organizations', 'first_name', 'last_name']

def __init__(self, *args, **kwargs):
super(InviteUserForm, self).__init__(*args, **kwargs)
self.fields['organizations'].widget.attrs['class'] = 'ui fluid dropdown'
self.fields['user_type'].widget.attrs['class'] = 'ui fluid dropdown'

def save(self, commit=True):
self.instance.is_active = False
return super(InviteUserForm, self).save(commit=commit)
38 changes: 35 additions & 3 deletions django_kala/auth/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
from django.conf import settings
from django.contrib.auth.models import UserManager, AbstractUser, Permission
from django.contrib.auth.tokens import default_token_generator
from django.core.mail import send_mail
from django.db import models
from django.shortcuts import render
from django.template import loader
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from django.utils.translation import ugettext_lazy as _
from django_localflavor_us.models import PhoneNumberField
from timezone_field import TimeZoneField
Expand All @@ -12,6 +19,13 @@
import datetime


# TODO: This does not work.
class KalaUserManager(UserManager):

def get_query_set(self):
return super(KalaUserManager, self).get_query_set().filter(is_active=True)


class User(AbstractUser):
email = models.EmailField(_('email address'), unique=True)

Expand All @@ -32,7 +46,7 @@ class User(AbstractUser):
removed = models.DateField(null=True)
avatar_url = models.URLField(max_length=1200)

objects = UserManager()
objects = KalaUserManager()

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
Expand Down Expand Up @@ -124,8 +138,26 @@ def get_users(self):
organizations = self.get_organizations().values_list('pk')
return User.objects.filter(organizations__in=organizations)

def send_invite(self):
pass
def send_invite(self, app, template, subject, object):
template_txt = '{0}/{1}.txt'.format(app, template)
if settings.USE_HTML_EMAIL:
template_html = loader.get_template('{0}/{1}.html'.format(app, template))
context = {
'object': object,
'user': self,
'uid': urlsafe_base64_encode(force_bytes(self.pk)).decode(),
'token': default_token_generator.make_token(self),
'application_url': settings.APPLICATION_URL,
'help_email': settings.HELP_EMAIL,
}
send_mail(
subject,
render_to_string(template_txt, context),
settings.FROM_EMAIL,
[self.email],
fail_silently=False,
html_message=render(None, template_html, context) if settings.USE_HTML_EMAIL else None
)

def add_perm(self, perm, uuid):
Permissions.add_perm(perm=perm, user=self, uuid=uuid)
Expand Down
12 changes: 12 additions & 0 deletions django_kala/auth/templates/invite_user.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,22 @@ <h2 class="active section">Invite User
<label>{{ form.email.label }}</label>
{{ form.email }}
</div>
<div class="field">
<label>{{ form.first_name.label }}</label>
{{ form.first_name }}
</div>
<div class="field">
<label>{{ form.last_name.label }}</label>
{{ form.last_name }}
</div>
<div class="field">
<label>{{ form.organizations.label }}</label>
{{ form.organizations }}
</div>
<div class="field">
<label>{{ form.user_type.label }}</label>
{{ form.user_type }}
</div>
<button id="submit-button" class="ui button primary" type="submit">Invite user</button>
</form>
</div>
Expand Down
9 changes: 9 additions & 0 deletions django_kala/auth/templates/kala/email/invite_document.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
You have been invited to collaborate! Please click the link below to activate your account with Kala.
{{ application_url }}{% url 'users:password_reset_confirm' uid token %}

-------
If you did not initiate this action, please contact the Kala admins at the email below.
Do NOT reply to this message as this email address does not accept incoming email.

Website: https://{{ application_url }}
Email: {{ help_email }}@{{ application_url }}
9 changes: 9 additions & 0 deletions django_kala/auth/templates/kala/email/invite_organization.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
You have been invited to collaborate! Please click the link below to activate your account with Kala.
{{ application_url }}{% url 'users:password_reset_confirm' uid token %}

-------
If you did not initiate this action, please contact the Kala admins at the email below.
Do NOT reply to this message as this email address does not accept incoming email.

Website: https://{{ application_url }}
Email: {{ help_email }}@{{ application_url }}
9 changes: 9 additions & 0 deletions django_kala/auth/templates/kala/email/invite_project.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
You have been invited to collaborate! Please click the link below to activate your account with Kala.
{{ application_url }}{% url 'users:password_reset_confirm' uid token %}

-------
If you did not initiate this action, please contact the Kala admins at the email below.
Do NOT reply to this message as this email address does not accept incoming email.

Website: https://{{ application_url }}
Email: {{ help_email }}@{{ application_url }}
9 changes: 9 additions & 0 deletions django_kala/auth/templates/kala/email/invite_user.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
You have been invited to collaborate! Please click the link below to activate your account with Kala.
{{ application_url }}{% url 'users:password_reset_confirm' uid token %}

-------
If you did not initiate this action, please contact the Kala admins at the email below.
Do NOT reply to this message as this email address does not accept incoming email.

Website: https://{{ application_url }}
Email: {{ help_email }}@{{ application_url }}
108 changes: 108 additions & 0 deletions django_kala/auth/templates/registration/password_reset_complete.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{% load i18n static %}
<!DOCTYPE html>
<html>
<head>
<!-- Standard Meta -->
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

<!-- Always Use Same -->
<link rel="stylesheet" type="text/css" href="{% static "css/ui/components/icon.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/ui/components/image.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/ui/components/transition.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/ui/components/checkbox.css" %}">
<link rel="icon" href="{% static 'images/kala_ico.png' %}" type="image/png"/>

<!--
These css files are pre-compiled
to test out gulp
use static.html, run gulp from semantic/, and modify theme.config or variables
!-->
<link rel="stylesheet" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/form.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/accordion.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/checkbox.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/reset.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/site.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/breadcrumb.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/button.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/card.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/container.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/divider.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/dimmer.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/dropdown.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/form.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/grid.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/header.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/input.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/label.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/list.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/menu.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/message.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/modal.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/popup.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/reveal.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/segment.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/table.css" %}">

<link rel="stylesheet" type="text/css" href="{% static "css/global.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/layouts/theme.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/layouts/home.css" %}">
<!-- Site Properties -->

<!-- JS Includes -->
<script src="{% static "javascript/library/jquery.min.js" %}"></script>
<script src="{% static "css/ui/semantic.min.js" %}"></script>
<script src="{% static "css/ui/components/form.js" %}"></script>
<script src="{% static "css/ui/components/modal.js" %}"></script>
<script src="{% static "css/ui/components/transition.js" %}"></script>

<style type="text/css">
body {
background-color: #DADADA;
}

body > .grid {
height: 100%;
}

.image {
margin-top: -100px;
}

.column {
max-width: 450px;
}
</style>

</head>
<body>

<div class="ui middle aligned center aligned grid">
<div class="column">
<img src="{% static 'images/Kala Logotype.svg' %}" style="flex-grow: 1">


{% block content_title %}<h1>{{ title }}</h1>{% endblock %}

{% block content %}

<p>{% trans "Your password has been set. You may go ahead and log in now." %}</p>

<p><a href="{{ login_url }}">{% trans 'Log in' %}</a></p>

{% endblock %}
</div>
</div>

</body>

</html>
124 changes: 124 additions & 0 deletions django_kala/auth/templates/registration/password_reset_confirm.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{% load i18n static %}
<!DOCTYPE html>
<html>
<head>
<!-- Standard Meta -->
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

<!-- Always Use Same -->
<link rel="stylesheet" type="text/css" href="{% static "css/ui/components/icon.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/ui/components/image.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/ui/components/transition.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/ui/components/checkbox.css" %}">
<link rel="icon" href="{% static 'images/kala_ico.png' %}" type="image/png"/>

<!--
These css files are pre-compiled
to test out gulp
use static.html, run gulp from semantic/, and modify theme.config or variables
!-->
<link rel="stylesheet" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/form.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/accordion.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/checkbox.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/reset.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/site.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/breadcrumb.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/button.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/card.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/container.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/divider.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/dimmer.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/dropdown.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/form.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/grid.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/header.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/input.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/label.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/list.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/menu.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/message.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/modal.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/popup.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/reveal.css" %}">
<link class="themable" rel="stylesheet" type="text/css"
href="{% static "css/ui/components/material/segment.css" %}">
<link class="themable" rel="stylesheet" type="text/css" href="{% static "css/ui/components/material/table.css" %}">

<link rel="stylesheet" type="text/css" href="{% static "css/global.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/layouts/theme.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/layouts/home.css" %}">
<!-- Site Properties -->

<!-- JS Includes -->
<script src="{% static "javascript/library/jquery.min.js" %}"></script>
<script src="{% static "css/ui/semantic.min.js" %}"></script>
<script src="{% static "css/ui/components/form.js" %}"></script>
<script src="{% static "css/ui/components/modal.js" %}"></script>
<script src="{% static "css/ui/components/transition.js" %}"></script>

<style type="text/css">
body {
background-color: #DADADA;
}

body > .grid {
height: 100%;
}

.image {
margin-top: -100px;
}

.column {
max-width: 450px;
}
</style>

</head>
<body>

<div class="ui middle aligned center aligned grid">
<div class="column">
<img src="{% static 'images/Kala Logotype.svg' %}" style="flex-grow: 1">


{% if validlink %}

<p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>

<form class="ui large form {% if form.non_field_errors %}error{% endif %}" method="post">{% csrf_token %}

<fieldset class="module aligned">
<div class="form-row field-password1">
{{ form.new_password1.errors }}
<label for="id_new_password1">{% trans 'New password:' %}</label>
{{ form.new_password1 }}
</div>
<div class="form-row field-password2">
{{ form.new_password2.errors }}
<label for="id_new_password2">{% trans 'Confirm password:' %}</label>
{{ form.new_password2 }}
</div>
<input class="ui button primary" type="submit" value="{% trans 'Change my password' %}">
</fieldset>
</form>
{% else %}

<p>{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}</p>

{% endif %}
</div>
</div>

</body>

</html>

0 comments on commit fb77f57

Please sign in to comment.