diff --git a/circle/dashboard/forms.py b/circle/dashboard/forms.py index d1c3110..5260e3b 100644 --- a/circle/dashboard/forms.py +++ b/circle/dashboard/forms.py @@ -1286,6 +1286,35 @@ class UserCreationForm(OrgUserCreationForm): return user +class UserEditForm(forms.ModelForm): + instance_limit = forms.IntegerField( + label=_('Instance limit'), + min_value=0, widget=NumberInput) + + def __init__(self, *args, **kwargs): + super(UserEditForm, self).__init__(*args, **kwargs) + self.fields["instance_limit"].initial = ( + self.instance.profile.instance_limit) + + class Meta: + model = User + fields = ('email', 'first_name', 'last_name', 'instance_limit', + 'is_active') + + def save(self, commit=True): + user = super(UserEditForm, self).save() + user.profile.instance_limit = ( + self.cleaned_data['instance_limit'] or None) + user.profile.save() + return user + + @property + def helper(self): + helper = FormHelper() + helper.add_input(Submit("submit", _("Save"))) + return helper + + class AclUserOrGroupAddForm(forms.Form): name = forms.CharField(widget=autocomplete_light.TextWidget( 'AclUserGroupAutocomplete', diff --git a/circle/dashboard/templates/dashboard/profile.html b/circle/dashboard/templates/dashboard/profile.html index 5c2a07a..f581499 100644 --- a/circle/dashboard/templates/dashboard/profile.html +++ b/circle/dashboard/templates/dashboard/profile.html @@ -8,7 +8,7 @@ {% block content %} <div class="row"> - <div class="col-md-12"> + <div class="col-md-{% if perms.auth.change_user %}8{% else %}12{% endif %}"> <div class="panel panel-default"> <div class="panel-heading"> {% if request.user.is_superuser %} @@ -17,7 +17,7 @@ title="{% trans "Log in as this user. Recommended to open in an incognito window." %}"> {% trans "Login as this user" %}</a> {% endif %} - <a class="pull-right btn btn-default btn-xs" href="{% url "dashboard.index" %}">{% trans "Back" %}</a> + <a class="pull-right btn btn-default btn-xs" href="{% url "dashboard.views.user-list" %}">{% trans "Back" %}</a> <h3 class="no-margin"> <i class="fa fa-user"></i> {% include "dashboard/_display-name.html" with user=profile show_org=True %} @@ -109,6 +109,23 @@ </div> </div> </div> + + {% if perms.auth.change_user %} + <div class="col-md-4"> + <div class="panel panel-default"> + <div class="panel-heading"> + <h3 class="no-margin"> + <i class="fa fa-user"></i> + {% trans "Edit user" %} + </h3> + </div> + <div class="panel-body"> + {% crispy form %} + </div> + </div> + </div> + {% endif %} + </div> {% endblock %} diff --git a/circle/dashboard/views/user.py b/circle/dashboard/views/user.py index 9233f6a..f9daeed 100644 --- a/circle/dashboard/views/user.py +++ b/circle/dashboard/views/user.py @@ -37,7 +37,7 @@ from django.shortcuts import redirect, get_object_or_404 from django.utils.translation import ugettext as _ from django.views.decorators.http import require_POST from django.views.generic import ( - TemplateView, DetailView, View, UpdateView, CreateView, + TemplateView, View, UpdateView, CreateView, ) from django_sshkey.models import UserKey @@ -50,7 +50,7 @@ from vm.models import Instance, InstanceTemplate from ..forms import ( CircleAuthenticationForm, MyProfileForm, UserCreationForm, UnsubscribeForm, UserKeyForm, CirclePasswordChangeForm, ConnectCommandForm, - UserListSearchForm, + UserListSearchForm, UserEditForm, ) from ..models import Profile, GroupProfile, ConnectCommand from ..tables import ( @@ -294,11 +294,13 @@ class UserCreationView(LoginRequiredMixin, PermissionRequiredMixin, return val -class ProfileView(LoginRequiredMixin, DetailView): +class ProfileView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): template_name = "dashboard/profile.html" model = User slug_field = "username" slug_url_kwarg = "username" + form_class = UserEditForm + success_message = _("Successfully modified user.") def get(self, *args, **kwargs): user = self.request.user @@ -359,6 +361,15 @@ class ProfileView(LoginRequiredMixin, DetailView): user, self.request.user) return context + def post(self, request, *args, **kwargs): + if not request.user.has_perm('auth.change_user'): + raise PermissionDenied() + return super(ProfileView, self).post(self, request, *args, **kwargs) + + def get_success_url(self): + return reverse('dashboard.views.profile', + kwargs=self.kwargs) + @require_POST def toggle_use_gravatar(request, **kwargs):