- Add Reset PW and Set Quota action buttons to each mailbox row - Shared edit modal that switches between password / quota modes - New woocow_admin_mailbox_edit AJAX handler in PHP - Quota reloads mailbox list after save; password closes modal silently - Customer-facing Change Password was already implemented in account JS Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
636 lines
27 KiB
PHP
636 lines
27 KiB
PHP
<?php
|
||
/**
|
||
* WooCow Admin – menu pages + AJAX handlers for the backend.
|
||
*/
|
||
defined( 'ABSPATH' ) || exit;
|
||
|
||
class WooCow_Admin {
|
||
|
||
public function __construct() {
|
||
add_action( 'admin_menu', [ $this, 'register_menu' ] );
|
||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
||
|
||
$ajax_actions = [
|
||
'woocow_servers_list',
|
||
'woocow_server_save',
|
||
'woocow_server_delete',
|
||
'woocow_server_test',
|
||
'woocow_server_domains',
|
||
'woocow_assignments_list',
|
||
'woocow_assignment_save',
|
||
'woocow_assignment_delete',
|
||
'woocow_customers_search',
|
||
'woocow_admin_mailboxes',
|
||
'woocow_admin_mailbox_create',
|
||
'woocow_admin_mailbox_delete',
|
||
'woocow_admin_mailbox_edit',
|
||
];
|
||
|
||
foreach ( $ajax_actions as $action ) {
|
||
add_action( 'wp_ajax_' . $action, [ $this, 'ajax_' . $action ] );
|
||
}
|
||
}
|
||
|
||
// ── Menu ─────────────────────────────────────────────────────────────────
|
||
|
||
public function register_menu(): void {
|
||
add_menu_page(
|
||
'WooCow',
|
||
'WooCow',
|
||
'manage_woocommerce',
|
||
'woocow',
|
||
[ $this, 'page_dashboard' ],
|
||
'dashicons-email-alt2',
|
||
56
|
||
);
|
||
add_submenu_page( 'woocow', 'Dashboard', 'Dashboard', 'manage_woocommerce', 'woocow', [ $this, 'page_dashboard' ] );
|
||
add_submenu_page( 'woocow', 'Servers', 'Servers', 'manage_woocommerce', 'woocow-servers', [ $this, 'page_servers' ] );
|
||
add_submenu_page( 'woocow', 'Assignments','Assignments', 'manage_woocommerce', 'woocow-assignments', [ $this, 'page_assignments' ] );
|
||
add_submenu_page( 'woocow', 'Mailboxes', 'Mailboxes', 'manage_woocommerce', 'woocow-mailboxes', [ $this, 'page_mailboxes' ] );
|
||
}
|
||
|
||
public function enqueue_assets( string $hook ): void {
|
||
if ( strpos( $hook, 'woocow' ) === false ) {
|
||
return;
|
||
}
|
||
wp_enqueue_style( 'woocow-admin', WOOCOW_PLUGIN_URL . 'assets/css/woocow.css', [], WOOCOW_VERSION );
|
||
wp_enqueue_script( 'woocow-admin', WOOCOW_PLUGIN_URL . 'assets/js/woocow-admin.js', [ 'jquery' ], WOOCOW_VERSION, true );
|
||
wp_localize_script( 'woocow-admin', 'woocow', [
|
||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||
'nonce' => wp_create_nonce( 'woocow_admin' ),
|
||
] );
|
||
}
|
||
|
||
// ── Page: Dashboard ──────────────────────────────────────────────────────
|
||
|
||
public function page_dashboard(): void {
|
||
global $wpdb;
|
||
$servers = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}woocow_servers WHERE active=1" );
|
||
$assignments = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}woocow_assignments" );
|
||
$customers = (int) $wpdb->get_var( "SELECT COUNT(DISTINCT customer_id) FROM {$wpdb->prefix}woocow_assignments" );
|
||
?>
|
||
<div class="wrap woocow-wrap">
|
||
<h1>WooCow <span class="woocow-version">v<?php echo esc_html( WOOCOW_VERSION ); ?></span></h1>
|
||
<div class="woocow-dashboard-cards">
|
||
<div class="woocow-card">
|
||
<span class="woocow-card-number"><?php echo esc_html( $servers ); ?></span>
|
||
<span class="woocow-card-label">Active Servers</span>
|
||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=woocow-servers' ) ); ?>" class="button button-secondary">Manage</a>
|
||
</div>
|
||
<div class="woocow-card">
|
||
<span class="woocow-card-number"><?php echo esc_html( $customers ); ?></span>
|
||
<span class="woocow-card-label">Customers with Email</span>
|
||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=woocow-assignments' ) ); ?>" class="button button-secondary">Manage</a>
|
||
</div>
|
||
<div class="woocow-card">
|
||
<span class="woocow-card-number"><?php echo esc_html( $assignments ); ?></span>
|
||
<span class="woocow-card-label">Domain Assignments</span>
|
||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=woocow-mailboxes' ) ); ?>" class="button button-secondary">View Mailboxes</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
// ── Page: Servers ────────────────────────────────────────────────────────
|
||
|
||
public function page_servers(): void {
|
||
?>
|
||
<div class="wrap woocow-wrap">
|
||
<h1>WooCow – Servers</h1>
|
||
<p>Add your Mailcow server instances here. The API key must be a read-write key from <strong>Configuration → Access → Edit administrator details → API</strong>.</p>
|
||
|
||
<div class="woocow-toolbar">
|
||
<button class="button button-primary" id="wc-add-server">+ Add Server</button>
|
||
</div>
|
||
<div id="wc-notices"></div>
|
||
|
||
<!-- Add / Edit form (hidden by default) -->
|
||
<div id="wc-server-form" class="woocow-card woocow-form" style="display:none">
|
||
<h3 id="wc-server-form-title">Add Server</h3>
|
||
<input type="hidden" id="wc-server-id" value="">
|
||
<table class="form-table">
|
||
<tr>
|
||
<th><label for="wc-server-name">Name</label></th>
|
||
<td><input type="text" id="wc-server-name" class="regular-text" placeholder="My Mailcow Server"></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-server-url">Server URL</label></th>
|
||
<td><input type="url" id="wc-server-url" class="regular-text" placeholder="https://mail.example.com"></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-server-key">API Key</label></th>
|
||
<td><input type="text" id="wc-server-key" class="regular-text" placeholder="Your read-write API key"></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-server-active">Active</label></th>
|
||
<td><input type="checkbox" id="wc-server-active" checked></td>
|
||
</tr>
|
||
</table>
|
||
<div class="woocow-form-actions">
|
||
<button class="button button-primary" id="wc-server-save">Save Server</button>
|
||
<button class="button" id="wc-server-test">Test Connection</button>
|
||
<button class="button" id="wc-server-cancel">Cancel</button>
|
||
<span id="wc-server-test-result"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Servers table -->
|
||
<div id="wc-servers-table-wrap">
|
||
<p id="wc-servers-loading">Loading servers…</p>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
// ── Page: Assignments ────────────────────────────────────────────────────
|
||
|
||
public function page_assignments(): void {
|
||
?>
|
||
<div class="wrap woocow-wrap">
|
||
<h1>WooCow – Domain Assignments</h1>
|
||
<p>Assign one or more Mailcow domains to a WooCommerce customer. The customer can then manage mailboxes for those domains from <em>My Account → Email Hosting</em>.</p>
|
||
|
||
<div class="woocow-card woocow-form" id="wc-assign-form">
|
||
<h3>Assign Domain to Customer</h3>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th><label>Customer</label></th>
|
||
<td>
|
||
<input type="text" id="wc-cust-search" class="regular-text" placeholder="Search by name or email…" autocomplete="off">
|
||
<div id="wc-cust-results" class="woocow-autocomplete"></div>
|
||
<input type="hidden" id="wc-cust-id">
|
||
<span id="wc-cust-selected" class="woocow-selected-badge"></span>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-assign-server">Server</label></th>
|
||
<td>
|
||
<select id="wc-assign-server" class="regular-text">
|
||
<option value="">— Select a server —</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr id="wc-domain-row" style="display:none">
|
||
<th><label for="wc-assign-domain">Domain</label></th>
|
||
<td>
|
||
<select id="wc-assign-domain" class="regular-text">
|
||
<option value="">— Loading domains —</option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
<div class="woocow-form-actions">
|
||
<button class="button button-primary" id="wc-assign-save">Assign Domain</button>
|
||
</div>
|
||
<div id="wc-assign-notice"></div>
|
||
</div>
|
||
|
||
<h2>Current Assignments</h2>
|
||
<div id="wc-assignments-loading">Loading…</div>
|
||
<div id="wc-assignments-table-wrap"></div>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
// ── Page: Mailboxes ──────────────────────────────────────────────────────
|
||
|
||
public function page_mailboxes(): void {
|
||
global $wpdb;
|
||
$servers = $wpdb->get_results( "SELECT id, name FROM {$wpdb->prefix}woocow_servers WHERE active=1 ORDER BY name" );
|
||
?>
|
||
<div class="wrap woocow-wrap">
|
||
<h1>WooCow – Mailboxes</h1>
|
||
|
||
<div class="woocow-toolbar woocow-flex">
|
||
<select id="wc-mb-server" class="regular-text">
|
||
<option value="">— Select server —</option>
|
||
<?php foreach ( $servers as $s ) : ?>
|
||
<option value="<?php echo esc_attr( $s->id ); ?>"><?php echo esc_html( $s->name ); ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<select id="wc-mb-domain" class="regular-text" style="display:none">
|
||
<option value="">— Select domain —</option>
|
||
</select>
|
||
<button class="button" id="wc-mb-load" disabled>Load Mailboxes</button>
|
||
<button class="button button-primary" id="wc-mb-create" style="display:none">+ Create Mailbox</button>
|
||
</div>
|
||
|
||
<div id="wc-mb-notices"></div>
|
||
<div id="wc-mb-table-wrap"></div>
|
||
|
||
<!-- Edit Mailbox Modal (password / quota) -->
|
||
<div id="wc-mb-edit-modal" class="woocow-modal" style="display:none">
|
||
<div class="woocow-modal-box">
|
||
<h3 id="wc-mb-edit-title">Edit Mailbox</h3>
|
||
<p id="wc-mb-edit-subtitle" class="woocow-modal-subtitle"></p>
|
||
|
||
<div id="wc-mb-edit-pw-section" style="display:none">
|
||
<table class="form-table">
|
||
<tr>
|
||
<th><label for="wc-mb-edit-pass">New Password</label></th>
|
||
<td><input type="password" id="wc-mb-edit-pass" class="regular-text" autocomplete="new-password"></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-mb-edit-pass2">Confirm Password</label></th>
|
||
<td><input type="password" id="wc-mb-edit-pass2" class="regular-text" autocomplete="new-password"></td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div id="wc-mb-edit-quota-section" style="display:none">
|
||
<table class="form-table">
|
||
<tr>
|
||
<th><label for="wc-mb-edit-quota">Max Quota (MB)</label></th>
|
||
<td>
|
||
<input type="number" id="wc-mb-edit-quota" class="small-text" min="1" step="1">
|
||
<p class="description">Current usage is shown in the mailbox list. 1024 MB = 1 GB.</p>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="woocow-modal-actions">
|
||
<button class="button button-primary" id="wc-mb-edit-save">Save</button>
|
||
<button class="button" id="wc-mb-edit-cancel">Cancel</button>
|
||
<span id="wc-mb-edit-notice"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Create Mailbox Modal -->
|
||
<div id="wc-mb-modal" class="woocow-modal" style="display:none">
|
||
<div class="woocow-modal-box">
|
||
<h3>Create Mailbox</h3>
|
||
<table class="form-table">
|
||
<tr>
|
||
<th><label for="wc-mb-local">Local Part</label></th>
|
||
<td>
|
||
<div class="woocow-flex-inline">
|
||
<input type="text" id="wc-mb-local" placeholder="user">
|
||
<span class="woocow-at">@</span>
|
||
<span id="wc-mb-domain-label" class="woocow-domain-label"></span>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-mb-fullname">Full Name</label></th>
|
||
<td><input type="text" id="wc-mb-fullname" class="regular-text" placeholder="Jane Doe"></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-mb-pass">Password</label></th>
|
||
<td><input type="password" id="wc-mb-pass" class="regular-text"></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-mb-pass2">Confirm Password</label></th>
|
||
<td><input type="password" id="wc-mb-pass2" class="regular-text"></td>
|
||
</tr>
|
||
<tr>
|
||
<th><label for="wc-mb-quota">Quota (MB)</label></th>
|
||
<td><input type="number" id="wc-mb-quota" value="1024" min="1"></td>
|
||
</tr>
|
||
</table>
|
||
<div class="woocow-modal-actions">
|
||
<button class="button button-primary" id="wc-mb-modal-save">Create</button>
|
||
<button class="button" id="wc-mb-modal-cancel">Cancel</button>
|
||
<span id="wc-mb-modal-notice"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
// ── AJAX helpers ─────────────────────────────────────────────────────────
|
||
|
||
private function verify(): void {
|
||
check_ajax_referer( 'woocow_admin', 'nonce' );
|
||
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||
wp_send_json_error( 'Insufficient permissions.', 403 );
|
||
}
|
||
}
|
||
|
||
private function get_server( int $id ): ?object {
|
||
global $wpdb;
|
||
return $wpdb->get_row( $wpdb->prepare(
|
||
"SELECT * FROM {$wpdb->prefix}woocow_servers WHERE id = %d",
|
||
$id
|
||
) );
|
||
}
|
||
|
||
private function json_ok( $data = null ): void {
|
||
wp_send_json_success( $data );
|
||
}
|
||
|
||
private function json_err( string $msg ): void {
|
||
wp_send_json_error( $msg );
|
||
}
|
||
|
||
// ── AJAX: Servers ─────────────────────────────────────────────────────────
|
||
|
||
public function ajax_woocow_servers_list(): void {
|
||
$this->verify();
|
||
global $wpdb;
|
||
$rows = $wpdb->get_results( "SELECT id, name, url, active, created_at FROM {$wpdb->prefix}woocow_servers ORDER BY name" );
|
||
$this->json_ok( $rows );
|
||
}
|
||
|
||
public function ajax_woocow_server_save(): void {
|
||
$this->verify();
|
||
global $wpdb;
|
||
|
||
$id = absint( $_POST['id'] ?? 0 );
|
||
$name = sanitize_text_field( $_POST['name'] ?? '' );
|
||
$url = esc_url_raw( $_POST['url'] ?? '' );
|
||
$key = sanitize_text_field( $_POST['api_key'] ?? '' );
|
||
$active = absint( $_POST['active'] ?? 1 );
|
||
|
||
if ( ! $name || ! $url || ! $key ) {
|
||
$this->json_err( 'Name, URL, and API key are required.' );
|
||
}
|
||
|
||
$data = compact( 'name', 'url', 'active' ) + [ 'api_key' => $key ];
|
||
|
||
if ( $id ) {
|
||
$wpdb->update( "{$wpdb->prefix}woocow_servers", $data, [ 'id' => $id ] );
|
||
$this->json_ok( [ 'id' => $id ] );
|
||
} else {
|
||
$wpdb->insert( "{$wpdb->prefix}woocow_servers", $data );
|
||
$this->json_ok( [ 'id' => $wpdb->insert_id ] );
|
||
}
|
||
}
|
||
|
||
public function ajax_woocow_server_delete(): void {
|
||
$this->verify();
|
||
global $wpdb;
|
||
$id = absint( $_POST['id'] ?? 0 );
|
||
$wpdb->delete( "{$wpdb->prefix}woocow_servers", [ 'id' => $id ] );
|
||
$wpdb->delete( "{$wpdb->prefix}woocow_assignments", [ 'server_id' => $id ] );
|
||
$this->json_ok();
|
||
}
|
||
|
||
public function ajax_woocow_server_test(): void {
|
||
$this->verify();
|
||
|
||
$id = absint( $_POST['id'] ?? 0 );
|
||
|
||
// Allow testing before saving (pass url+key directly)
|
||
if ( $id ) {
|
||
$server = $this->get_server( $id );
|
||
if ( ! $server ) {
|
||
$this->json_err( 'Server not found.' );
|
||
}
|
||
$api = WooCow_API::from_server( $server );
|
||
} else {
|
||
$url = esc_url_raw( $_POST['url'] ?? '' );
|
||
$key = sanitize_text_field( $_POST['api_key'] ?? '' );
|
||
if ( ! $url || ! $key ) {
|
||
$this->json_err( 'URL and API key required.' );
|
||
}
|
||
$api = new WooCow_API( $url, $key );
|
||
}
|
||
|
||
$result = $api->test_connection();
|
||
if ( $result['success'] ) {
|
||
$version = $result['data']['version'] ?? $result['data'][0]['version'] ?? 'unknown';
|
||
$this->json_ok( [ 'version' => $version ] );
|
||
} else {
|
||
$this->json_err( $result['error'] ?? 'Connection failed.' );
|
||
}
|
||
}
|
||
|
||
public function ajax_woocow_server_domains(): void {
|
||
$this->verify();
|
||
$id = absint( $_POST['server_id'] ?? 0 );
|
||
$server = $this->get_server( $id );
|
||
if ( ! $server ) {
|
||
$this->json_err( 'Server not found.' );
|
||
}
|
||
$api = WooCow_API::from_server( $server );
|
||
$result = $api->get_domains();
|
||
if ( ! $result['success'] ) {
|
||
$this->json_err( $result['error'] ?? 'Failed to fetch domains.' );
|
||
}
|
||
$domains = array_map( fn( $d ) => [ 'domain' => $d['domain_name'], 'active' => $d['active'] ], (array) $result['data'] );
|
||
$this->json_ok( $domains );
|
||
}
|
||
|
||
// ── AJAX: Assignments ─────────────────────────────────────────────────────
|
||
|
||
public function ajax_woocow_assignments_list(): void {
|
||
$this->verify();
|
||
global $wpdb;
|
||
$rows = $wpdb->get_results( "
|
||
SELECT a.id, a.customer_id, a.domain, a.created_at,
|
||
s.name AS server_name, s.url AS server_url,
|
||
u.display_name, u.user_email
|
||
FROM {$wpdb->prefix}woocow_assignments a
|
||
JOIN {$wpdb->prefix}woocow_servers s ON s.id = a.server_id
|
||
JOIN {$wpdb->users} u ON u.ID = a.customer_id
|
||
ORDER BY u.display_name, a.domain
|
||
" );
|
||
$this->json_ok( $rows );
|
||
}
|
||
|
||
public function ajax_woocow_assignment_save(): void {
|
||
$this->verify();
|
||
global $wpdb;
|
||
|
||
$customer_id = absint( $_POST['customer_id'] ?? 0 );
|
||
$server_id = absint( $_POST['server_id'] ?? 0 );
|
||
$domain = sanitize_text_field( $_POST['domain'] ?? '' );
|
||
|
||
if ( ! $customer_id || ! $server_id || ! $domain ) {
|
||
$this->json_err( 'Customer, server, and domain are all required.' );
|
||
}
|
||
|
||
$existing = $wpdb->get_var( $wpdb->prepare(
|
||
"SELECT id FROM {$wpdb->prefix}woocow_assignments WHERE customer_id=%d AND domain=%s",
|
||
$customer_id, $domain
|
||
) );
|
||
if ( $existing ) {
|
||
$this->json_err( 'This domain is already assigned to this customer.' );
|
||
}
|
||
|
||
$wpdb->insert( "{$wpdb->prefix}woocow_assignments", compact( 'customer_id', 'server_id', 'domain' ) );
|
||
$this->json_ok( [ 'id' => $wpdb->insert_id ] );
|
||
}
|
||
|
||
public function ajax_woocow_assignment_delete(): void {
|
||
$this->verify();
|
||
global $wpdb;
|
||
$id = absint( $_POST['id'] ?? 0 );
|
||
$wpdb->delete( "{$wpdb->prefix}woocow_assignments", [ 'id' => $id ] );
|
||
$this->json_ok();
|
||
}
|
||
|
||
// ── AJAX: Customer search ─────────────────────────────────────────────────
|
||
|
||
public function ajax_woocow_customers_search(): void {
|
||
$this->verify();
|
||
|
||
$term = sanitize_text_field( $_POST['term'] ?? '' );
|
||
if ( strlen( $term ) < 2 ) {
|
||
$this->json_ok( [] );
|
||
}
|
||
|
||
$users = get_users( [
|
||
'search' => '*' . $term . '*',
|
||
'search_columns' => [ 'user_login', 'user_email', 'display_name' ],
|
||
'role__in' => [ 'customer', 'subscriber', 'administrator', 'shop_manager' ],
|
||
'number' => 15,
|
||
] );
|
||
|
||
$out = array_map( fn( $u ) => [
|
||
'id' => $u->ID,
|
||
'label' => sprintf( '%s (%s)', $u->display_name, $u->user_email ),
|
||
], $users );
|
||
|
||
$this->json_ok( $out );
|
||
}
|
||
|
||
// ── AJAX: Admin Mailboxes ─────────────────────────────────────────────────
|
||
|
||
public function ajax_woocow_admin_mailboxes(): void {
|
||
$this->verify();
|
||
|
||
$server_id = absint( $_POST['server_id'] ?? 0 );
|
||
$domain = sanitize_text_field( $_POST['domain'] ?? '' );
|
||
|
||
$server = $this->get_server( $server_id );
|
||
if ( ! $server ) {
|
||
$this->json_err( 'Server not found.' );
|
||
}
|
||
|
||
$api = WooCow_API::from_server( $server );
|
||
|
||
$result = $domain
|
||
? $api->get_domain_mailboxes( $domain )
|
||
: $api->get_all_mailboxes();
|
||
|
||
if ( ! $result['success'] ) {
|
||
$this->json_err( $result['error'] ?? 'Failed to fetch mailboxes.' );
|
||
}
|
||
|
||
$this->json_ok( [
|
||
'mailboxes' => $result['data'] ?? [],
|
||
'webmail_url' => $api->get_webmail_url(),
|
||
] );
|
||
}
|
||
|
||
public function ajax_woocow_admin_mailbox_create(): void {
|
||
$this->verify();
|
||
|
||
$server_id = absint( $_POST['server_id'] ?? 0 );
|
||
$domain = sanitize_text_field( $_POST['domain'] ?? '' );
|
||
$local_part = sanitize_text_field( $_POST['local_part'] ?? '' );
|
||
$name = sanitize_text_field( $_POST['name'] ?? '' );
|
||
$password = $_POST['password'] ?? '';
|
||
$password2 = $_POST['password2'] ?? '';
|
||
$quota = absint( $_POST['quota'] ?? 1024 );
|
||
|
||
if ( ! $domain || ! $local_part || ! $password ) {
|
||
$this->json_err( 'Domain, local part, and password are required.' );
|
||
}
|
||
if ( $password !== $password2 ) {
|
||
$this->json_err( 'Passwords do not match.' );
|
||
}
|
||
|
||
$server = $this->get_server( $server_id );
|
||
if ( ! $server ) {
|
||
$this->json_err( 'Server not found.' );
|
||
}
|
||
|
||
$api = WooCow_API::from_server( $server );
|
||
$result = $api->create_mailbox( [
|
||
'local_part' => $local_part,
|
||
'domain' => $domain,
|
||
'name' => $name ?: $local_part,
|
||
'password' => $password,
|
||
'password2' => $password2,
|
||
'quota' => $quota,
|
||
'active' => 1,
|
||
'force_pw_update' => 0,
|
||
'tls_enforce_in' => 0,
|
||
'tls_enforce_out' => 0,
|
||
] );
|
||
|
||
if ( ! $result['success'] ) {
|
||
$this->json_err( $result['error'] ?? 'Failed to create mailbox.' );
|
||
}
|
||
|
||
$this->json_ok( [ 'email' => $local_part . '@' . $domain ] );
|
||
}
|
||
|
||
public function ajax_woocow_admin_mailbox_delete(): void {
|
||
$this->verify();
|
||
|
||
$server_id = absint( $_POST['server_id'] ?? 0 );
|
||
$email = sanitize_email( $_POST['email'] ?? '' );
|
||
|
||
$server = $this->get_server( $server_id );
|
||
if ( ! $server ) {
|
||
$this->json_err( 'Server not found.' );
|
||
}
|
||
|
||
$api = WooCow_API::from_server( $server );
|
||
$result = $api->delete_mailbox( $email );
|
||
|
||
if ( ! $result['success'] ) {
|
||
$this->json_err( $result['error'] ?? 'Failed to delete mailbox.' );
|
||
}
|
||
|
||
$this->json_ok();
|
||
}
|
||
|
||
public function ajax_woocow_admin_mailbox_edit(): void {
|
||
$this->verify();
|
||
|
||
$server_id = absint( $_POST['server_id'] ?? 0 );
|
||
$email = sanitize_email( $_POST['email'] ?? '' );
|
||
$type = sanitize_text_field( $_POST['type'] ?? '' ); // 'password' or 'quota'
|
||
|
||
if ( ! $email ) {
|
||
$this->json_err( 'Email address is required.' );
|
||
}
|
||
|
||
$server = $this->get_server( $server_id );
|
||
if ( ! $server ) {
|
||
$this->json_err( 'Server not found.' );
|
||
}
|
||
|
||
$api = WooCow_API::from_server( $server );
|
||
$attr = [];
|
||
|
||
if ( $type === 'password' ) {
|
||
$pass = $_POST['password'] ?? '';
|
||
$pass2 = $_POST['password2'] ?? '';
|
||
if ( ! $pass ) {
|
||
$this->json_err( 'Password cannot be empty.' );
|
||
}
|
||
if ( $pass !== $pass2 ) {
|
||
$this->json_err( 'Passwords do not match.' );
|
||
}
|
||
$attr = [ 'password' => $pass, 'password2' => $pass2 ];
|
||
|
||
} elseif ( $type === 'quota' ) {
|
||
$quota = absint( $_POST['quota'] ?? 0 );
|
||
if ( $quota < 1 ) {
|
||
$this->json_err( 'Quota must be at least 1 MB.' );
|
||
}
|
||
$attr = [ 'quota' => $quota ];
|
||
|
||
} else {
|
||
$this->json_err( 'Unknown edit type.' );
|
||
}
|
||
|
||
$result = $api->edit_mailbox( [ $email ], $attr );
|
||
|
||
if ( ! $result['success'] ) {
|
||
$this->json_err( $result['error'] ?? 'Failed to update mailbox.' );
|
||
}
|
||
|
||
$this->json_ok();
|
||
}
|
||
}
|