mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-12 22:10:16 +02:00
Merge pull request #166 from Adarnof/passwords
Custom service passwords
This commit is contained in:
commit
f5bd9133fa
@ -95,6 +95,7 @@ urlpatterns = patterns('',
|
|||||||
url(r'^deactivate_forum/$', 'services.views.deactivate_forum', name='auth_deactivate_forum'),
|
url(r'^deactivate_forum/$', 'services.views.deactivate_forum', name='auth_deactivate_forum'),
|
||||||
url(r'^reset_forum_password/$', 'services.views.reset_forum_password',
|
url(r'^reset_forum_password/$', 'services.views.reset_forum_password',
|
||||||
name='auth_reset_forum_password'),
|
name='auth_reset_forum_password'),
|
||||||
|
url(r'^set_forum_password/$', 'services.views.set_forum_password', name='auth_set_forum_password'),
|
||||||
|
|
||||||
|
|
||||||
# Jabber Service Control
|
# Jabber Service Control
|
||||||
@ -102,12 +103,14 @@ urlpatterns = patterns('',
|
|||||||
url(r'^deactivate_jabber/$', 'services.views.deactivate_jabber', name='auth_deactivate_jabber'),
|
url(r'^deactivate_jabber/$', 'services.views.deactivate_jabber', name='auth_deactivate_jabber'),
|
||||||
url(r'^reset_jabber_password/$', 'services.views.reset_jabber_password',
|
url(r'^reset_jabber_password/$', 'services.views.reset_jabber_password',
|
||||||
name='auth_reset_jabber_password'),
|
name='auth_reset_jabber_password'),
|
||||||
|
url(r'^set_jabber_password/$', 'services.views.set_jabber_password', name='auth_set_jabber_password'),
|
||||||
|
|
||||||
# Mumble service control
|
# Mumble service control
|
||||||
url(r'^activate_mumble/$', 'services.views.activate_mumble', name='auth_activate_mumble'),
|
url(r'^activate_mumble/$', 'services.views.activate_mumble', name='auth_activate_mumble'),
|
||||||
url(r'^deactivate_mumble/$', 'services.views.deactivate_mumble', name='auth_deactivate_mumble'),
|
url(r'^deactivate_mumble/$', 'services.views.deactivate_mumble', name='auth_deactivate_mumble'),
|
||||||
url(r'^reset_mumble_password/$', 'services.views.reset_mumble_password',
|
url(r'^reset_mumble_password/$', 'services.views.reset_mumble_password',
|
||||||
name='auth_reset_mumble_password'),
|
name='auth_reset_mumble_password'),
|
||||||
|
url(r'^set_mumble_password/$', 'services.views.set_mumble_password', name='auth_set_mumble_password'),
|
||||||
|
|
||||||
# Ipboard service control
|
# Ipboard service control
|
||||||
url(r'^activate_ipboard/$', 'services.views.activate_ipboard_forum',
|
url(r'^activate_ipboard/$', 'services.views.activate_ipboard_forum',
|
||||||
@ -116,6 +119,7 @@ urlpatterns = patterns('',
|
|||||||
name='auth_deactivate_ipboard'),
|
name='auth_deactivate_ipboard'),
|
||||||
url(r'^reset_ipboard_password/$', 'services.views.reset_ipboard_password',
|
url(r'^reset_ipboard_password/$', 'services.views.reset_ipboard_password',
|
||||||
name='auth_reset_ipboard_password'),
|
name='auth_reset_ipboard_password'),
|
||||||
|
url(r'^set_ipboard_password/$', 'services.views.set_ipboard_password', name='auth_set_ipboard_password'),
|
||||||
|
|
||||||
# Teamspeak3 service control
|
# Teamspeak3 service control
|
||||||
url(r'^activate_teamspeak3/$', 'services.views.activate_teamspeak3',
|
url(r'^activate_teamspeak3/$', 'services.views.activate_teamspeak3',
|
||||||
|
@ -35,3 +35,11 @@ class FleetFormatterForm(forms.Form):
|
|||||||
class DiscordForm(forms.Form):
|
class DiscordForm(forms.Form):
|
||||||
email = forms.CharField(label="Email Address", required=True)
|
email = forms.CharField(label="Email Address", required=True)
|
||||||
password = forms.CharField(label="Password", required=True, widget=forms.PasswordInput)
|
password = forms.CharField(label="Password", required=True, widget=forms.PasswordInput)
|
||||||
|
|
||||||
|
class ServicePasswordForm(forms.Form):
|
||||||
|
password = forms.CharField(label="Password", required=True)
|
||||||
|
def clean_password(self):
|
||||||
|
password = self.cleaned_data['password']
|
||||||
|
if not len(password) >= 8:
|
||||||
|
raise forms.ValidationError("Password must be at least 8 characters long.")
|
||||||
|
return password
|
||||||
|
@ -137,8 +137,9 @@ class IPBoardManager:
|
|||||||
IPBoardManager.remove_user_from_group(username, g)
|
IPBoardManager.remove_user_from_group(username, g)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_user_password(username, email):
|
def update_user_password(username, email, plain_password=None):
|
||||||
logger.debug("Settings new IPBoard password for user %s" % username)
|
logger.debug("Settings new IPBoard password for user %s" % username)
|
||||||
|
if not plain_password:
|
||||||
plain_password = IPBoardManager.__generate_random_pass()
|
plain_password = IPBoardManager.__generate_random_pass()
|
||||||
IPBoardManager.update_user(username, email, plain_password)
|
IPBoardManager.update_user(username, email, plain_password)
|
||||||
return plain_password
|
return plain_password
|
||||||
|
@ -213,9 +213,10 @@ class MumbleManager:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_user_password(username):
|
def update_user_password(username, password=None):
|
||||||
logger.debug("Updating mumble user %s password." % username)
|
logger.debug("Updating mumble user %s password." % username)
|
||||||
dbcursor = connections['mumble'].cursor()
|
dbcursor = connections['mumble'].cursor()
|
||||||
|
if not password:
|
||||||
password = MumbleManager.__generate_random_pass()
|
password = MumbleManager.__generate_random_pass()
|
||||||
pwhash = MumbleManager._gen_pwhash(password)
|
pwhash = MumbleManager._gen_pwhash(password)
|
||||||
logger.debug("Proceeding with mumble user %s password update - pwhash starts with %s" % (username, pwhash[0:5]))
|
logger.debug("Proceeding with mumble user %s password update - pwhash starts with %s" % (username, pwhash[0:5]))
|
||||||
|
@ -82,9 +82,10 @@ class OpenfireManager:
|
|||||||
logger.info("Unlocked openfire user %s" % username)
|
logger.info("Unlocked openfire user %s" % username)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_user_pass(username):
|
def update_user_pass(username, password=None):
|
||||||
logger.debug("Updating openfire user %s password." % username)
|
logger.debug("Updating openfire user %s password." % username)
|
||||||
try:
|
try:
|
||||||
|
if not password:
|
||||||
password = OpenfireManager.__generate_random_pass()
|
password = OpenfireManager.__generate_random_pass()
|
||||||
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
api = ofUsers(settings.OPENFIRE_ADDRESS, settings.OPENFIRE_SECRET_KEY)
|
||||||
api.update_user(username, password=password)
|
api.update_user(username, password=password)
|
||||||
|
@ -248,9 +248,10 @@ class Phpbb3Manager:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_user_password(username, characterid):
|
def update_user_password(username, characterid, password=None):
|
||||||
logger.debug("Updating phpbb user %s password" % username)
|
logger.debug("Updating phpbb user %s password" % username)
|
||||||
cursor = connections['phpbb3'].cursor()
|
cursor = connections['phpbb3'].cursor()
|
||||||
|
if not password:
|
||||||
password = Phpbb3Manager.__generate_random_pass()
|
password = Phpbb3Manager.__generate_random_pass()
|
||||||
if Phpbb3Manager.check_user(username):
|
if Phpbb3Manager.check_user(username):
|
||||||
pwhash = Phpbb3Manager.__gen_hash(password)
|
pwhash = Phpbb3Manager.__gen_hash(password)
|
||||||
|
@ -26,6 +26,7 @@ from celerytask.tasks import update_discord_groups
|
|||||||
from forms import JabberBroadcastForm
|
from forms import JabberBroadcastForm
|
||||||
from forms import FleetFormatterForm
|
from forms import FleetFormatterForm
|
||||||
from forms import DiscordForm
|
from forms import DiscordForm
|
||||||
|
from forms import ServicePasswordForm
|
||||||
from util import check_if_user_has_permission
|
from util import check_if_user_has_permission
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
@ -457,3 +458,128 @@ def activate_discord(request):
|
|||||||
logger.debug("Rendering form for user %s with success %s" % (request.user, success))
|
logger.debug("Rendering form for user %s with success %s" % (request.user, success))
|
||||||
context = {'form': form, 'success': success}
|
context = {'form': form, 'success': success}
|
||||||
return render_to_response('registered/discord.html', context, context_instance=RequestContext(request))
|
return render_to_response('registered/discord.html', context, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_passes_test(service_blue_alliance_test)
|
||||||
|
def set_forum_password(request):
|
||||||
|
logger.debug("set_forum_password called by user %s" % request.user)
|
||||||
|
error = None
|
||||||
|
if request.method == 'POST':
|
||||||
|
logger.debug("Received POST request with form.")
|
||||||
|
form = ServicePasswordForm(request.POST)
|
||||||
|
logger.debug("Form is valid: %s" % form.is_valid())
|
||||||
|
if form.is_valid():
|
||||||
|
password = form.cleaned_data['password']
|
||||||
|
logger.debug("Form contains password of length %s" % len(password))
|
||||||
|
authinfo = AuthServicesInfoManager.get_auth_service_info(request.user)
|
||||||
|
result = Phpbb3Manager.update_user_password(authinfo.forum_username, authinfo.main_char_id, password=password)
|
||||||
|
if result != "":
|
||||||
|
AuthServicesInfoManager.update_user_forum_info(authinfo.forum_username, result, request.user)
|
||||||
|
logger.info("Succesfully reset forum password for user %s" % request.user)
|
||||||
|
return HttpResponseRedirect("/services/")
|
||||||
|
else:
|
||||||
|
logger.error("Failed to install custom forum password for user %s" % request.user)
|
||||||
|
error = "Failed to install custom password."
|
||||||
|
else:
|
||||||
|
error = "Invalid password provided"
|
||||||
|
else:
|
||||||
|
logger.debug("Request is not type POST - providing empty form.")
|
||||||
|
form = ServicePasswordForm()
|
||||||
|
|
||||||
|
logger.debug("Rendering form for user %s" % request.user)
|
||||||
|
context = {'form': form, 'service': 'Forum'}
|
||||||
|
return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_passes_test(service_blue_alliance_test)
|
||||||
|
def set_mumble_password(request):
|
||||||
|
logger.debug("set_mumble_password called by user %s" % request.user)
|
||||||
|
error = None
|
||||||
|
if request.method == 'POST':
|
||||||
|
logger.debug("Received POST request with form.")
|
||||||
|
form = ServicePasswordForm(request.POST)
|
||||||
|
logger.debug("Form is valid: %s" % form.is_valid())
|
||||||
|
if form.is_valid():
|
||||||
|
password = form.cleaned_data['password']
|
||||||
|
logger.debug("Form contains password of length %s" % len(password))
|
||||||
|
authinfo = AuthServicesInfoManager.get_auth_service_info(request.user)
|
||||||
|
result = MumbleManager.update_user_password(authinfo.mumble_username, password=password)
|
||||||
|
if result != "":
|
||||||
|
AuthServicesInfoManager.update_user_mumble_info(authinfo.mumble_username, result, request.user)
|
||||||
|
logger.info("Succesfully reset forum password for user %s" % request.user)
|
||||||
|
return HttpResponseRedirect("/services/")
|
||||||
|
else:
|
||||||
|
logger.error("Failed to install custom mumble password for user %s" % request.user)
|
||||||
|
error = "Failed to install custom password."
|
||||||
|
else:
|
||||||
|
error = "Invalid password provided"
|
||||||
|
else:
|
||||||
|
logger.debug("Request is not type POST - providing empty form.")
|
||||||
|
form = ServicePasswordForm()
|
||||||
|
|
||||||
|
logger.debug("Rendering form for user %s" % request.user)
|
||||||
|
context = {'form': form, 'service': 'Mumble', 'error': error}
|
||||||
|
return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_passes_test(service_blue_alliance_test)
|
||||||
|
def set_jabber_password(request):
|
||||||
|
logger.debug("set_jabber_password called by user %s" % request.user)
|
||||||
|
error = None
|
||||||
|
if request.method == 'POST':
|
||||||
|
logger.debug("Received POST request with form.")
|
||||||
|
form = ServicePasswordForm(request.POST)
|
||||||
|
logger.debug("Form is valid: %s" % form.is_valid())
|
||||||
|
if form.is_valid():
|
||||||
|
password = form.cleaned_data['password']
|
||||||
|
logger.debug("Form contains password of length %s" % len(password))
|
||||||
|
authinfo = AuthServicesInfoManager.get_auth_service_info(request.user)
|
||||||
|
result = OpenfireManager.update_user_pass(authinfo.jabber_username, password=password)
|
||||||
|
if result != "":
|
||||||
|
AuthServicesInfoManager.update_user_jabber_info(authinfo.jabber_username, result, request.user)
|
||||||
|
logger.info("Succesfully reset forum password for user %s" % request.user)
|
||||||
|
return HttpResponseRedirect("/services/")
|
||||||
|
else:
|
||||||
|
logger.error("Failed to install custom jabber password for user %s" % request.user)
|
||||||
|
error = "Failed to install custom password."
|
||||||
|
else:
|
||||||
|
error = "Invalid password provided"
|
||||||
|
else:
|
||||||
|
logger.debug("Request is not type POST - providing empty form.")
|
||||||
|
form = ServicePasswordForm()
|
||||||
|
|
||||||
|
logger.debug("Rendering form for user %s" % request.user)
|
||||||
|
context = {'form': form, 'service': 'Jabber', 'error': error}
|
||||||
|
return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@user_passes_test(service_blue_alliance_test)
|
||||||
|
def set_ipboard_password(request):
|
||||||
|
logger.debug("set_ipboard_password called by user %s" % request.user)
|
||||||
|
error = None
|
||||||
|
if request.method == 'POST':
|
||||||
|
logger.debug("Received POST request with form.")
|
||||||
|
form = ServicePasswordForm(request.POST)
|
||||||
|
logger.debug("Form is valid: %s" % form.is_valid())
|
||||||
|
if form.is_valid():
|
||||||
|
password = form.cleaned_data['password']
|
||||||
|
logger.debug("Form contains password of length %s" % len(password))
|
||||||
|
authinfo = AuthServicesInfoManager.get_auth_service_info(request.user)
|
||||||
|
result = IPBoardManager.update_user_password(authinfo.ipboard_username, request.user.email, plain_password=password)
|
||||||
|
if result != "":
|
||||||
|
AuthServicesInfoManager.update_user_ipboard_info(authinfo.ipboard_username, result, request.user)
|
||||||
|
logger.info("Succesfully reset forum password for user %s" % request.user)
|
||||||
|
return HttpResponseRedirect("/services/")
|
||||||
|
else:
|
||||||
|
logger.error("Failed to install custom ipboard password for user %s" % request.user)
|
||||||
|
error = "Failed to install custom password."
|
||||||
|
else:
|
||||||
|
error = "Invalid password provided"
|
||||||
|
else:
|
||||||
|
logger.debug("Request is not type POST - providing empty form.")
|
||||||
|
form = ServicePasswordForm()
|
||||||
|
|
||||||
|
logger.debug("Rendering form for user %s" % request.user)
|
||||||
|
context = {'form': form, 'service': 'IPBoard', 'error': error}
|
||||||
|
return render_to_response('registered/service_password.html', context, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
38
stock/templates/registered/service_password.html
Normal file
38
stock/templates/registered/service_password.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{% extends "public/base.html" %}
|
||||||
|
{% load bootstrap %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block title %}Alliance Auth{% endblock %}
|
||||||
|
|
||||||
|
{% block page_title %}Service Password Change{% endblock page_title %}
|
||||||
|
{% block extra_css %}{% endblock extra_css %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<h1 class="page-header text-center">Set {{service}} Password</h1>
|
||||||
|
{% if error %}
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-md-4 col-md-offset-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="alert alert-danger text-center" role="alert">{{error}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-md-4 col-md-offset-4">
|
||||||
|
<div class="row">
|
||||||
|
<p>Passwords are stored as plain text. Don't re-use another password.</p>
|
||||||
|
<form class="form-signin" role="form" action="" method="POST"
|
||||||
|
onsubmit="submitbutton.disabled = true; return true;">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|bootstrap }}
|
||||||
|
<br/>
|
||||||
|
<button class="btn btn-lg btn-primary btn-block" name="submitbutton" type="submit">Set Password</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
@ -30,6 +30,10 @@
|
|||||||
class="glyphicon glyphicon-ok"></span></button>
|
class="glyphicon glyphicon-ok"></span></button>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a href="{% url 'auth_set_forum_password' %}">
|
||||||
|
<button type="button" class="btn btn-warning"><span
|
||||||
|
class="glyphicon glyphicon-pencil"></span></button>
|
||||||
|
</a>
|
||||||
<a href="{% url 'auth_reset_forum_password' %}">
|
<a href="{% url 'auth_reset_forum_password' %}">
|
||||||
<button type="button" class="btn btn-primary"><span
|
<button type="button" class="btn btn-primary"><span
|
||||||
class="glyphicon glyphicon-refresh"></span></button>
|
class="glyphicon glyphicon-refresh"></span></button>
|
||||||
@ -53,6 +57,10 @@
|
|||||||
class="glyphicon glyphicon-ok"></span></button>
|
class="glyphicon glyphicon-ok"></span></button>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a href="{% url 'auth_set_ipboard_password' %}">
|
||||||
|
<button type="button" class="btn btn-warning"><span
|
||||||
|
class="glyphicon glyphicon-pencil"></span></button>
|
||||||
|
</a>
|
||||||
<a href="{% url 'auth_reset_ipboard_password' %}">
|
<a href="{% url 'auth_reset_ipboard_password' %}">
|
||||||
<button type="button" class="btn btn-primary"><span
|
<button type="button" class="btn btn-primary"><span
|
||||||
class="glyphicon glyphicon-refresh"></span></button>
|
class="glyphicon glyphicon-refresh"></span></button>
|
||||||
@ -77,6 +85,10 @@
|
|||||||
class="glyphicon glyphicon-ok"></span></button>
|
class="glyphicon glyphicon-ok"></span></button>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a href="{% url 'auth_set_jabber_password' %}">
|
||||||
|
<button type="button" class="btn btn-warning"><span
|
||||||
|
class="glyphicon glyphicon-pencil"></span></button>
|
||||||
|
</a>
|
||||||
<a href="{% url 'auth_reset_jabber_password' %}">
|
<a href="{% url 'auth_reset_jabber_password' %}">
|
||||||
<button type="button" class="btn btn-primary"><span
|
<button type="button" class="btn btn-primary"><span
|
||||||
class="glyphicon glyphicon-refresh"></span></button>
|
class="glyphicon glyphicon-refresh"></span></button>
|
||||||
@ -102,6 +114,10 @@
|
|||||||
class="glyphicon glyphicon-ok"></span></button>
|
class="glyphicon glyphicon-ok"></span></button>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a href="{% url 'auth_set_mumble_password' %}">
|
||||||
|
<button type="button" class="btn btn-warning"><span
|
||||||
|
class="glyphicon glyphicon-pencil"></span></button>
|
||||||
|
</a>
|
||||||
<a href="{% url 'auth_reset_mumble_password' %}">
|
<a href="{% url 'auth_reset_mumble_password' %}">
|
||||||
<button type="button" class="btn btn-primary"><span
|
<button type="button" class="btn btn-primary"><span
|
||||||
class="glyphicon glyphicon-refresh"></span></button>
|
class="glyphicon glyphicon-refresh"></span></button>
|
||||||
@ -200,6 +216,10 @@
|
|||||||
class="glyphicon glyphicon-ok"></span></button>
|
class="glyphicon glyphicon-ok"></span></button>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a href="{% url 'auth_set_forum_password' %}">
|
||||||
|
<button type="button" class="btn btn-warning"><span
|
||||||
|
class="glyphicon glyphicon-pencil"></span></button>
|
||||||
|
</a>
|
||||||
<a href="{% url 'auth_reset_forum_password' %}">
|
<a href="{% url 'auth_reset_forum_password' %}">
|
||||||
<button type="button" class="btn btn-primary"><span
|
<button type="button" class="btn btn-primary"><span
|
||||||
class="glyphicon glyphicon-refresh"></span></button>
|
class="glyphicon glyphicon-refresh"></span></button>
|
||||||
@ -224,6 +244,10 @@
|
|||||||
class="glyphicon glyphicon-ok"></span></button>
|
class="glyphicon glyphicon-ok"></span></button>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a href="{% url 'auth_set_ipboard_password' %}">
|
||||||
|
<button type="button" class="btn btn-warning"><span
|
||||||
|
class="glyphicon glyphicon-pencil"></span></button>
|
||||||
|
</a>
|
||||||
<a href="{% url 'auth_reset_ipboard_password' %}">
|
<a href="{% url 'auth_reset_ipboard_password' %}">
|
||||||
<button type="button" class="btn btn-primary"><span
|
<button type="button" class="btn btn-primary"><span
|
||||||
class="glyphicon glyphicon-refresh"></span></button>
|
class="glyphicon glyphicon-refresh"></span></button>
|
||||||
@ -248,6 +272,10 @@
|
|||||||
class="glyphicon glyphicon-ok"></span></button>
|
class="glyphicon glyphicon-ok"></span></button>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a href="{% url 'auth_set_jabber_password' %}">
|
||||||
|
<button type="button" class="btn btn-warning"><span
|
||||||
|
class="glyphicon glyphicon-pencil"></span></button>
|
||||||
|
</a>
|
||||||
<a href="{% url 'auth_reset_jabber_password' %}">
|
<a href="{% url 'auth_reset_jabber_password' %}">
|
||||||
<button type="button" class="btn btn-primary"><span
|
<button type="button" class="btn btn-primary"><span
|
||||||
class="glyphicon glyphicon-refresh"></span></button>
|
class="glyphicon glyphicon-refresh"></span></button>
|
||||||
@ -273,6 +301,10 @@
|
|||||||
class="glyphicon glyphicon-ok"></span></button>
|
class="glyphicon glyphicon-ok"></span></button>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a href="{% url 'auth_set_mumble_password' %}">
|
||||||
|
<button type="button" class="btn btn-warning"><span
|
||||||
|
class="glyphicon glyphicon-pencil"></span></button>
|
||||||
|
</a>
|
||||||
<a href="{% url 'auth_reset_mumble_password' %}">
|
<a href="{% url 'auth_reset_mumble_password' %}">
|
||||||
<button type="button" class="btn btn-primary"><span
|
<button type="button" class="btn btn-primary"><span
|
||||||
class="glyphicon glyphicon-refresh"></span></button>
|
class="glyphicon glyphicon-refresh"></span></button>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user