Skip to content

Commit

Permalink
Merge branch 'master' of github.com:alexhudson/bongo-web-client
Browse files Browse the repository at this point in the history
* 'master' of github.com:alexhudson/bongo-web-client:
  Make login system hide new login pane, not just the form
  Bring through list of mapped domains underneath domain configs
  Remove 'account name is domain name' mapping option
  Separate user accounts into global/non-global
  Fix minor JSON errors in test fixture data
  Bring system account list through to front admin page.
  Add store protocol for user account management
  • Loading branch information
Lance Haig committed Aug 6, 2011
2 parents 6e30c75 + cb27f27 commit a601b0f
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 37 deletions.
55 changes: 46 additions & 9 deletions admin/backend/classes.php
Expand Up @@ -88,21 +88,61 @@ public function grabStoreConfig() {
}

// look for domain information
array_unshift($result['queue']['domains'], 'default_config');
$result['aliases'] = array();
foreach ($result['queue']['domains'] as $domain) {
$result['domains'] = array();
$domain_maps = array();

// FIXME: do I really need to co-erce this to a simple array? :(
$result['queue']['domains'] = array_values($result['queue']['domains']);

$domains = $result['queue']['domains'];
array_unshift($domains, 'default_config');
foreach ($domains as $domain) {
$domain_config = $this->store->Read('/config/aliases/' . $domain);
$result['aliases'][$domain] = json_decode($domain_config->value, true);
$config = json_decode($domain_config->value, true);

if (isset($config['domainalias']) && ($config['domainalias'] != '')) {
$domain_maps[$domain] = $config['domainalias'];
}

$config['name'] = $domain;
$result['domains'][$domain] = $config;
// change alias mapping to something more amenable.
$list = $result['aliases'][$domain]['aliases'];
$list = $result['domains'][$domain]['aliases'];

$newlist = array();
foreach ($list as $from => $to) {
array_push($newlist, array('from' => $from, 'to' => $to));
}

$result['aliases'][$domain]['aliases'] = $newlist;
$result['domains'][$domain]['domainaliases'] = array();
$result['domains'][$domain]['aliases'] = $newlist;
$result['domains'][$domain]['accounts'] = array();
}
// merge the mapped domains information back in - do this afterwards
// so we know we've already loaded the main config
foreach ($domain_maps as $from => $to) {
if (isset($result['domains'][$to])) {
array_push($result['domains'][$to]['domainaliases'], $from);
}
// if there is no domain to stick it on, we have a config
// problem that we ought to report really... FIXME
}

// look for user accounts
$userCallback = new Bongo_StoreCallback(null, function($resp, &$data) {
array_push($data, $resp->name);
}, array());
$userCallback->data = array();
$this->store->Store();
$this->store->AccountList($userCallback);
foreach ($userCallback->data as $account) {
$acpos = strpos($account, '@');
if ($acpos === false) {
array_push($result['domains']['default_config']['accounts'], array('name'=>$account));
} else {
$domain = substr($account, $acpos+1);
array_push($result['domains'][$domain]['accounts'], array('name'=>$account));
}
}
} catch (Exception $e) {
return null;
Expand All @@ -120,9 +160,6 @@ public function grabExtraFlags() {
public function saveData($dataset) {
$this->store->Store('_system');

// remove data hacks
$dataset['queue']['domains'] = array_filter($dataset['queue']['domains'], function ($var) { return ($var != 'default_config'); });

// save current data
foreach ($dataset as $config => $configitems) {
if ($config == 'aliases') continue;
Expand Down
78 changes: 63 additions & 15 deletions admin/index.html
Expand Up @@ -29,7 +29,8 @@
</head>

<body id="home">
<div id="login-pane" style="display: block;">

<div id="login-pane">
<div id="login-bg-top"></div>
<div id="login-bg-bottom"></div>
<h1 id="login-logo">Bongo</h1>
Expand All @@ -40,24 +41,27 @@ <h4 id="login-form-message">&nbsp;</h4>
<tr>
<th>
<label id="login-user-label">Name:</label>
</th>
<td colspan="2">
</th>
<td colspan="2">
<input id="login-user" class="text-entry" type="text" style="width: 98%;" name="name" >
</td>
</tr>
<tr>
<th>
<label id="login-password-label">Password:</label>
</th>
<td colspan="2">
</th>
<td colspan="2">
<input id="login-password" class="text-entry" type="password" style="width: 98%;" name="password">
</td>
</tr>
<tr>
<td colspan="3">
<input id="login-form-button" type="button" style="float: right; display: block;" value="Login">
</td>
</tr>
<input id="login-form-button" type="button" style="float: right; display: block;" value="Login">
</td>
</tr>
</tbody>
</table>
</form>
</div>

<div id="admin-tool" style="display: none">
Expand All @@ -70,17 +74,30 @@ <h1>Bongo Administration</h1>

<div id="admin-tabs">
<ul>
<li><a href="#tabs-accounts">Global Accounts</a></li>
<li><a href="#tabs-domains">Domains</a></li>
<li><a href="#tabs-agents">Global settings</a></li>
<li><a href="#tabs-anti">Antispam &amp; virus</a></li>
<li><a href="#tabs-access">POP &amp; IMAP</a></li>
<li><a href="#tabs-smtp">SMTP</a></li>
<li><a href="#tabs-queue">Internal queue</a></li>
</ul>
<div id="tabs-accounts">
<table>
<thead>
<tr>
<th>Login name</th>
</tr>
</thead>
<tbody data-bind="template: { name: 'tmp_account_list', foreach: domains['default_config'].accounts }"></tbody>
</table>
</div>
<div id="tabs-domains">
<div data-bind="visible: ! _showSelectedDomain()">
<h2>Domains available</h2>

<button data-bind="click: function() { _selectedDomain('default_config'); _showSelectedDomain(true); }">Edit fall-back configuration</button>

<table>
<thead>
<tr>
Expand All @@ -102,26 +119,45 @@ <h2>Domains available</h2>
<button data-bind="click: function () { _showSelectedDomain(false); } ">Close</button>
<h2>Domain: <span data-bind="text: _selectedDomain()">domain name</span></h2>

<p>Domain is mapped to: <input data-bind="value: aliases[_selectedDomain()]['domainalias']" /></p>

<div data-bind="visible: aliases[_selectedDomain()]['domainalias']() == ''">
<p>Username mapping: <select data-bind="value: aliases[_selectedDomain()]['username-mapping']">
<div data-bind="visible: domains[_selectedDomain()]['domainalias']() == ''">
<p>Username mapping: <select data-bind="value: domains[_selectedDomain()]['username-mapping']">
<option value="0">E-mail address local part is user account name</option>
<option value="1">Full e-mail address is user account name</option>
<option value="2">E-mail address domain name is user account name</option>
</select></p>

<table>
<thead >
<th>Incoming local part</th>
<th>Maps to</th>
</thead>
<tbody data-bind="template: { name: 'tmp_domain_mapping', foreach: aliases[_selectedDomain()]['aliases'], templateOptions: { aliases: aliases, domain: _selectedDomain() } }">
<tbody data-bind="template: { name: 'tmp_domain_mapping', foreach: domains[_selectedDomain()]['aliases'], templateOptions: { domains: domains, domain: _selectedDomain() } }">
</tbody>
</table>
<button data-bind="click: function () { admin.addMapping(); }">Add new mapping</button>
</div>

<h3>Domain Accounts</h3>

<table>
<thead>
<tr>
<th>Login name</th>
</tr>
</thead>
<tbody data-bind="template: { name: 'tmp_account_list', foreach: domains[_selectedDomain()].accounts }"></tbody>
</table>

<h3>Domains mapped onto this configuration</h3>

<table>
<thead>
<tr>
<th>Domain name</th>
</tr>
</thead>
<tbody data-bind="template: { name: 'tmp_mapped_domain_list', foreach: domains[_selectedDomain()].domainaliases }"></tbody>
</table>

<br />
<button data-bind="click: function () { admin.removeCurrentDomain(); }">Remove domain</button>
</div>
Expand Down Expand Up @@ -278,7 +314,19 @@ <h2>IMAP</h2>
<tr>
<td><input type="text" data-bind="value: from" /></td>
<td><input type="text" data-bind="value: to" /></td>
<td><button data-bind="click: function () { $item.aliases[$item.domain]['aliases'].remove($data); }">Remove</button></td>
<td><button data-bind="click: function () { $item.domains[$item.domain]['aliases'].remove($data); }">Remove</button></td>
</tr>
</script>

<script type="text/html" id="tmp_account_list">
<tr>
<td data-bind="text: name">Account name</td>
</tr>
</script>

<script type="text/html" id="tmp_mapped_domain_list">
<tr>
<td data-bind="text: $data">Domain name</td>
</tr>
</script>

Expand Down
12 changes: 6 additions & 6 deletions admin/js/admin.js
Expand Up @@ -15,7 +15,7 @@ Bongo.AdminTool = function(backend) {
});
$('#admin-logout').click(function() {
$.cookie('bongo_admin_cookie', 'unset', { expires: -1, path: '/' });
$('#login-form').show();
$('#login-pane').show();
$('#admin-tool').hide();
});
$('#admin-save').click(function () {
Expand All @@ -26,11 +26,11 @@ Bongo.AdminTool = function(backend) {

var existing_cookie = $.cookie('bongo_admin_cookie');
if (existing_cookie) {
$('#login-form').hide();
$('#login-pane').hide();
// TODO: show some kind of holding thing?
$this.loadData({ command: 'login', cookie: existing_cookie },
function() {
$('#login-form').show();
$('#login-pane').show();
});
}
},
Expand Down Expand Up @@ -59,7 +59,7 @@ Bongo.AdminTool = function(backend) {
$this.model._showAddDomain = ko.observable(false);

ko.applyBindings($this.model);
$('#login-form').hide();
$('#login-pane').hide();
$('#admin-tool').show();
},

Expand All @@ -80,7 +80,7 @@ Bongo.AdminTool = function(backend) {
},

addMapping: function () {
this.model.aliases[this.model._selectedDomain()]['aliases'].push({
this.model.domains[this.model._selectedDomain()]['aliases'].push({
from: ko.observable('from'),
to: ko.observable('to')
});
Expand All @@ -92,7 +92,7 @@ Bongo.AdminTool = function(backend) {
this.model.queue.domains.push(name);
var aliases = ko.observableArray();
aliases.push({ from: ko.observable('postmaster'), to: ko.observable('admin') });
this.model.aliases[name] = {
this.model.domains[name] = {
'domainalias': ko.observable(''),
'aliases': aliases,
'username-mapping': ko.observable(0)
Expand Down
14 changes: 14 additions & 0 deletions library/Bongo/CommandStreamResponse.php
Expand Up @@ -64,6 +64,20 @@ public function ProcessResponse($data) {
}
}

// 2001 <accountname>
class Bongo_CommandStreamResponse_AccountList extends Bongo_CommandStreamResponse
{
public $name;

public function ProcessResponse($data) {
if ($this->response_code == 2001) {
$bits = explode(" ", $data);

$this->name = $bits[0];
}
}
}

class Bongo_CommandStreamResponse_Collections extends Bongo_CommandStreamResponse
{
public $guid;
Expand Down
23 changes: 23 additions & 0 deletions library/Bongo/Store.php
Expand Up @@ -286,4 +286,27 @@ public function Write($collection, $type, $content, $options) {
throw new Bongo_StoreException("Can't write document");
}
}

public function AccountCreate($username, $password) {
$this->SendCommand("ACCOUNT CREATE $username $password");
return $this->GetLineResponse();
}

public function AccountDelete($username) {
$this->SendCommand("ACCOUNT DELETE $username");
return $this->GetLineResponse();
}

public function AccountList(Bongo_StoreCallback $callback) {
$this->SendCommand("ACCOUNT LIST");

while(TRUE) {
$response = $this->GetLineResponse('Bongo_CommandStreamResponse_AccountList');
if ($response->response_code == 2001) {
$this->doCallback($callback, $response);
} else {
return $response;
}
}
}
}
24 changes: 17 additions & 7 deletions test/server-config.json
Expand Up @@ -107,27 +107,37 @@
"require_auth":true
},

"aliases": {
"domains": {
"default_config" : {
"domainalias" : "",
"domainaliases" : [],
"aliases" : [
{ "from: "postmaster", "to" : "admin" }
{ "from": "postmaster", "to" : "admin" }
],
"username-mapping" : 0
"username-mapping" : 0,
"accounts" : [ { "name": "admin" } ]
},
"example.com" : {
"domainalias" : "",
"domainaliases" : [ "mapped.com" ],
"aliases" : [
{ "from: "postmaster", "to" : "admin" }
{ "from": "postmaster", "to" : "admin" }
],
"username-mapping" : 1
"username-mapping" : 1,
"accounts" : [ { "name": "fred@example.com" }, { "name": "joe@example.com" } ]
},
"another.example.com" : {
"domainalias" : "",
"domainaliases" : [],
"aliases" : [
{ "from: "postmaster", "to" : "admin" }
{ "from": "postmaster", "to" : "admin" }
],
"username-mapping" : 2
"username-mapping" : 1,
"accounts" : []
},
"mapped.com": {
"domainaliases" : [],
"domainalias" : "example.com"
}
}
}

0 comments on commit a601b0f

Please sign in to comment.