private static function pushNotification($userKey, $message, $title = null, $url = null, $urltitle = null) { Logger::getLogger('MESSAGING')->debug('Pushover[pushNotification' . ']; $userKey=[' . $userKey . ']; $message=[' . $message . ']; $title=[' . $title . ']; $url=[' . $url . ']; $urltitle=[' . $urltitle . ']'); $notification = new Pushover(); $token = Config::get('applicationToken', 'msg_pushover'); if (is_null($token)) { throw new Exception("Pushover - Application token not specified", 500); } if (is_null($userKey)) { throw new Exception("Pushover - User key not specified", 500); } $notification->setToken($token); $notification->setUser($userKey); $notification->setMessage($message); if (!is_null($title)) { $notification->setTitle($title); } $notification->setHtml(1); $notification->setUrl($url); $notification->setUrlTitle($urltitle); if (!$notification->send()) { Logger::getUserLogger()->error("Pushover - Error in sending a notification to '{$userKey}'"); } else { Logger::getUserLogger()->notice("Pushover message sent."); } }
/** * Constructor of Session class * private to prevent any outside instantiation of this object */ private function __construct() { $this->logger = Logger::getLogger('FW'); $this->database = Database::singleton(); $conceptSession = Concept::getConceptByLabel('SESSION'); // Also checks if 'SESSION' is defined as concept in Ampersand script $this->id = session_id(); $this->sessionAtom = new Atom($this->id, $conceptSession); $this->logger->debug("Session id: {$this->id}"); // Remove expired Ampersand sessions from __SessionTimeout__ and all concept tables and relations where it appears. $expiredSessionsAtoms = array_column((array) $this->database->Exe("SELECT SESSION FROM `__SessionTimeout__` WHERE `lastAccess` < " . (time() - Config::get('sessionExpirationTime'))), 'SESSION'); foreach ($expiredSessionsAtoms as $expiredSessionAtom) { if ($expiredSessionAtom == $this->id) { // Notify user that session is expired when login functionality is enabled if (Config::get('loginEnabled')) { Logger::getUserLogger()->warning("Your session has expired, please login again"); } // 440 Login Timeout -> is redirected by frontend to login page } $this->destroyAmpersandSession($expiredSessionAtom); } // Create a new Ampersand session atom if not yet in SESSION table (browser started a new session or Ampersand session was expired) $sessionAtom = new Atom($this->id, $conceptSession); if (!$sessionAtom->atomExists()) { $sessionAtom->addAtom(); $this->database->commitTransaction(); //TODO: ook door Database->closeTransaction() laten doen, maar die verwijst terug naar Session class voor de checkrules. Oneindige loop } $this->database->Exe("INSERT INTO `__SessionTimeout__` (`SESSION`,`lastAccess`) VALUES ('" . $this->id . "', '" . time() . "') ON DUPLICATE KEY UPDATE `lastAccess` = '" . time() . "'"); // Add public interfaces $this->accessibleInterfaces = InterfaceObject::getPublicInterfaces(); }
private static function pushNotification($userKey, $message, $title = null, $url = null, $urltitle = null) { Logger::getLogger('MESSAGING')->debug('Pushalot - $userKey=[' . $userKey . ']; $message=[' . $message . ']; $title=[' . $title . ']; $url=[' . $url . ']; $urltitle=[' . $urltitle . ']'); if (is_null($userKey)) { throw new Exception("Pushalot - User/API key not specified", 500); } $notification = new Pushalot($userKey); //$pushalot->setProxy('http://localhost:12345','user:pass'); $success = $notification->sendMessage(array('Title' => $title, 'Body' => $message, 'IsImportant' => true, 'IsSilent' => false, 'Image' => 'http://wiki.tarski.nl/skins/common/images/AmpersandLogo.png', 'Source' => 'Ampersand prototype')); if (!$success) { Logger::getUserLogger()->error("Pushalot error '{$notification->getError}()' sending notification to '{$userKey}'"); } else { Logger::getUserLogger()->notice("Pushalot message sent."); } }
function datimeGT($gtRelation, $DateConcept, $srcAtom, $tgtAtom) { Logger::getLogger('EXECENGINE')->debug("datimeGT({$gtRelation},{$DateConcept},{$srcAtom},{$tgtAtom})"); if (($dt1 = strtotime($srcAtom)) === false) { Logger::getUserLogger()->error("datimeGT: Illegal date {$dt1} specified in srcAtom (3rd arg): {$srcAtom}"); } if (($dt2 = strtotime($tgtAtom)) === false) { Logger::getUserLogger()->error("datimeGT: Illegal date {$dt2} specified in tgtAtom (4th arg): {$tgtAtom}"); } if ($dt1 == $dt2) { return; } if ($dt1 > $dt2) { InsPair($gtRelation, $DateConcept, $srcAtom, $DateConcept, $tgtAtom); } else { InsPair($gtRelation, $DateConcept, $tgtAtom, $DateConcept, $srcAtom); } }
/** * * @param boolean $cacheConjuncts * @return Violation[] */ private function checkRule($cacheConjuncts = true) { $this->logger->debug("Checking rule '{$this->id}'"); try { $violations = array(); // Evaluate conjuncts of this rule foreach ($this->conjuncts as $conjunct) { foreach ($conjunct->evaluateConjunct($cacheConjuncts) as $violation) { $violations[] = new Violation($this, $violation['src'], $violation['tgt']); } } // If no violations => rule holds if (empty($violations)) { $this->logger->debug("Rule '{$this->id}' holds"); } // Cache violations when requested if ($cacheConjuncts) { $this->violations = $violations; } return $violations; } catch (Exception $e) { Logger::getUserLogger()->error("While evaluating rule '{$this->id}': {$e->getMessage()}"); } }
/** * Function to create a new Atom at the given interface. * @param array $data * @param array $options * @throws Exception * @return mixed */ public function create($data, $options = array()) { $this->logger->debug("create() called on {$this->path}"); // CRUD check if (!$this->crudC) { throw new Exception("Create not allowed for '{$this->path}'", 405); } if (!$this->tgtConcept->isObject) { throw new Exception("Cannot create non-object '{$this->tgtConcept}' in '{$this->path}'. Use PATCH add operation instead", 405); } if ($this->isRef()) { throw new Exception("Cannot create on reference interface in '{$this->path}'. See #498", 501); } // Handle options if (isset($options['requestType'])) { $this->database->setRequestType($options['requestType']); } // Perform create $newAtom = $this->tgtConcept->createNewAtom(); // Special case for CREATE in I[Concept] interfaces if ($this->srcAtom->id === '_NEW') { $this->srcAtom->setId($newAtom->id); $this->path = str_replace('_NEW', $newAtom->getJsonRepresentation(), $this->path); } // If interface expression is a relation, also add tuple(this, newAtom) in this relation if ($this->relation) { $this->relation()->addLink($this->srcAtom, $newAtom, $this->relationIsFlipped); } else { $newAtom->addAtom(); } // Walk to new atom $newAtom = $this->atom($newAtom->id); // Set requested state (using patches) $patches = is_array($data) ? $data['patches'] : array(); $newAtom->doPatches($patches); // Special case for file upload. TODO: make extension with hooks if ($this->tgtConcept->isFileObject()) { $conceptFilePath = Concept::getConceptByLabel('FilePath'); $conceptFileName = Concept::getConceptByLabel('FileName'); if (is_uploaded_file($_FILES['file']['tmp_name'])) { $tmp_name = $_FILES['file']['tmp_name']; $new_name = time() . '_' . $_FILES['file']['name']; $absolutePath = Config::get('absolutePath') . Config::get('uploadPath') . $new_name; $relativePath = Config::get('uploadPath') . $new_name; $result = move_uploaded_file($tmp_name, $absolutePath); if ($result) { Logger::getUserLogger()->notice("File '{$new_name}' uploaded"); } else { throw new Exception("Error in file upload", 500); } // Populate filePath and originalFileName relations in database $relFilePath = Relation::getRelation('filePath', $newAtom->concept, $conceptFilePath); $relOriginalFileName = Relation::getRelation('originalFileName', $newAtom->concept, $conceptFileName); $relFilePath->addLink($newAtom, new Atom($relativePath, $conceptFilePath)); $relOriginalFileName->addLink($newAtom, new Atom($_FILES['file']['name'], $conceptFileName)); } else { throw new Exception("No file uploaded", 500); } } // Close transaction $this->database->closeTransaction($newAtom->concept . ' created', null, $newAtom); // temp store content of $newAtom (also when not crudR) // Return atom content (can be null) return $newAtom->getStoredContent(); }
global $app; // Path to API is 'api/v1/excelimport/import' $app->post('/excelimport/import', function () use($app) { $session = Session::singleton(); $roleIds = $app->request->params('roleIds'); $session->activateRoles($roleIds); // Check sessionRoles if allowedRolesForExcelImport is specified $allowedRoles = Config::get('allowedRolesForExcelImport', 'excelImport'); if (!is_null($allowedRoles)) { $ok = false; foreach ($session->getSessionRoles() as $role) { if (in_array($role->label, $allowedRoles)) { $ok = true; } } if (!$ok) { throw new Exception("You do not have access to import excel files", 401); } } if (is_uploaded_file($_FILES['file']['tmp_name'])) { // Parse: $parser = new ExcelImport(); $parser->ParseFile($_FILES['file']['tmp_name']); Database::singleton()->closeTransaction("File {$_FILES['file']['tmp_name']} imported successfully", true); unlink($_FILES['file']['tmp_name']); } else { Logger::getUserLogger()->error("No file uploaded"); } $result = array('notifications' => Notifications::getAll(), 'files' => $_FILES); print json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); });
public static function run($allRules = false) { $database = Database::singleton(); $logger = Logger::getLogger('EXECENGINE'); $logger->info("ExecEngine run started"); // Load the execEngine functions (security hazard :P) $files = getDirectoryList(__DIR__ . '/functions'); foreach ($files as $file) { if (substr($file, -3) !== 'php') { continue; } require_once $path = __DIR__ . '/functions/' . $file; $logger->debug("Included file: {$path}"); } self::$roleName = Config::get('execEngineRoleName', 'execEngine'); try { $role = Role::getRoleByName(self::$roleName); } catch (Exception $e) { $logger->warning("ExecEngine extension included but role '" . self::$roleName . "' not used/defined in &-script."); self::$doRun = false; // prevent exec engine execution } $maxRunCount = Config::get('maxRunCount', 'execEngine'); self::$runCount = 0; self::$autoRerun = Config::get('autoRerun', 'execEngine'); // Get all rules that are maintained by the ExecEngine $rulesThatHaveViolations = array(); while (self::$doRun) { self::$doRun = false; self::$runCount++; // Prevent infinite loop in ExecEngine reruns if (self::$runCount > $maxRunCount) { Logger::getUserLogger()->error('Maximum reruns exceeded for ExecEngine (rules with violations:' . implode(', ', $rulesThatHaveViolations) . ')'); break; } $logger->notice("ExecEngine run #" . self::$runCount . " (auto rerun: " . var_export(self::$autoRerun, true) . ") for role '{$role->label}'"); // Determine affected rules that must be checked by the exec engine $affectedConjuncts = RuleEngine::getAffectedConjuncts($database->getAffectedConcepts(), $database->getAffectedRelations(), 'sig'); $affectedRules = array(); foreach ($affectedConjuncts as $conjunct) { $affectedRules = array_merge($affectedRules, $conjunct->sigRuleNames); } // Check rules $rulesThatHaveViolations = array(); foreach ($role->maintains() as $ruleName) { if (!in_array($ruleName, $affectedRules) && !$allRules) { continue; } // skip this rule $rule = Rule::getRule($ruleName); $violations = $rule->getViolations(false); if (count($violations)) { $rulesThatHaveViolations[] = $rule->id; // Fix violations for every rule $logger->notice("ExecEngine fixing " . count($violations) . " violations for rule '{$rule->id}'"); self::fixViolations($violations); // Conjunct violations are not cached, because they are fixed by the ExecEngine $logger->debug("Fixed " . count($violations) . " violations for rule '{$rule->__toString()}'"); // If $autoRerun, set $doRun to true because violations have been fixed (this may fire other execEngine rules) if (self::$autoRerun) { self::$doRun = true; } } } } $logger->info("ExecEngine run completed"); }
private static function pushNotification($emailAddr, $message, $title = null, $url = null, $urltitle = null) { Logger::getLogger('MESSAGING')->debug('Email[pushNotification' . ']; $emailAddr=[' . $emailAddr . ']; $message=[' . $message . ']; $title=[' . $title . ']; $url=[' . $url . ']; $urltitle=[' . $urltitle . ']'); // adapted from http://phpmailer.worxware.com/?pg=examplebgmail $config = Config::get('sendEmailConfig', 'msg_email'); $from = $config['from']; $username = $config['username']; $password = $config['password']; Logger::getLogger('MESSAGING')->debug('Email.php - Username = '******'smtp.gmail.com'; // Specify main and backup server $mail->SMTPSecure = 'ssl'; // Enable encryption, 'ssl' also accepted $mail->Port = 465; $mail->SMTPAuth = true; // Enable SMTP authentication $mail->Username = $username; // SMTP username (for GMAIL) $mail->Password = $password; // SMTP password $mail->From = $from; $mail->FromName = 'Ampersand Prototype'; $mail->AddAddress($emailAddr); // Add a recipient, e.g. $to = '*****@*****.**', 'Rieks Joosten' $mail->Subject = $title; // $message = $message . 'optional URL'; if ($url != '_NULL' && $url != '') { $mail->IsHTML(true); // make sure we send in HTML if ($urltitle != '_NULL' && $urltitle != '') { $message = '<p>' . $message . '</p><p><a href=' . $url . '>' . $urltitle . '</a></p>'; } else { $message = $message . '<a' . $urltitle . '</a>'; } Logger::getLogger('MESSAGING')->debug('Email message refactored to: [' . $message . ']'); } $mail->Body = $message; $mail->WordWrap = 50; // Set word wrap to 50 characters if (!$mail->Send()) { Logger::getUserLogger()->error('Mailer Error: ' . $mail->ErrorInfo); } else { Logger::getUserLogger()->notice("Email message sent."); } }
/** * Function to evaluate conjunct * @param boolean $cacheConjuncts * @return array[] array(array('src' => '<srcAtomId>', 'tgt' => '<tgtAtomId>')) */ public function evaluateConjunct($cacheConjuncts = true) { $this->logger->debug("Checking conjunct '{$this->id}' cache:" . var_export($cacheConjuncts, true)); try { // If conjunct is already evaluated and conjunctCach may be used -> return violations if (isset($this->conjunctViolations) && $cacheConjuncts) { $this->logger->debug("Conjunct is already evaluated, getting violations from cache"); return $this->conjunctViolations; // Otherwise evaluate conjunct, cache and return violations } else { $db = Database::singleton(); $dbsignalTableName = Config::get('dbsignalTableName', 'mysqlDatabase'); $violations = array(); // Execute conjunct query $violations = (array) $db->Exe($this->query); // Cache violations in php Conjunct object if ($cacheConjuncts) { $this->conjunctViolations = $violations; } if (count($violations) == 0) { $this->logger->debug("Conjunct '{$this->id}' holds"); // Remove "old" conjunct violations from database $query = "DELETE FROM `{$dbsignalTableName}` WHERE `conjId` = '{$this->id}'"; $db->Exe($query); } else { $this->logger->debug("Conjunct '{$this->id}' broken, updating violations in database"); // Remove "old" conjunct violations from database $query = "DELETE FROM `{$dbsignalTableName}` WHERE `conjId` = '{$this->id}'"; $db->Exe($query); // Add new conjunct violation to database $query = "INSERT IGNORE INTO `{$dbsignalTableName}` (`conjId`, `src`, `tgt`) VALUES "; $values = array(); foreach ($violations as $violation) { $values[] = "('{$this->id}', '" . $db->escape($violation['src']) . "', '" . $db->escape($violation['tgt']) . "')"; } $query .= implode(',', $values); $db->Exe($query); } return $violations; } } catch (Exception $e) { Logger::getUserLogger()->error("While checking conjunct '{$this->id}': " . $e->getMessage()); return array(); } }
/** * Function to request closing the open database transaction * @param string $succesMessage specifies success/info message when invariants hold * @param boolean $databaseCommit specifies to commit (true) or rollback (false) when all invariants hold * @param Atom $atomStoreNewContent specifies to store the new content for the updated/created atom * @return boolean specifies if invariant rules hold (true) or not (false) */ public function closeTransaction($succesMessage = 'Updated', $databaseCommit = null, &$atomStoreNewContent = null) { Hooks::callHooks('preDatabaseCloseTransaction', get_defined_vars()); $this->logger->info("Closing database transaction"); $this->logger->info("Checking all affected conjuncts"); // Check invariant rules (we only have to check the affected invariant rules) $affectedConjuncts = RuleEngine::getAffectedConjuncts($this->affectedConcepts, $this->affectedRelations, 'inv'); // Get affected invariant conjuncts $invariantRulesHold = RuleEngine::checkInvariantRules($affectedConjuncts, true); // Check all process rules that are relevant for the activate roles RuleEngine::checkProcessRules(); unset($this->affectedConcepts, $this->affectedRelations); $this->affectedConcepts = array(); $this->affectedRelations = array(); if (!is_null($atomStoreNewContent)) { $atomStoreNewContent->setStoredContent(); } // Determine if transaction should be committed or not when all invariant rules hold based on $requestType if (is_null($databaseCommit)) { $databaseCommit = $this->processRequestType(); } if ($invariantRulesHold && $databaseCommit) { $this->commitTransaction(); // commit database transaction Logger::getUserLogger()->notice($succesMessage); } elseif (Config::get('ignoreInvariantViolations', 'transactions') && $databaseCommit) { $this->commitTransaction(); Logger::getUserLogger()->warning("Transaction committed with invariant violations"); } elseif ($invariantRulesHold) { $this->logger->info("Invariant rules hold, but no database commit requested"); $this->rollbackTransaction(); // rollback database transaction } else { $this->logger->info("Invariant rules do not hold"); $this->rollbackTransaction(); // rollback database transaction } Hooks::callHooks('postDatabaseCloseTransaction', get_defined_vars()); return $this->invariantRulesHold = $invariantRulesHold; }
private static function pushNotification($SMSAddr, $message, $title = null, $url = null, $urltitle = null) { Logger::getLogger('MESSAGING')->debug('UNTESTED !!! SMS[pushNotification' . ']; $SMSAddr=[' . $SMSAddr . ']; $message=[' . $message . ']; $title=[' . $title . ']; $url=[' . $url . ']; $urltitle=[' . $urltitle . ']'); /* Config params for SendSMS function of ExecEngine (using MessageBird.com) * Set the sender, could be a number (16 numbers) or letters (11 characters) * */ // Copy the following line to localSettings.php and provide settings // Config::set('sendSMSConfig', 'execEngine', array('username' => '', 'password' => '', 'sender' => '')); $config = Config::get('sendSMSConfig', 'msg_SMS'); $username = $config['username']; $password = $config['password']; $sender = $config['sender']; Logger::getLogger('MESSAGING')->debug('Username = '******'31600000000'); // Set an reference, optional // $sms->setReference('123456789'); // Set a schedule date-time, optional // $sms->setTimestamp('2014-01-01 10:02'); // Replace non GSM-7 characters by appropriate valid GSM-7 characters // $sms->setReplacechars(false); // If you want a dlr notification of the message send to another url then that you have set on the web site, you can use this parameter. Don't forget to set a reference! // $sms->setDlrUrl('http://www.example.com/dlr_url.php'); // If $test is TRUE, then the message is not actually sent or scheduled, and there will be no credits deducted. Logger::getLogger('MESSAGING')->debug("SMS testing is set to TRUE (messages are not actually sent)"); $sms->setTest(true); // Send the message to the destination(s) $sms->sendSms($message); if ($sms->getResponseCode() == "01") { Logger::getUserLogger()->notice("SMS message sent."); } else { Logger::getUserLogger()->error('SMS error: ' . $sms->getResponseMessage()); } Logger::getLogger('MESSAGING')->debug("SMS Response: " . $sms->getResponseMessage()); Logger::getLogger('MESSAGING')->debug("SMS Balance: " . $sms->getCreditBalance()); }
/** * Performs given patches on atom, i.e. add, replace, remove tuples in relations * @param array $patches * @throws Exception * @return void */ public function doPatches($patches = array()) { $errorCount = 0; foreach ((array) $patches as $key => $patch) { try { // Check patch if (!array_key_exists('op', $patch)) { throw new Exception("No 'op' (i.e. operation) specfied for patch #{$key}", 400); } if (!array_key_exists('path', $patch)) { throw new Exception("No 'path' specfied for patch #{$key}", 400); } $atomOrIfc = $this->walkIfcPath($patch['path']); switch ($patch['op']) { case "replace": $atomOrIfc->doPatchReplace($patch); break; case "add": $atomOrIfc->doPatchAdd($patch); break; case "remove": $atomOrIfc->doPatchRemove($patch); break; default: throw new Exception("Unknown patch operation '" . $patch['op'] . "'. Supported are: 'replace', 'add' and 'remove'", 501); } } catch (Exception $e) { Logger::getUserLogger()->error($e->getMessage()); $errorCount++; } } if ($errorCount) { $totalPatches = count($patches); $processed = $totalPatches - $errorCount; Logger::getUserLogger()->warning("{$processed}/{$totalPatches} patches processed. {$errorCount} errors."); } }
function ClearConcept($concept, $atom) { Logger::getLogger('EXECENGINE')->info("ClearConcept({$concept},{$atom})"); if (func_num_args() != 2) { throw new Exception("Wrong number of arguments supplied for function ClearConcept(): " . func_num_args() . " arguments", 500); } try { $database = Database::singleton(); $atom = new Atom($atom, Concept::getConceptByLabel($concept)); $database->atomClearConcept($atom); Logger::getLogger('EXECENGINE')->debug("Atom '{$atom->__toString()}' removed as member from concept '{$concept}'"); } catch (Exception $e) { Logger::getUserLogger()->error('ClearConcept: ' . $e->getMessage()); } }