diff --git a/pyweb/mumble/media/js/channelviewerplugins.js b/pyweb/mumble/media/js/channelviewerplugins.js
new file mode 100644
index 0000000..7e77fdd
--- /dev/null
+++ b/pyweb/mumble/media/js/channelviewerplugins.js
@@ -0,0 +1,139 @@
+// kate: space-indent on; indent-width 4; replace-tabs on;
+
+Ext.namespace('Ext.ux');
+
+Ext.ux.MumbleUserEditor = Ext.extend( Ext.Component, {
+ clickHandler: function( node, ev ){
+ if( typeof node.attributes.userdata != "undefined" ){
+ this.activate(node.attributes.userdata);
+ }
+ },
+
+ init: function( tree ){
+ this.tree = tree;
+ tree.on("click", this.clickHandler, this);
+ },
+
+ activate: function( userdata ){
+ if( !this.wnd ){
+ this.userdata = userdata;
+ this.wnd = new Ext.Window({
+ title: this.windowTitle || gettext("User details"),
+ layout: 'fit',
+ items: [{
+ xtype: "tabpanel",
+ activeTab: 0,
+ border: false,
+ items: [{
+ html: userdata.comment || gettext("No user comment set"),
+ title: gettext("User comment"),
+ }, {
+ title: gettext("Avatar"),
+ html: '
',
+ }, {
+ title: gettext("Infos"),
+ html: "
- admin: yes
- registered: maybe
",
+ }, {
+ xtype: "form",
+ border: false,
+ title: gettext("Kick/Ban"),
+ items: [{
+ xtype: "checkbox",
+ fieldLabel: gettext("Ban"),
+ name: "ban"
+ }, {
+ xtype: "numberfield",
+ fieldLabel: gettext("Ban duration"),
+ value: 3600,
+ name: "duration"
+ }, {
+ xtype: "label",
+ text: gettext("Only if banning. Set to 0 for permanent ban, any other value for the ban duration in seconds."),
+ cls: "form_hint_label",
+ }, {
+ xtype: "textfield",
+ fieldLabel: gettext("Reason"),
+ name: "reason"
+ }],
+ fbar: [{
+ scope: this,
+ text: gettext("Kick"),
+ handler: function(btn){
+ f = btn.ownerCt.ownerCt.getForm().getValues();
+ Mumble.kickUser(
+ this.serverid, this.userdata.session, f.reason, (f.ban || false), parseInt(f.duration)
+ );
+ }
+ }],
+ }],
+ }],
+ width: 500,
+ height: 300,
+ scope: this,
+ listeners: {
+ beforeclose: function(){
+ this.owner.wnd = null;
+ }
+ },
+ });
+ this.wnd.owner = this;
+ }
+ if( !this.wnd.isVisible() ){
+ this.wnd.show();
+ mypos = this.tree.getPosition();
+ mysize = this.tree.getSize();
+ this.wnd.setPosition( mypos[0] + mysize.width - 50, mypos[1] + 50 );
+ }
+ else{
+ this.wnd.close();
+ }
+ },
+} );
+
+Ext.ux.MumbleChannelEditor = Ext.extend( Ext.Component, {
+ clickHandler: function( node, ev ){
+ if( typeof node.attributes.chandata != "undefined" ){
+ this.activate(node.attributes.chandata);
+ }
+ },
+
+ init: function( tree ){
+ this.tree = tree;
+ tree.on("click", this.clickHandler, this);
+ },
+
+ activate: function( chandata ){
+ if( !this.wnd ){
+ this.wnd = new Ext.Window({
+ title: this.windowTitle || gettext("Channel details"),
+ layout: 'fit',
+ items: [{
+ xtype: "tabpanel",
+ activeTab: 0,
+ items: [{
+ html: chandata.description || gettext("No channel description set"),
+ title: gettext("Channel description"),
+ }],
+ }],
+ width: 500,
+ height: 300,
+ scope: this,
+ listeners: {
+ beforeclose: function(){
+ this.owner.wnd = null;
+ }
+ },
+ });
+ this.wnd.owner = this;
+ }
+ if( !this.wnd.isVisible() ){
+ this.wnd.show();
+ mypos = this.tree.getPosition();
+ mysize = this.tree.getSize();
+ this.wnd.setPosition( mypos[0] + mysize.width - 50, mypos[1] + 50 );
+ }
+ else{
+ this.wnd.close();
+ }
+ },
+} );
diff --git a/pyweb/mumble/models.py b/pyweb/mumble/models.py
index c02bdce..a7e15db 100644
--- a/pyweb/mumble/models.py
+++ b/pyweb/mumble/models.py
@@ -554,8 +554,8 @@ class Mumble( models.Model ):
def kickUser( self, sessionid, reason="" ):
return self.ctl.kickUser( self.srvid, sessionid, reason )
- def banUser( self, sessionid, reason="" ):
- return self.ctl.addBanForSession( self.srvid, sessionid, reason=reason )
+ def banUser( self, sessionid, reason="", duration=0 ):
+ return self.ctl.addBanForSession( self.srvid, sessionid, reason=reason, duration=duration )
def moveUser( self, sessionid, channelid ):
return self.ctl.moveUser( self.srvid, sessionid, channelid )
diff --git a/pyweb/mumble/templates/mumble/mumble.html b/pyweb/mumble/templates/mumble/mumble.html
index 5f5a90a..afcd7e3 100644
--- a/pyweb/mumble/templates/mumble/mumble.html
+++ b/pyweb/mumble/templates/mumble/mumble.html
@@ -12,8 +12,9 @@
-
+
+
@@ -59,6 +60,12 @@
width: 350,
split: true,
enableDD: true,
+ plugins: [
+ new Ext.ux.MumbleUserEditor({
+ serverid: {{MumbleServer.id}}
+ }),
+ new Ext.ux.MumbleChannelEditor()
+ ],
source_url: "{% url mumble.views.cvp_json MumbleServer.id %}",
imageurl: '{{MUMBLE_MEDIA_PREFIX}}/img',
listeners: {
diff --git a/pyweb/mumble/views.py b/pyweb/mumble/views.py
index 154a2eb..424015d 100644
--- a/pyweb/mumble/views.py
+++ b/pyweb/mumble/views.py
@@ -258,6 +258,14 @@ def moveChannel( request, server, channelid, parentid ):
raise Exception( 'Access denied' )
srv.moveChannel( channelid, parentid )
+@EXT_DIRECT_PROVIDER.register_method( "Mumble" )
+def kickUser( request, server, sessionid, reason, ban, duration ):
+ srv = get_object_or_404( Mumble, id=int(server) )
+ if not srv.isUserAdmin( request.user ):
+ raise Exception( 'Access denied' )
+ if ban:
+ srv.banUser( sessionid, reason, duration )
+ srv.kickUser( sessionid, reason )
@EXT_DIRECT_PROVIDER.register_method( "MumbleUserAdmin" )
def users( request, server ):