diff --git a/htdocs/checkcolumn.js b/htdocs/checkcolumn.js
new file mode 100644
index 0000000..54c39f2
--- /dev/null
+++ b/htdocs/checkcolumn.js
@@ -0,0 +1,39 @@
+/*
+ * Ext JS Library 2.2
+ * Copyright(c) 2006-2008, Ext JS, LLC.
+ * licensing@extjs.com
+ *
+ * http://extjs.com/license
+ */
+
+Ext.grid.CheckColumn = function(config){
+ Ext.apply(this, config);
+ if(!this.id){
+ this.id = Ext.id();
+ }
+ this.renderer = this.renderer.createDelegate(this);
+};
+
+Ext.grid.CheckColumn.prototype ={
+ init : function(grid){
+ this.grid = grid;
+ this.grid.on('render', function(){
+ var view = this.grid.getView();
+ view.mainBody.on('mousedown', this.onMouseDown, this);
+ }, this);
+ },
+
+ onMouseDown : function(e, t){
+ if(t.className && t.className.indexOf('x-grid3-cc-'+this.id) != -1){
+ e.stopEvent();
+ var index = this.grid.getView().findRowIndex(t);
+ var record = this.grid.store.getAt(index);
+ record.set(this.dataIndex, !record.data[this.dataIndex]);
+ }
+ },
+
+ renderer : function(v, p, record){
+ p.css += ' x-grid3-check-col-td';
+ return '
';
+ }
+};
diff --git a/pyweb/mumble/urls.py b/pyweb/mumble/urls.py
index 3ca550e..431deb4 100644
--- a/pyweb/mumble/urls.py
+++ b/pyweb/mumble/urls.py
@@ -18,6 +18,7 @@ from django.conf.urls.defaults import *
urlpatterns = patterns(
'mumble.views',
+ ( r'(?P\d+)/users', 'users' ),
( r'(?P\d+)/(?P\d+)texture.png', 'showTexture' ),
( r'(?P\d+)/texture.png', 'showTexture' ),
( r'(?P\d+)', 'show' ),
diff --git a/pyweb/mumble/views.py b/pyweb/mumble/views.py
index 27091b5..326f769 100644
--- a/pyweb/mumble/views.py
+++ b/pyweb/mumble/views.py
@@ -14,6 +14,7 @@
* GNU General Public License for more details.
"""
+import simplejson
from StringIO import StringIO
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
@@ -21,6 +22,7 @@ from django.template import RequestContext
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import User
from django.conf import settings
from models import Mumble, MumbleUser
@@ -174,4 +176,62 @@ def showTexture( request, server, userid = None ):
return HttpResponse( buffer.getvalue(), "image/png" );
+@login_required
+def users( request, server ):
+ srv = get_object_or_404( Mumble, id=int(server) );
+
+ if not srv.isUserAdmin( request.user ):
+ return HttpResponse(
+ simplejson.dumps({ 'success': False, 'objects': [], 'errormsg': 'Access denied' }),
+ mimetype='text/javascript'
+ );
+
+ if request.method == 'POST':
+ data = simplejson.loads( request.POST['data'] );
+ print "Json: ", data;
+ for record in data:
+ if record['id'] == -1:
+ if record['delete']:
+ continue;
+ mu = MumbleUser( server=srv );
+ else:
+ mu = MumbleUser.objects.get( id=record['id'] );
+ if record['delete']:
+ mu.delete();
+ continue;
+
+ mu.name = record['name'];
+ mu.password = record['password'];
+ mu.isAdmin = record['admin'];
+
+ if record['owner_id']:
+ mu.owner = User.objects.get( id=int(record['owner_id']) );
+
+ mu.save();
+
+ users = [];
+ for mu in srv.mumbleuser_set.all():
+ owner = None;
+ owner_id = None;
+ if mu.owner is not None:
+ owner = unicode( mu.owner );
+ owner_id = mu.owner.id
+
+ users.append( {
+ 'id': mu.id,
+ 'name': mu.name,
+ 'password': None,
+ 'owner': owner,
+ 'owner_id': owner_id,
+ 'admin': mu.getAdmin(),
+ } );
+
+ return HttpResponse(
+ simplejson.dumps( { 'success': True, 'objects': users } ),
+ mimetype='text/javascript'
+ );
+
+
+
+
diff --git a/template/index.htm b/template/index.htm
index 5271b38..5f82dcd 100644
--- a/template/index.htm
+++ b/template/index.htm
@@ -11,6 +11,7 @@
+
{% block HeadTag %}
{% endblock %}
diff --git a/template/mumble/mumble.htm b/template/mumble/mumble.htm
index 02a47f6..f5927ee 100644
--- a/template/mumble/mumble.htm
+++ b/template/mumble/mumble.htm
@@ -144,6 +144,37 @@
Ext.get( 'mumble_admin' ).addClass( 'x-hide-display' );
{% endif %}
+ {% if CurrentUserIsAdmin %}
+ userRecord = Ext.data.Record.create([
+ { name: 'id', type: 'int' },
+ { name: 'name', type: 'string' },
+ { name: 'password', type: 'string' },
+ { name: 'owner', type: 'string' },
+ { name: 'owner_id', type: 'int' },
+ { name: 'admin', type: 'bool' },
+ { name: 'delete', type: 'bool' },
+ ]);
+
+ userAdminStore = new Ext.data.Store({
+ url: '/mumble/{{ DBaseObject.id }}/users/',
+ reader: new Ext.data.JsonReader({
+ root: 'objects',
+ fields: userRecord,
+ }),
+ autoLoad: true,
+ });
+
+ adminColumn = new Ext.grid.CheckColumn({
+ header: '{% trans "Admin on root channel" %}',
+ dataIndex: 'admin',
+ });
+
+ deleteColumn = new Ext.grid.CheckColumn({
+ header: '{% trans "Delete" %}',
+ dataIndex: 'delete',
+ });
+ {% endif %}
+
var cardpanel = new Ext.Panel({
renderTo: 'mumble_ext_container',
layout: 'card',
@@ -157,13 +188,79 @@
defaults: { autoheight: true },
activeTab: {{ DisplayTab }},
items: [
- { contentEl: 'mumble_motd', title: '{% trans "Server Info" %}', autoScroll: true },
- { contentEl: 'mumble_registration', title: '{% trans "Registration" %}', autoScroll: true },
+ { contentEl: 'mumble_motd', title: '{% trans "Server Info" %}', autoScroll: true },
+ { contentEl: 'mumble_registration', title: '{% trans "Registration" %}', autoScroll: true },
{% if CurrentUserIsAdmin %}
- { contentEl: 'mumble_admin', title: '{% trans "Administration" %}', autoScroll: true },
+ { contentEl: 'mumble_admin', title: '{% trans "Administration" %}', autoScroll: true },
{% endif %}
{% if Registered %}
- { contentEl: 'mumble_texture', title: '{% trans "User Texture" %}', autoScroll: true },
+ { contentEl: 'mumble_texture',title: '{% trans "User Texture" %}', autoScroll: true },
+ {% endif %}
+ {% if CurrentUserIsAdmin %}
+ {
+ title: '{% trans "User List" %}',
+ xtype: 'editorgrid',
+ store: userAdminStore,
+ cm: new Ext.grid.ColumnModel( [ {
+ header: '{% trans "name" %}',
+ dataIndex: 'name',
+ editor: new Ext.form.TextField({
+ allowBlank: false,
+ }),
+ }, {
+ header: '{% trans "Account owner" %}',
+ dataIndex: 'owner',
+ editor: new Ext.form.TextField(),
+ }, adminColumn, {
+ header: '{% trans "Change password" %}',
+ dataIndex: 'password',
+ editor: new Ext.form.TextField({
+ inputType: 'password',
+ }),
+ }, deleteColumn ] ),
+ tbar: [{
+ text: '{% trans "Add" %}',
+ handler : function(){
+ userAdminStore.add( new userRecord( {
+ id: -1,
+ name: 'New User',
+ admin: false,
+ owner: null,
+ owner_id: null,
+ password: null,
+ 'delete': false,
+ } ) );
+ }
+ }, {
+ text: '{% trans "Save" %}',
+ handler : function(){
+ data = [];
+ for( i = 0; i < userAdminStore.data.items.length; i++ ){
+ rec = userAdminStore.data.items[i];
+ if( rec.dirty ){
+ data.push(rec.data);
+ }
+ }
+
+ var conn = new Ext.data.Connection();
+ conn.request( {
+ url: userAdminStore.url,
+ params: { data: Ext.encode( data ), },
+ success: function(){
+ for( i = 0; i < userAdminStore.data.items.length; i++ ){
+ rec = userAdminStore.data.items[i];
+ if( rec.data['delete'] == true )
+ userAdminStore.remove( rec );
+ else if( rec.dirty ){
+ rec.commit();
+ }
+ }
+ },
+ } );
+ }
+ }],
+ plugins: [ adminColumn, deleteColumn ],
+ },
{% endif %}
]
},