1: <?php
2: /**
3: * Copyright (C) Apis Networks, Inc - All Rights Reserved.
4: *
5: * Unauthorized copying of this file, via any medium, is
6: * strictly prohibited without consent. Any dissemination of
7: * material herein is prohibited.
8: *
9: * For licensing inquiries email <licensing@apisnetworks.com>
10: *
11: * Written by Matt Saladna <matt@apisnetworks.com>, July 2017
12: */
13:
14: class Diskquota_Module extends Module_Skeleton implements \Module\Skeleton\Contracts\Hookable
15: {
16: const DEPENDENCY_MAP = [
17: 'siteinfo',
18: ];
19:
20: const MIN_STORAGE_AMNESTY = QUOTA_STORAGE_WAIT;
21: // time in seconds between amnesty requests
22: const AMNESTY_DURATION = QUOTA_STORAGE_DURATION;
23: // 24 hours
24: const AMNESTY_MULTIPLIER = QUOTA_STORAGE_BOOST;
25: const AMNESTY_JOB_MARKER = 'amnesty';
26:
27: public $exportedFunctions = [
28: '*' => PRIVILEGE_SITE,
29: 'amnesty' => PRIVILEGE_SITE | PRIVILEGE_ADMIN
30: ];
31:
32: /**
33: * Request a temporary bump to account storage
34: *
35: * @return bool
36: * @see MIN_STORAGE_AMNESTY
37: */
38: public function amnesty(string $site = null): bool
39: {
40: if (posix_getuid() && !IS_CLI) {
41: return $this->query('diskquota_amnesty');
42: }
43:
44: $last = $this->getServiceValue('diskquota', 'amnesty');
45: $now = coalesce($_SERVER['REQUEST_TIME'], time());
46: if (!$site) {
47: $site = $this->site;
48: } else if ($site && !($this->permission_level && PRIVILEGE_SITE)) {
49: if (!($site = \Auth::get_site_id_from_anything($site))) {
50: return error("Unknown site identifier `%s'", $site);
51: }
52:
53: $site = "site" . $site;
54: }
55:
56: if (($this->permission_level & PRIVILEGE_SITE) && self::MIN_STORAGE_AMNESTY > ($now - $last)) {
57: $aday = self::MIN_STORAGE_AMNESTY / 86400;
58:
59: return error('storage amnesty may be requested once every %(period)d days, %(remaining)d days remaining', [
60: 'period' => $aday,
61: 'remaining' => $aday - ceil(($now - $last) / 86400)
62: ]);
63: }
64:
65: $ctx = \Auth::context(null, $site);
66: $storage = $ctx->getAccount()->conf['diskquota']['quota'];
67: $newstorage = $storage * self::AMNESTY_MULTIPLIER;
68: $acct = new Util_Account_Editor($ctx->getAccount(), $ctx);
69: $acct->setConfig('diskquota', 'quota', $newstorage)->setConfig('diskquota', 'amnesty', $now);
70: $ret = $acct->edit();
71: if ($ret !== true) {
72: Error_Reporter::report(var_export($ret, true));
73: return error('failed to set amnesty on account');
74: }
75: $acct->setConfig('diskquota', 'quota', $storage);
76: $cmd = $acct->getCommand();
77: $proc = new Util_Process_Schedule('+' . self::AMNESTY_DURATION . ' seconds');
78: if (($this->permission_level & PRIVILEGE_ADMIN)) {
79: if ($id = $proc->preempted(self::AMNESTY_JOB_MARKER, $ctx)) {
80: // @xxx potential unbounded storage growth
81: $proc->cancelJob($id);
82: // @todo report duplicate request
83: }
84:
85: }
86: $proc->setID(self::AMNESTY_JOB_MARKER, $ctx);
87: $ret = $proc->run($cmd);
88:
89: // @todo extract to event
90: $msg = sprintf("Domain: %s\r\nSite: %d\r\nServer: %s", $this->domain, $this->site_id, SERVER_NAME_SHORT);
91: Mail::send(Crm_Module::COPY_ADMIN, 'Amnesty Request', $msg);
92:
93: return $ret['success'];
94: }
95:
96: /**
97: * Account is under amnesty
98: *
99: * @return bool
100: */
101: public function amnesty_active(): bool
102: {
103: $time = $_SERVER['REQUEST_TIME'] ?? time();
104: $amnesty = $this->getServiceValue('diskquota', 'amnesty');
105: if (!$amnesty) {
106: return false;
107: }
108:
109: return ($time - $amnesty) <= self::AMNESTY_DURATION;
110: }
111:
112: public function _edit()
113: {
114: // TODO: Implement _edit() method.
115: }
116:
117: public function _delete()
118: {
119: // TODO: Implement _delete() method.
120: }
121:
122: public function _edit_user(string $userold, string $usernew, array $oldpwd)
123: {
124: // TODO: Implement _edit_user() method.
125: }
126:
127: public function _verify_conf(\Opcenter\Service\ConfigurationContext $ctx): bool
128: {
129: return true;
130: }
131:
132: public function _create()
133: {
134: // TODO: Implement _create() method.
135: }
136:
137: public function _create_user(string $user)
138: {
139: // TODO: Implement _create_user() method.
140: }
141:
142: public function _delete_user(string $user)
143: {
144: // TODO: Implement _delete_user() method.
145: }
146: }