system.go raw

   1  package mailinabox
   2  
   3  import (
   4  	"context"
   5  	"fmt"
   6  	"net/http"
   7  	"net/url"
   8  	"strconv"
   9  	"strings"
  10  )
  11  
  12  // SystemStatus Represents a system status.
  13  type SystemStatus struct {
  14  	Type  string        `json:"type,omitempty"`
  15  	Text  string        `json:"text,omitempty"`
  16  	Extra []ExtraStatus `json:"extra,omitempty"`
  17  }
  18  
  19  // ExtraStatus Represents extra status.
  20  type ExtraStatus struct {
  21  	Monospace bool   `json:"monospace,omitempty"`
  22  	Text      string `json:"text,omitempty"`
  23  }
  24  
  25  // BackupStatus Represents a backup status.
  26  type BackupStatus struct {
  27  	Backups           []Backup `json:"backups,omitempty"`
  28  	UnmatchedFileSize int      `json:"unmatched_file_size,omitempty"`
  29  	Error             string   `json:"error,omitempty"`
  30  }
  31  
  32  // Backup Represents a backup.
  33  type Backup struct {
  34  	Date      string `json:"date,omitempty"`
  35  	DateDelta string `json:"date_delta,omitempty"`
  36  	DateStr   string `json:"date_str,omitempty"`
  37  	DeletedIn string `json:"deleted_in,omitempty"`
  38  	Full      bool   `json:"full,omitempty"`
  39  	Size      int    `json:"size,omitempty"`
  40  	Volumes   int    `json:"volumes,omitempty"`
  41  }
  42  
  43  // BackupConfig Represents a backup configuration.
  44  type BackupConfig struct {
  45  	EncPwFile           string `json:"enc_pw_file,omitempty"`
  46  	FileTargetDirectory string `json:"file_target_directory,omitempty"`
  47  	MinAgeInDays        int    `json:"min_age_in_days,omitempty"`
  48  	SSHPubKey           string `json:"ssh_pub_key,omitempty"`
  49  	Target              string `json:"target,omitempty"`
  50  	TargetUser          string `json:"target_user,omitempty"`
  51  	TargetPass          string `json:"target_pass,omitempty"`
  52  }
  53  
  54  // SystemService System API.
  55  // https://mailinabox.email/api-docs.html#tag/System
  56  type SystemService service
  57  
  58  // GetStatus Returns an array of statuses which can include headings.
  59  // https://mailinabox.email/api-docs.html#operation/getSystemStatus
  60  func (s *SystemService) GetStatus(ctx context.Context) ([]SystemStatus, error) {
  61  	endpoint := s.client.baseURL.JoinPath("admin", "system", "status")
  62  
  63  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), http.NoBody)
  64  	if err != nil {
  65  		return nil, fmt.Errorf("unable to create request: %w", err)
  66  	}
  67  
  68  	var results []SystemStatus
  69  
  70  	err = s.client.doJSON(req, &results)
  71  	if err != nil {
  72  		return nil, err
  73  	}
  74  
  75  	return results, nil
  76  }
  77  
  78  // GetVersion Returns installed Mail-in-a-Box version.
  79  // https://mailinabox.email/api-docs.html#operation/getSystemVersion
  80  func (s *SystemService) GetVersion(ctx context.Context) (string, error) {
  81  	endpoint := s.client.baseURL.JoinPath("admin", "system", "version")
  82  
  83  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), http.NoBody)
  84  	if err != nil {
  85  		return "", fmt.Errorf("unable to create request: %w", err)
  86  	}
  87  
  88  	resp, err := s.client.doPlain(req)
  89  	if err != nil {
  90  		return "", err
  91  	}
  92  
  93  	return strings.TrimSpace(string(resp)), nil
  94  }
  95  
  96  // GetUpstreamVersion Returns Mail-in-a-Box upstream version.
  97  // https://mailinabox.email/api-docs.html#operation/getSystemUpstreamVersion
  98  func (s *SystemService) GetUpstreamVersion(ctx context.Context) (string, error) {
  99  	endpoint := s.client.baseURL.JoinPath("admin", "system", "latest-upstream-version")
 100  
 101  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), http.NoBody)
 102  	if err != nil {
 103  		return "", fmt.Errorf("unable to create request: %w", err)
 104  	}
 105  
 106  	resp, err := s.client.doPlain(req)
 107  	if err != nil {
 108  		return "", err
 109  	}
 110  
 111  	return strings.TrimSpace(string(resp)), nil
 112  }
 113  
 114  // GetUpdates Returns system (apt) updates.
 115  // https://mailinabox.email/api-docs.html#operation/getSystemUpdates
 116  func (s *SystemService) GetUpdates(ctx context.Context) ([]string, error) {
 117  	endpoint := s.client.baseURL.JoinPath("admin", "system", "updates")
 118  
 119  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), http.NoBody)
 120  	if err != nil {
 121  		return nil, fmt.Errorf("unable to create request: %w", err)
 122  	}
 123  
 124  	resp, err := s.client.doPlain(req)
 125  	if err != nil {
 126  		return nil, err
 127  	}
 128  
 129  	updates := strings.Split(strings.TrimSpace(string(resp)), "\n")
 130  
 131  	return updates, nil
 132  }
 133  
 134  // UpdatePackages Updates system (apt) packages.
 135  // https://mailinabox.email/api-docs.html#operation/getSystemUpdates
 136  func (s *SystemService) UpdatePackages(ctx context.Context) (string, error) {
 137  	endpoint := s.client.baseURL.JoinPath("admin", "system", "update-packages")
 138  
 139  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), http.NoBody)
 140  	if err != nil {
 141  		return "", fmt.Errorf("unable to create request: %w", err)
 142  	}
 143  
 144  	resp, err := s.client.doPlain(req)
 145  	if err != nil {
 146  		return "", err
 147  	}
 148  
 149  	return strings.TrimSpace(string(resp)), nil
 150  }
 151  
 152  // GetPrivacyStatus Returns system privacy (new-version check) status.
 153  // https://mailinabox.email/api-docs.html#operation/getSystemPrivacyStatus
 154  func (s *SystemService) GetPrivacyStatus(ctx context.Context) (bool, error) {
 155  	endpoint := s.client.baseURL.JoinPath("admin", "system", "privacy")
 156  
 157  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), http.NoBody)
 158  	if err != nil {
 159  		return false, fmt.Errorf("unable to create request: %w", err)
 160  	}
 161  
 162  	var result bool
 163  
 164  	err = s.client.doJSON(req, &result)
 165  	if err != nil {
 166  		return false, err
 167  	}
 168  
 169  	return result, nil
 170  }
 171  
 172  // UpdatePrivacyStatus Updates system privacy (new-version checks).
 173  // - value: `private`: Disable new version checks
 174  // - value: `off`: Enable new version checks
 175  // https://mailinabox.email/api-docs.html#operation/updateSystemPrivacy
 176  func (s *SystemService) UpdatePrivacyStatus(ctx context.Context, value string) (string, error) {
 177  	endpoint := s.client.baseURL.JoinPath("admin", "system", "privacy")
 178  
 179  	data := url.Values{}
 180  	data.Set("value", value)
 181  
 182  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), strings.NewReader(data.Encode()))
 183  	if err != nil {
 184  		return "", fmt.Errorf("unable to create request: %w", err)
 185  	}
 186  
 187  	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
 188  
 189  	resp, err := s.client.doPlain(req)
 190  	if err != nil {
 191  		return "", err
 192  	}
 193  
 194  	return strings.TrimSpace(string(resp)), nil
 195  }
 196  
 197  // GetRebootStatus Returns the system reboot status.
 198  // https://mailinabox.email/api-docs.html#operation/getSystemRebootStatus
 199  func (s *SystemService) GetRebootStatus(ctx context.Context) (bool, error) {
 200  	endpoint := s.client.baseURL.JoinPath("admin", "system", "reboot")
 201  
 202  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), http.NoBody)
 203  	if err != nil {
 204  		return false, fmt.Errorf("unable to create request: %w", err)
 205  	}
 206  
 207  	var result bool
 208  
 209  	err = s.client.doJSON(req, &result)
 210  	if err != nil {
 211  		return false, err
 212  	}
 213  
 214  	return result, nil
 215  }
 216  
 217  // Reboot Reboots the system.
 218  // https://mailinabox.email/api-docs.html#operation/rebootSystem
 219  func (s *SystemService) Reboot(ctx context.Context) (string, error) {
 220  	endpoint := s.client.baseURL.JoinPath("admin", "system", "reboot")
 221  
 222  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), http.NoBody)
 223  	if err != nil {
 224  		return "", fmt.Errorf("unable to create request: %w", err)
 225  	}
 226  
 227  	resp, err := s.client.doPlain(req)
 228  	if err != nil {
 229  		return "", err
 230  	}
 231  
 232  	return strings.TrimSpace(string(resp)), nil
 233  }
 234  
 235  // GetBackupStatus Returns the system backup status.
 236  // https://mailinabox.email/api-docs.html#operation/getSystemBackupStatus
 237  func (s *SystemService) GetBackupStatus(ctx context.Context) (*BackupStatus, error) {
 238  	endpoint := s.client.baseURL.JoinPath("admin", "system", "backup", "status")
 239  
 240  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), http.NoBody)
 241  	if err != nil {
 242  		return nil, fmt.Errorf("unable to create request: %w", err)
 243  	}
 244  
 245  	var result BackupStatus
 246  
 247  	err = s.client.doJSON(req, &result)
 248  	if err != nil {
 249  		return nil, err
 250  	}
 251  
 252  	return &result, nil
 253  }
 254  
 255  // GetBackupConfig Returns the system backup config.
 256  // https://mailinabox.email/api-docs.html#operation/getSystemBackupConfig
 257  func (s *SystemService) GetBackupConfig(ctx context.Context) (*BackupConfig, error) {
 258  	endpoint := s.client.baseURL.JoinPath("admin", "system", "backup", "config")
 259  
 260  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), http.NoBody)
 261  	if err != nil {
 262  		return nil, fmt.Errorf("unable to create request: %w", err)
 263  	}
 264  
 265  	var result BackupConfig
 266  
 267  	err = s.client.doJSON(req, &result)
 268  	if err != nil {
 269  		return nil, err
 270  	}
 271  
 272  	return &result, nil
 273  }
 274  
 275  // UpdateBackupConfig Updates the system backup config.
 276  // https://mailinabox.email/api-docs.html#operation/updateSystemBackupConfig
 277  func (s *SystemService) UpdateBackupConfig(ctx context.Context, target, targetUser, targetPass string, minAge int) (string, error) {
 278  	endpoint := s.client.baseURL.JoinPath("admin", "system", "backup", "config")
 279  
 280  	data := url.Values{}
 281  	data.Set("target", target)
 282  	data.Set("targetUser", targetUser)
 283  	data.Set("targetPass", targetPass)
 284  	data.Set("minAge", strconv.Itoa(minAge))
 285  
 286  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), strings.NewReader(data.Encode()))
 287  	if err != nil {
 288  		return "", fmt.Errorf("unable to create request: %w", err)
 289  	}
 290  
 291  	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
 292  
 293  	resp, err := s.client.doPlain(req)
 294  	if err != nil {
 295  		return "", err
 296  	}
 297  
 298  	return strings.TrimSpace(string(resp)), nil
 299  }
 300