diff --git a/include/class.staff.php b/include/class.staff.php index 19bd71bf02da54c1ee1fd6c36ac356c32f0ca7aa..424b273e5c1eaa49e8725477cc8a5a88fedb778b 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -484,6 +484,8 @@ class Staff { if($vars['passwd1']) { $sql.=' ,change_passwd=0, passwdreset=NOW(), passwd='.db_input(Passwd::hash($vars['passwd1'])); + $info = array('password' => $vars['passwd1']); + Signal::send('auth.pwchange', $this, $info); $this->cancelResetTokens(); } @@ -702,20 +704,24 @@ class Staff { if (!($template = $tpl->getMsgTemplate('staff.pwreset'))) return new Error('Unable to retrieve password reset email template'); - $msg = $ost->replaceTemplateVariables($template->asArray(), array( + $vars = array( 'url' => $ost->getConfig()->getBaseUrl(), 'token' => $token, 'reset_link' => sprintf( "%s/scp/pwreset.php?token=%s", $ost->getConfig()->getBaseUrl(), $token), - )); + ); + $info = array('email' => $email, 'vars' => &$vars); + Signal::send('auth.pwreset.email', $this, $info); + + $msg = $ost->replaceTemplateVariables($template->asArray(), $vars); if(!($email=$cfg->getAlertEmail())) $email =$cfg->getDefaultEmail(); $_config = new Config('pwreset'); - $_config->set($token, $this->getId()); + $_config->set($vars['token'], $this->getId()); $email->send($this->getEmail(), $msg['subj'], $msg['body']); } diff --git a/scp/pwreset.php b/scp/pwreset.php index a8efb2f6ef86715463398d01143d907a0313e10e..5b7a20fa86ab35ce1c9e701107a8a9e8be93dee0 100644 --- a/scp/pwreset.php +++ b/scp/pwreset.php @@ -60,9 +60,11 @@ if($_POST) { elseif (!$staff->forcePasswdRest()) $msg = 'Unable to reset password'; else { + $info = array('page' => 'index.php'); + Signal::send('auth.pwreset.login', $staff, $info); Staff::_do_login($staff, $_POST['userid']); $_SESSION['_staff']['reset-token'] = $_POST['token']; - header('Location: index.php'); + header('Location: '.$info['page']); exit(); } break; diff --git a/setup/doc/api.md b/setup/doc/api.md index f40d7423c68730d2a20a2df58b36a6a1b2104a17..db9774af74848351f4c180abadeb66ef14af0576 100644 --- a/setup/doc/api.md +++ b/setup/doc/api.md @@ -17,6 +17,24 @@ API keys can be created and managed via the admin panel. Navigate to Manage special configuration is required to allow the API key to be used for the HTTP API. All API keys are valid for the HTTP API. +HTTP Access +----------- +Access to the HTTP API is restricted to valid API keys. An `X-API-Key` HTTP +header must be sent to indicate which API key is to be used with the +request. The API key must match the remote IP of the connected HTTP client. +The remote IP is checked as usual. If the osTicket server is sitting behind +a reverse proxy, the original IP of the client will be retrieved from the +`X-Forwarded-For` header, if provided by your proxy. + +Example: + + X-API-Key: BA00B76BAA30F62E1940B46CC1C3C73C + +Commandline Example with Curl: + + curl -d "{}" -H "X-API-Key: BA00B76BAA30F62E1940B46CC1C3C73C" + https://support.you.tld/api/tickets.json + Wrappers -------- diff --git a/setup/doc/signals.md b/setup/doc/signals.md new file mode 100644 index 0000000000000000000000000000000000000000..68c5e1513305ae8b615ece591c2fb8364099b9a8 --- /dev/null +++ b/setup/doc/signals.md @@ -0,0 +1,109 @@ +osTicket Signals API +==================== +osTicket uses a very simple publish and subscribe signal model to add +extensibility. To keep things simplistic between classes and to maintain +compatibility with PHP version 4, signals will not be explicitly defined or +registered. Instead, signals are connected to callbacks via a string signal +name. + +The system is proofed with a static inspection test which will ensure that +for every given Signal::connect() function call, somewhere else in the +codebase there exists a Signal::send() for the same-named signal. + +Publishing a signal +------------------- + $info = array('username'=>'blah'); + Signal::send('signal.name', $this, $info); + +All subscribers to the signal will be called in the order they connect()ed +to the signal. Subscribers do not have the opportunity to interrupt or +discontinue delivery of the signal to other subscribers. The $object +argument is required and should almost always be ($this). Its interpretation +is the object originating or sending the signal. It could also be +interpreted as the context of the signal. + +$data if sent should be a hash-array of data included with the signal event. +There is otherwise no definition for what should or could be included in the +$data array. The received data is received by reference and can be passed to +the callable by reference, if the callable is defined to receive it by +reference. Therefore, it is possible to propagate changes in the signal +handlers back to the originating context. + +Connecting to a signal +---------------------- + Signal::connect('signal.name', 'function', optional 'check_callable'); + +The subscribed function should receive two arguments and will have this +signature: + + function callback($object, $data); + +Where the $object argument is the object originating the signal, called the +context, and the $data is a hash-array of other information originating +from- and pertaining to the signal. + +The exact value of the $data argument is not defined. It is signal specific. +It should be a hash-array of data; however, no runtime checks are made to +ensure such an interface. + +Optionally, if $object is a class and is passed into the ::connect() method, +only instances of the named class or subclass will actually be connected to +the callable function. + +A predicate function, $check, can be used to filter calls to the signal +handler. The function will receive the signal data and should return true if +the signal handler should be called. + +Signals in osTicket +------------------- +**auth.login.succeeded** +Sent after a successful login is process for a user + +Context: +Object<StaffSession> - Staff object retrieved from the login credentials + +Parameters: +(none) + +**auth.login.failed** +Sent after an unsuccessful login is attempted by a user. + +Context: +null + +Arguments: + * **username**: *read-only* username submitted to the login form + * **passowrd**: *read-only* password submitted to the login form + +**auth.pwreset.email** +Sent just before an email is sent to the user with the password reset token + +Context: +Object<Staff> - Staff object who will receive the email + +Parameters: + * **email**: *read-only* email object used to send the email + * **vars**: (array) template variables used to render the password-reset + email template + +**auth.pwreset.login** +Sent just before processing the automatic login for the staff from the link +and token provided in the password-reset email. This signal is only sent if +the token presented is considered completely valid and the password for the +staff is forced to-be-changed. + +Context: +Object<Staff> - Staff being logged in from the reset token + +Parameters: + * **page**: Page / URL sent in the redirect to the user. In other words, + the next page the staff will see. + +**auth.pwchange** +Sent when the password for a user is changed + +Context: +Object<Staff> - Staff whose password is being changed + +Parameters: + * **password**: New password (clear-text) for the user