Пример #1
0
 /**
  *
  * @throws Exception when segment type is unknown
  * @throws Exception when segment expression return more that 1 tgt atom
  * @return string
  */
 public function getViolationMessage()
 {
     $database = Database::singleton();
     $strArr = array();
     foreach ($this->rule->violationSegments as $segment) {
         // text segment
         if ($segment['segmentType'] == 'Text') {
             $strArr[] = $segment['Text'];
             // expressie segment
         } elseif ($segment['segmentType'] == 'Exp') {
             // select starting atom depending on whether the segment uses the src of tgt atom.
             $atom = $segment['srcOrTgt'] == 'Src' ? $this->src : $this->tgt;
             // quering the expression
             $query = "SELECT DISTINCT `tgt` FROM ({$segment['expSQL']}) AS `results` WHERE `src` = '{$atom->idEsc}'";
             // SRC of TGT kunnen door een expressie gevolgd worden
             $rows = $database->Exe($query);
             // returning the result
             if (count($rows) > 1) {
                 throw new Exception("Expression of pairview results in more than one tgt atom", 501);
             }
             // 501: Not implemented
             $strArr[] = $rows[0]['tgt'];
             // unknown segment
         } else {
             $errorMessage = "Unknown segmentType '{$segment['segmentType']}' in violationSegments of rule '{$this->rule->id}'";
             throw new Exception($errorMessage, 501);
             // 501: Not implemented
         }
     }
     // If empty array of strings (i.e. no violation segments defined), use default violation representation: '<srcAtom>,<tgtAtom>'
     $this->message = empty($strArr) ? "{$this->src->getLabel()},{$this->tgt->getLabel()}" : implode($strArr);
     return $this->message;
 }
Пример #2
0
 /**
  * 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();
 }
Пример #3
0
 /**
  * Relation constructor
  * Private function to prevent outside instantiation of Relations. Use Relation::getRelation($relationSignature)
  *
  * @param array $relationDef
  */
 public function __construct($relationDef)
 {
     $this->db = Database::singleton();
     $this->logger = Logger::getLogger('FW');
     $this->name = $relationDef['name'];
     $this->srcConcept = Concept::getConcept($relationDef['srcConceptId']);
     $this->tgtConcept = Concept::getConcept($relationDef['tgtConceptId']);
     $this->signature = $relationDef['signature'];
     $this->isUni = $relationDef['uni'];
     $this->isTot = $relationDef['tot'];
     $this->isInj = $relationDef['inj'];
     $this->isSur = $relationDef['sur'];
     $this->isProp = $relationDef['prop'];
     foreach ((array) $relationDef['affectedConjuncts'] as $conjId) {
         $conj = Conjunct::getConjunct($conjId);
         $this->affectedConjuncts[] = $conj;
         if ($conj->isSigConj()) {
             $this->affectedSigConjuncts[] = $conj;
         }
         if ($conj->isInvConj()) {
             $this->affectedInvConjuncts[] = $conj;
         }
         // if (!$conj->isSigConj() && !$conj->isInvConj()) $this->logger->warning("Affected conjunct '{$conj->id}' (specified for relation '{$this->__toString()}') is not part of an invariant or signal rule");
     }
     // Specify mysql table information
     $this->mysqlTable = new RelationTable($relationDef['mysqlTable']['name'], $relationDef['mysqlTable']['tableOf']);
     $srcCol = $relationDef['mysqlTable']['srcCol'];
     $tgtCol = $relationDef['mysqlTable']['tgtCol'];
     $this->mysqlTable->addSrcCol(new DatabaseTableCol($srcCol['name'], $srcCol['null'], $srcCol['unique']));
     $this->mysqlTable->addTgtCol(new DatabaseTableCol($tgtCol['name'], $tgtCol['null'], $tgtCol['unique']));
 }
Пример #4
0
    $allLinks = array();
    foreach (Relation::getAllRelations() as $rel) {
        $allLinks[$rel->signature] = $rel->getAllLinks();
    }
    $strFileContent = '<?php' . PHP_EOL . '$allAtoms = ' . var_export($allAtoms, true) . ';' . PHP_EOL . '$allLinks = ' . var_export($allLinks, true) . ';' . PHP_EOL . '?>';
    file_put_contents(Config::get('absolutePath') . Config::get('logPath') . "export-" . date('Y-m-d_H-i-s') . ".php", $strFileContent);
});
$app->get('/admin/import', function () use($app) {
    if (Config::get('productionEnv')) {
        throw new Exception("Import not allowed in production environment", 403);
    }
    $file = $app->request->params('file');
    if (is_null($file)) {
        throw new Exception("Import file not specified", 500);
    }
    $database = Database::singleton();
    include_once Config::get('absolutePath') . Config::get('logPath') . "{$file}";
    // check if all concepts and relations are defined
    foreach ((array) $allAtoms as $cpt => $atoms) {
        if (!empty($atoms)) {
            Concept::getConcept($cpt);
        }
    }
    foreach ((array) $allLinks as $rel => $links) {
        if (!empty($links)) {
            Relation::getRelation($rel);
        }
    }
    foreach ((array) $allAtoms as $cpt => $atoms) {
        $concept = Concept::getConcept($cpt);
        foreach ($atoms as $atomId) {
Пример #5
0
 /**
  * InterfaceObject constructor
  * @param array $ifcDef Interface object definition as provided by Ampersand generator
  * @param string $pathEntry
  * @param boolean $rootIfc Specifies if this interface object is a toplevel interface (true) or subinterface (false)
  */
 public function __construct($ifcDef, $pathEntry = null, $rootIfc = false)
 {
     $this->database = Database::singleton();
     $this->logger = Logger::getLogger('FW');
     $this->isRoot = $rootIfc;
     // Set attributes from $ifcDef
     $this->id = $ifcDef['id'];
     $this->label = $ifcDef['label'];
     $this->view = is_null($ifcDef['viewId']) ? null : View::getView($ifcDef['viewId']);
     $this->path = is_null($pathEntry) ? $this->id : "{$pathEntry}/{$this->id}";
     // Information about the (editable) relation if applicable
     $this->relation = is_null($ifcDef['relation']) ? null : Relation::getRelation($ifcDef['relation']);
     $this->relationIsFlipped = $ifcDef['relationIsFlipped'];
     // Interface expression information
     $this->srcConcept = Concept::getConcept($ifcDef['expr']['srcConceptId']);
     $this->tgtConcept = Concept::getConcept($ifcDef['expr']['tgtConceptId']);
     $this->isUni = $ifcDef['expr']['isUni'];
     $this->isTot = $ifcDef['expr']['isTot'];
     $this->isIdent = $ifcDef['expr']['isIdent'];
     $this->query = $ifcDef['expr']['query'];
     // CRUD rights
     $this->crudC = $ifcDef['crud']['create'];
     $this->crudR = $ifcDef['crud']['read'];
     $this->crudU = $ifcDef['crud']['update'];
     $this->crudD = $ifcDef['crud']['delete'];
     if ($this->crudU && $this->tgtConcept->isObject) {
         $this->editableConcepts[] = $this->tgtConcept;
     }
     // Interface expression must equal (editable) relation when crudU is specified
     if ($this->crudU && is_null($this->relation)) {
         $this->logger->warning("Update rights (crUd) specified while interface expression is not an editable relation for (sub)interface: {$this->path}");
     }
     // Check for unsupported patchReplace functionality due to missing 'old value'. Related with issue #318
     if (!is_null($this->relation) && $this->crudU && !$this->tgtConcept->isObject && $this->isUni) {
         // Only applies to editable relations
         // Only applies to crudU, because issue is with patchReplace, not with add/remove
         // Only applies to scalar, because objects don't use patchReplace, but Remove and Add
         // Only if interface expression (not! the relation) is univalent, because else a add/remove option is used in the UI
         if (!$this->relationIsFlipped && $this->relation->getMysqlTable()->tableOf == 'tgt' || $this->relationIsFlipped && $this->relation->getMysqlTable()->tableOf == 'src') {
             $this->logger->warning("Unsupported edit functionality due to combination of factors for (sub)interface: '{$this->path}' - {$this->relation->__toString()}" . ($this->relationIsFlipped ? '~' : '') . " administrated in table of '{$this->relation->getMysqlTable()->tableOf}'");
         }
     }
     // Subinterfacing
     if (!is_null($ifcDef['subinterfaces'])) {
         // Subinterfacing is not supported/possible for tgt concepts with a scalar representation type (i.e. non-objects)
         if (!$this->tgtConcept->isObject) {
             throw new Exception("Subinterfacing is not supported for concepts with a scalar representation type (i.e. non-objects). (Sub)Interface '{$this->path}' with target {$this->tgtConcept->__toString()} (type:{$this->tgtConcept->type}) has subinterfaces specified", 501);
         }
         // Reference to top level interface
         $this->refInterfaceId = $ifcDef['subinterfaces']['refSubInterfaceId'];
         $this->isLinkTo = $ifcDef['subinterfaces']['refIsLinTo'];
         // Inline subinterface definitions
         foreach ((array) $ifcDef['subinterfaces']['ifcObjects'] as $subIfcDef) {
             $ifc = new InterfaceObject($subIfcDef, $this->path);
             $this->subInterfaces[$ifc->id] = $ifc;
             $this->editableConcepts = array_merge($this->editableConcepts, $ifc->editableConcepts);
         }
     }
 }
Пример #6
0
 private function login($email)
 {
     if (empty($email)) {
         throw new Exception("No emailaddress provided to login", 500);
     }
     $session = Session::singleton();
     $db = Database::singleton();
     $conceptUserID = Concept::getConceptByLabel('UserID');
     $conceptDomain = Concept::getConceptByLabel('Domain');
     $conceptDateTime = Concept::getConceptByLabel('DateTime');
     $conceptOrg = Concept::getConceptByLabel('Organization');
     $conceptAccount = Concept::getConceptByLabel('Account');
     $conceptSession = Concept::getConceptByLabel('SESSION');
     // Set sessionUser
     $atom = new Atom($email, $conceptUserID);
     $accounts = $atom->ifc('AccountForUserid')->getTgtAtoms();
     // create new user
     if (empty($accounts)) {
         $newAccount = Concept::getConceptByLabel('Account')->createNewAtom();
         // Save email as accUserid
         $relAccUserid = Relation::getRelation('accUserid', $newAccount->concept, $conceptUserID);
         $relAccUserid->addLink($newAccount, new Atom($email, $conceptUserID), false, 'OAuthLoginExtension');
         // If possible, add account to organization(s) based on domain name
         $domain = explode('@', $email)[1];
         $atom = new Atom($domain, $conceptDomain);
         $orgs = $atom->ifc('DomainOrgs')->getTgtAtoms();
         $relAccOrg = Relation::getRelation('accOrg', $newAccount->concept, $conceptOrg);
         foreach ($orgs as $org) {
             $relAccOrg->addLink($newAccount, $org, false, 'OAuthLoginExtension');
         }
         // Account created, add to $accounts list (used lateron)
         $accounts[] = $newAccount;
     }
     if (count($accounts) > 1) {
         throw new Exception("Multiple users registered with email {$email}", 401);
     }
     $relSessionAccount = Relation::getRelation('sessionAccount', $conceptSession, $conceptAccount);
     $relAccMostRecentLogin = Relation::getRelation('accMostRecentLogin', $conceptAccount, $conceptDateTime);
     $relAccLoginTimestamps = Relation::getRelation('accLoginTimestamps', $conceptAccount, $conceptDateTime);
     foreach ($accounts as $account) {
         // Set sessionAccount
         $relSessionAccount->addLink($session->sessionAtom, $account, false, 'OAuthLoginExtension');
         // Timestamps
         $ts = new Atom(date(DATE_ISO8601), $conceptDateTime);
         $relAccMostRecentLogin->addLink($account, $ts, false, 'OAuthLoginExtension');
         $relAccLoginTimestamps->addLink($account, $ts, false, 'OAuthLoginExtension');
     }
     $db->closeTransaction('Login successfull', true);
 }
Пример #7
0
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);
});
Пример #8
0
 /**
  * Concept constructor
  * Private function to prevent outside instantiation of concepts. Use Concept::getConcept($conceptName)
  * 
  * @param array $conceptDef
  */
 private function __construct($conceptDef)
 {
     $this->database = Database::singleton();
     $this->logger = Logger::getLogger('FW');
     $this->def = $conceptDef;
     $this->name = $conceptDef['id'];
     $this->label = $conceptDef['label'];
     $this->type = $conceptDef['type'];
     $this->isObject = $this->type == "OBJECT" ? true : false;
     $this->affectedConjunctIds = (array) $conceptDef['affectedConjuncts'];
     foreach ($this->affectedConjunctIds as $conjId) {
         $conj = Conjunct::getConjunct($conjId);
         if ($conj->isSigConj()) {
             $this->affectedSigConjuncts[] = $conj;
         }
         if ($conj->isInvConj()) {
             $this->affectedInvConjuncts[] = $conj;
         }
         // if (!$conj->isSigConj() && !$conj->isInvConj()) $this->logger->warning("Affected conjunct '{$conj->id}' (specified for concept '[{$this->name}]') is not part of an invariant or signal rule");
     }
     $this->specializations = (array) $conceptDef['specializations'];
     $this->generalizations = (array) $conceptDef['generalizations'];
     $this->interfaceIds = (array) $conceptDef['interfaces'];
     $this->largestConceptId = $conceptDef['largestConcept'];
     if (!is_null($conceptDef['defaultViewId'])) {
         $this->defaultView = View::getView($conceptDef['defaultViewId']);
     }
     $this->mysqlConceptTable = new DatabaseTable($conceptDef['conceptTable']['name']);
     foreach ($conceptDef['conceptTable']['cols'] as $colName) {
         $this->mysqlConceptTable->addCol(new DatabaseTableCol($colName));
     }
 }
Пример #9
0
 /**
  * Overwrites getViolationMessage() method from Violation class
  * @throws Exception when segment type is unknown
  * @throws Exception when segment expression return more that 1 tgt atom
  * @return string
  */
 public function getViolationMessage()
 {
     $database = Database::singleton();
     $strArr = array();
     foreach ($this->rule->violationSegments as $segment) {
         // text segment
         if ($segment['segmentType'] == 'Text') {
             $strArr[] = $segment['Text'];
             // expressie segment
         } elseif ($segment['segmentType'] == 'Exp') {
             // select starting atom depending on whether the segment uses the src of tgt atom.
             $atom = $segment['srcOrTgt'] == 'Src' ? $this->src : $this->tgt;
             $rows = array();
             if ($segment['expIsIdent']) {
                 // when segment expression isIdent (i.e. SRC I or TGT I), we don't have to query the database.
                 $rows[] = array('tgt' => $atom->id);
             } else {
                 // quering the expression
                 $query = "SELECT DISTINCT `tgt` FROM ({$segment['expSQL']}) AS `results` WHERE `src` = '{$atom->idEsc}'";
                 // SRC of TGT kunnen door een expressie gevolgd worden
                 $rows = $database->Exe($query);
             }
             // returning the result
             if (count($rows) == 0) {
                 $strArr[] = '_NULL';
             } else {
                 $str = '';
                 foreach ($rows as $row) {
                     $str .= $row['tgt'] . '_AND';
                 }
                 $str = substr($str, 0, -4);
                 // strip the last _AND
                 $strArr[] = str_replace(array('{EX}', '{php}'), '', $str);
                 // prevent php interpreter by user input. Only allowed as Text segments specified in &-script
             }
             // unknown segment
         } else {
             $errorMessage = "Unknown segmentType '{$segment['segmentType']}' in violationSegments of rule '{$this->rule->id}'";
             throw new Exception($errorMessage, 501);
             // 501: Not implemented
         }
     }
     return $this->message = implode($strArr);
 }
Пример #10
0
function OverwritePopulation($rArray, $relationName, $conceptName)
{
    try {
        $database = Database::singleton();
        $concept = Concept::getConceptByLabel($conceptName);
        $relation = Relation::getRelation($relationName, $concept, $concept);
        $relationTable = $relation->getMysqlTable();
        $srcCol = $relationTable->srcCol();
        $tgtCol = $relationTable->tgtCol();
        $query = "DELETE FROM `{$relationTable->name}`";
        // Do not use TRUNCATE statement, this causes an implicit commit
        $database->Exe($query);
        foreach ($rArray as $src => $tgtArray) {
            foreach ($tgtArray as $tgt => $bool) {
                if ($bool) {
                    $query = "INSERT INTO `{$relationTable->name}` (`{$srcCol->name}`, `{$tgtCol->name}`) VALUES ('{$src}','{$tgt}')";
                    $database->Exe($query);
                }
            }
        }
    } catch (Exception $e) {
        throw new Exception('OverwritePopulation: ' . $e->getMessage(), 500);
    }
}
Пример #11
0
 /**
  * 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();
     }
 }
Пример #12
0
 /**
  * Atom constructor
  * @param string $atomId
  * @param Concept $concept
  * @param InterfaceObject $ifc
  * @param array $qData the row data (from database query) from which this atom is created
  * @return void
  */
 public function __construct($atomId, Concept $concept, InterfaceObject $ifc = null, array $qData = null)
 {
     $this->database = Database::singleton();
     $this->logger = Logger::getLogger('FW');
     $this->concept = $concept;
     $this->parentIfc = $ifc;
     $this->qData = $qData;
     $this->setId($atomId);
     // JSON-LD attributes
     $this->url = Config::get('serverURL') . Config::get('apiPath') . '/resource/' . $this->concept->name . '/' . $this->getJsonRepresentation();
 }
Пример #13
0
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());
    }
}