diff --git a/.config/phpcs.xml.dist b/.config/phpcs.xml.dist
new file mode 100644
index 0000000..bc62ad3
--- /dev/null
+++ b/.config/phpcs.xml.dist
@@ -0,0 +1,50 @@
+
+
+ PHP coding standards for the PDS Interop PHP Solid Server project
+
+
+
+
+
+
+
+
+
+ .
+ *(.config|vendor)/*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..7438acf
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,24 @@
+root = true
+
+[*.php]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = tab
+insert_final_newline = true
+max_line_length = 120
+spelling_language = en-US
+tab_width = 4
+trim_trailing_whitespace = true
+
+# Unset settings for vendor directories
+[{node_modules,vendor}/**]
+charset = unset
+end_of_line = unset
+indent_size = unset
+indent_style = unset
+insert_final_newline = unset
+max_line_length = unset
+spelling_language = unset
+tab_width = unset
+trim_trailing_whitespace = unset
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000..523df56
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,16 @@
+# List of revisions that are hidden from git blame annotations.
+#
+# This concerns massive code re-formatting, renaming, large changes
+# that were later reverted, etc.
+#
+# Configure your git so that it always ignores the revisions listed
+# in this file:
+#
+# git config blame.ignoreRevsFile .git-blame-ignore-revs
+#
+# When adding a new revision to the list, please put its commit message
+# in a comment above it.
+
+
+# Mass fix of PHP Codesniffer whitespace violations
+aaeca415e39669aae893f2fde47cf2ae04a6a287
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index 85c820c..9fb4410 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -51,7 +51,8 @@ jobs:
--exclude vendor
--no-progress
.
-# # 01.quality.php.validate.dependencies-file.yml
+
+ # 01.quality.php.validate.dependencies-file.yml
validate-dependencies-file:
name: Validate dependencies file
runs-on: ubuntu-24.04
@@ -63,6 +64,7 @@ jobs:
--no-plugins
--no-scripts
--strict
+
# 02.test.php.test-unit.yml
php-unittest:
name: PHP Unit Tests
@@ -89,6 +91,7 @@ jobs:
env:
COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
- run: vendor/bin/phpunit --configuration tests/phpunit/phpunit.xml
+
# 03.quality.php.scan.dependencies-vulnerabilities.yml
scan-dependencies-vulnerabilities:
name: Scan Dependencies Vulnerabilities
@@ -107,6 +110,24 @@ jobs:
--no-dev
--no-plugins
--no-scripts
+
+
+ # 03.quality.php.lint-quality.yml
+ php-lint-quality:
+ needs:
+ - lint-php-syntax
+ runs-on: ubuntu-24.04
+ steps:
+ - uses: actions/checkout@v4
+ - uses: docker://pipelinecomponents/php-codesniffer
+ with:
+ args: >-
+ phpcs
+ --standard=.config/phpcs.xml.dist
+ --report-full
+ --report-summary
+ .
+
# 03.quality.php.lint-version-compatibility.yml
php-check-version-compatibility:
name: PHP Version Compatibility
diff --git a/init.php b/init.php
index af5668d..94c1b72 100644
--- a/init.php
+++ b/init.php
@@ -1,83 +1,90 @@
exec($statement);
- }
- } catch(\PDOException $e) {
- echo $e->getMessage();
}
+ } catch (\PDOException $e) {
+ echo $e->getMessage();
}
+}
- function initStorageDatabase() {
- $statements = [
- 'CREATE TABLE IF NOT EXISTS storage (
- storage_id VARCHAR(255) NOT NULL PRIMARY KEY,
- owner VARCHAR(255) NOT NULL
- )'
- ];
+function initStorageDatabase()
+{
+ $statements = [
+ 'CREATE TABLE IF NOT EXISTS storage (
+ storage_id VARCHAR(255) NOT NULL PRIMARY KEY,
+ owner VARCHAR(255) NOT NULL
+ )'
+ ];
- try {
- $pdo = new \PDO("sqlite:" . DBPATH);
+ try {
+ $pdo = new \PDO("sqlite:" . DBPATH);
- // create tables
- foreach($statements as $statement){
+ // create tables
+ foreach ($statements as $statement) {
$pdo->exec($statement);
- }
- } catch(\PDOException $e) {
- echo $e->getMessage();
}
+ } catch (\PDOException $e) {
+ echo $e->getMessage();
}
- initKeys();
- initDatabase();
- initStorageDatabase();
\ No newline at end of file
+}
+
+initKeys();
+initDatabase();
+initStorageDatabase();
diff --git a/lib/ClientRegistration.php b/lib/ClientRegistration.php
index 741edbf..70d9f93 100644
--- a/lib/ClientRegistration.php
+++ b/lib/ClientRegistration.php
@@ -1,72 +1,78 @@
prepare(
- 'SELECT clientData FROM clients WHERE clientId=:clientId'
- );
- $query->execute([
- ':clientId' => $clientId
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- return json_decode($result[0]['clientData'], true);
- }
- if (preg_match("/^http(s)?:/", $clientId)) {
- $clientData = self::getRemoteRegistration($clientId);
- if (!isset($clientData['origin']) && isset($clientData['client_uri'])) {
- $clientData['origin'] = rtrim($clientData['client_uri'], '/');
- }
- self::saveClientRegistration($clientData);
- return $clientData;
+use Pdsinterop\PhpSolid\Db;
+
+class ClientRegistration
+{
+ public static function getRegistration($clientId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT clientData FROM clients WHERE clientId=:clientId'
+ );
+ $query->execute([
+ ':clientId' => $clientId
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ return json_decode($result[0]['clientData'], true);
+ }
+ if (preg_match("/^http(s)?:/", $clientId)) {
+ $clientData = self::getRemoteRegistration($clientId);
+ if (!isset($clientData['origin']) && isset($clientData['client_uri'])) {
+ $clientData['origin'] = rtrim($clientData['client_uri'], '/');
}
- return false;
+ self::saveClientRegistration($clientData);
+ return $clientData;
}
+ return false;
+ }
- public static function getRemoteRegistration($url) {
- $clientDocument = file_get_contents($url);
- $clientRegistration = json_decode($clientDocument, true);
- if (!isset($clientRegistration['client_id'])) {
- throw new \Exception("No client ID found in client document");
- }
- if (!isset($clientRegistration['redirect_uris'])) {
- throw new \Exception("No redirect URIs found in client document");
- }
- return $clientRegistration;
+ public static function getRemoteRegistration($url)
+ {
+ $clientDocument = file_get_contents($url);
+ $clientRegistration = json_decode($clientDocument, true);
+ if (!isset($clientRegistration['client_id'])) {
+ throw new \Exception("No client ID found in client document");
}
+ if (!isset($clientRegistration['redirect_uris'])) {
+ throw new \Exception("No redirect URIs found in client document");
+ }
+ return $clientRegistration;
+ }
- public static function saveClientRegistration($clientData) {
- Db::connect();
- if (!isset($clientData['client_name'])) {
- $clientData['client_name'] = $clientData['origin'];
- }
- $query = Db::$pdo->prepare(
- 'INSERT INTO clients VALUES(:clientId, :origin, :clientData)'
- );
- $query->execute([
- ':clientId' => $clientData['client_id'],
- ':origin' => $clientData['origin'],
- ':clientData' => json_encode($clientData)
- ]);
+ public static function saveClientRegistration($clientData)
+ {
+ Db::connect();
+ if (!isset($clientData['client_name'])) {
+ $clientData['client_name'] = $clientData['origin'];
}
-
- public static function getClientByOrigin($origin) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT clientData FROM clients WHERE origin=:origin'
- );
- $query->execute([
- ':origin' => $origin
- ]);
- $result = $query->fetchAll();
-
- if (sizeof($result)=== 1) {
- return json_decode($result[0]['clientData'], true);
- }
- return false;
+ $query = Db::$pdo->prepare(
+ 'INSERT INTO clients VALUES(:clientId, :origin, :clientData)'
+ );
+ $query->execute([
+ ':clientId' => $clientData['client_id'],
+ ':origin' => $clientData['origin'],
+ ':clientData' => json_encode($clientData)
+ ]);
+ }
+
+ public static function getClientByOrigin($origin)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT clientData FROM clients WHERE origin=:origin'
+ );
+ $query->execute([
+ ':origin' => $origin
+ ]);
+ $result = $query->fetchAll();
+
+ if (sizeof($result) === 1) {
+ return json_decode($result[0]['clientData'], true);
}
- }
\ No newline at end of file
+ return false;
+ }
+}
diff --git a/lib/Db.php b/lib/Db.php
index 8eb46e1..7f738c2 100644
--- a/lib/Db.php
+++ b/lib/Db.php
@@ -1,11 +1,14 @@
prepare(
- 'INSERT INTO ipAttempts VALUES(:ip, :type, :expires)'
- );
- $query->execute([
- ':ip' => $ip,
- ':type' => $type,
- ':expires' => $expires
- ]);
+
+namespace Pdsinterop\PhpSolid;
+
+use Pdsinterop\PhpSolid\Db;
+
+class IpAttempts
+{
+ public static function logFailedAttempt($ip, $type, $expires)
+ {
+ if (in_array($ip, TRUSTED_IPS)) {
+ return;
}
- public static function getAttemptsCount($ip, $type) {
- if (in_array($ip, TRUSTED_IPS)) {
- return 0;
- }
-
- Db::connect();
-
- $now = new \DateTime();
- $query = Db::$pdo->prepare(
- 'SELECT count(ip) as count FROM ipAttempts WHERE ip=:ip AND type=:type AND expires > :now'
- );
- $query->execute([
- ':ip' => $ip,
- ':type' => $type,
- ':now' => $now->getTimestamp()
- ]);
- $result = $query->fetch();
- if (isset($result['count'])) {
- return $result['count'];
- }
+ Db::connect();
+
+ $query = Db::$pdo->prepare(
+ 'INSERT INTO ipAttempts VALUES(:ip, :type, :expires)'
+ );
+ $query->execute([
+ ':ip' => $ip,
+ ':type' => $type,
+ ':expires' => $expires
+ ]);
+ }
+
+ public static function getAttemptsCount($ip, $type)
+ {
+ if (in_array($ip, TRUSTED_IPS)) {
return 0;
}
- public static function cleanupAttempts() {
- Db::connect();
-
- $now = new \DateTime();
- $query = Db::$pdo->prepare(
- 'DELETE FROM ipAttempts WHERE expires < :now'
- );
- $query->execute([
- ':now' => $now->getTimestamp()
- ]);
+
+ Db::connect();
+
+ $now = new \DateTime();
+ $query = Db::$pdo->prepare(
+ 'SELECT count(ip) as count FROM ipAttempts WHERE ip=:ip AND type=:type AND expires > :now'
+ );
+ $query->execute([
+ ':ip' => $ip,
+ ':type' => $type,
+ ':now' => $now->getTimestamp()
+ ]);
+ $result = $query->fetch();
+ if (isset($result['count'])) {
+ return $result['count'];
}
+ return 0;
+ }
+ public static function cleanupAttempts()
+ {
+ Db::connect();
+
+ $now = new \DateTime();
+ $query = Db::$pdo->prepare(
+ 'DELETE FROM ipAttempts WHERE expires < :now'
+ );
+ $query->execute([
+ ':now' => $now->getTimestamp()
+ ]);
}
+}
diff --git a/lib/JtiStore.php b/lib/JtiStore.php
index b487059..04c6b3c 100644
--- a/lib/JtiStore.php
+++ b/lib/JtiStore.php
@@ -1,46 +1,52 @@
prepare(
- 'SELECT jti FROM jti WHERE jti=:jti AND expires>:now'
- );
- $query->execute([
- ':jti' => $jti,
- ':now' => $now->getTimestamp()
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- return true;
- }
- return false;
- }
-
- public static function saveJti($jti) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'INSERT INTO jti VALUES(:jti, :expires)'
- );
- $expires = new \DateTime();
- $expires->add(new \DateInterval("PT1H"));
- $query->execute([
- ':jti' => $jti,
- ':expires' => $expires->getTimestamp()
- ]);
- }
+namespace Pdsinterop\PhpSolid;
+
+use Pdsinterop\PhpSolid\Db;
- public static function cleanupJti() {
- Db::connect();
- $now = new \DateTime();
- $query = Db::$pdo->prepare(
- 'DELETE FROM jti WHERE expires < :now'
- );
- $query->execute([
- ':now' => $now->getTimestamp()
- ]);
+class JtiStore
+{
+ public static function hasJti($jti)
+ {
+ Db::connect();
+ $now = new \DateTime();
+ $query = Db::$pdo->prepare(
+ 'SELECT jti FROM jti WHERE jti=:jti AND expires>:now'
+ );
+ $query->execute([
+ ':jti' => $jti,
+ ':now' => $now->getTimestamp()
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ return true;
}
- }
\ No newline at end of file
+ return false;
+ }
+
+ public static function saveJti($jti)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'INSERT INTO jti VALUES(:jti, :expires)'
+ );
+ $expires = new \DateTime();
+ $expires->add(new \DateInterval("PT1H"));
+ $query->execute([
+ ':jti' => $jti,
+ ':expires' => $expires->getTimestamp()
+ ]);
+ }
+
+ public static function cleanupJti()
+ {
+ Db::connect();
+ $now = new \DateTime();
+ $query = Db::$pdo->prepare(
+ 'DELETE FROM jti WHERE expires < :now'
+ );
+ $query->execute([
+ ':now' => $now->getTimestamp()
+ ]);
+ }
+}
diff --git a/lib/MailTemplateGenerator.php b/lib/MailTemplateGenerator.php
index 670ae19..47a9e83 100644
--- a/lib/MailTemplateGenerator.php
+++ b/lib/MailTemplateGenerator.php
@@ -1,11 +1,17 @@
+
+class MailTemplateGenerator
+{
+ public static function mailtemplate($mailTokens)
+ {
+ $backgroundColor = MAILSTYLES['container']['backgroundColor'] ?? "#eeeeee";
+ ob_start();
+ ?>
@@ -51,15 +57,17 @@ public static function mailtemplate($mailTokens) {
-
+ return $mailTemplate;
+ }
+
+ private static function mailTemplateHeader($mailTokens)
+ {
+ $backgroundColor = MAILSTYLES['header']['backgroundColor'] ?? "#3b3b3b";
+ ?>
@@ -75,44 +83,47 @@ private static function mailTemplateHeader($mailTokens) {
-
+ private static function mailTemplateCallToAction($mailTokens)
+ {
+ $backgroundColor = MAILSTYLES['call-to-action']['backgroundColor'] ?? "#ffffff";
+ $color = MAILSTYLES['call-to-action']['color'] ?? "#181818";
+ $colorMuted = MAILSTYLES['call-to-action']['colorMuted'] ?? "#333333";
+ $fontFamily = MAILSTYLES['call-to-action']['fontFamily'] ?? "Arial, Helvetica, sans-serif";
+ ?>
|
-
+ }
+ self::mailTemplateCallToActionDescription($mailTokens);
+ ?>
|
-
+
|
@@ -120,17 +131,18 @@ private static function mailTemplateCallToActionButton($mailTokens) {
|
-
+ private static function mailTemplateCallToActionButtonNoLink($mailTokens)
+ {
+ $backgroundColor = MAILSTYLES['call-to-action']['backgroundColor'] ?? "#ffffff";
+ $color = MAILSTYLES['call-to-action']['color'] ?? "#181818";
+ $colorMuted = MAILSTYLES['call-to-action']['colorMuted'] ?? "#333333";
+ $fontFamily = MAILSTYLES['call-to-action']['fontFamily'] ?? "Arial, Helvetica, sans-serif";
+ $buttonTextColor = MAILSTYLES['call-to-action']['buttonTextColor'] ?? "##eeeeee";
+ $buttonBackgroundColor = MAILSTYLES['call-to-action']['buttonBackgroundColor'] ?? "#262c2f";
+ ?>
|
@@ -138,15 +150,16 @@ private static function mailTemplateCallToActionButtonNoLink($mailTokens) {
|
-
+ private static function mailTemplateCallToActionTitle($mailTokens)
+ {
+ $backgroundColor = MAILSTYLES['call-to-action']['backgroundColor'] ?? "#ffffff";
+ $color = MAILSTYLES['call-to-action']['color'] ?? "#181818";
+ $colorMuted = MAILSTYLES['call-to-action']['colorMuted'] ?? "#333333";
+ $fontFamily = MAILSTYLES['call-to-action']['fontFamily'] ?? "Arial, Helvetica, sans-serif";
+ ?>
|
@@ -165,15 +178,16 @@ private static function mailTemplateCallToActionTitle($mailTokens) {
|
-
+ private static function mailTemplateCallToActionDescription($mailTokens)
+ {
+ $backgroundColor = MAILSTYLES['call-to-action']['backgroundColor'] ?? "#ffffff";
+ $color = MAILSTYLES['call-to-action']['color'] ?? "#181818";
+ $colorMuted = MAILSTYLES['call-to-action']['colorMuted'] ?? "#333333";
+ $fontFamily = MAILSTYLES['call-to-action']['fontFamily'] ?? "Arial, Helvetica, sans-serif";
+ ?>
|
@@ -192,13 +206,15 @@ private static function mailTemplateCallToActionDescription($mailTokens) {
|
-
+
@@ -232,6 +248,7 @@ private static function mailTemplateFooter($mailTokens) {
-
\ No newline at end of file
+
diff --git a/lib/MailTemplates.php b/lib/MailTemplates.php
index d1f85ef..a66d2b1 100644
--- a/lib/MailTemplates.php
+++ b/lib/MailTemplates.php
@@ -1,134 +1,142 @@
"Confirm your e-mail",
- "description" => "Your online identity is almost ready. Enter to code to complete your registration",
- "footer" => "",
- "buttonText" => "{code}",
- );
-
- $mailSubject = "Confirm your e-mail: {code}";
- $mailHtmlBody = MailTemplateGenerator::mailTemplate($mailTokens);
-
- $mailPlainBody = implode("\n\n", array(
- $mailTokens['title'],
- $mailTokens['buttonText'],
- $mailTokens['description'],
- $mailTokens['footer']
- ));
-
- foreach ($mailTokens as $token => $value) {
- $mailSubject = str_replace("{" . $token . "}", $mailTokens[$token], $mailSubject);
- $mailHtmlBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailHtmlBody);
- $mailPlainBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailPlainBody);
- }
-
- return array(
- "mailSubject" => $mailSubject,
- "mailHtmlBody" => $mailHtmlBody,
- "mailPlainBody" => $mailPlainBody
- );
+
+// phpcs:disable Generic.Files.LineLength.TooLong
+
+namespace Pdsinterop\PhpSolid;
+
+use Pdsinterop\PhpSolid\MailTemplateGenerator;
+
+class MailTemplates
+{
+ public static function verify()
+ {
+ $mailTokens = array(
+ "title" => "Confirm your e-mail",
+ "description" => "Your online identity is almost ready. Enter to code to complete your registration",
+ "footer" => "",
+ "buttonText" => "{code}",
+ );
+
+ $mailSubject = "Confirm your e-mail: {code}";
+ $mailHtmlBody = MailTemplateGenerator::mailTemplate($mailTokens);
+
+ $mailPlainBody = implode("\n\n", array(
+ $mailTokens['title'],
+ $mailTokens['buttonText'],
+ $mailTokens['description'],
+ $mailTokens['footer']
+ ));
+
+ foreach ($mailTokens as $token => $value) {
+ $mailSubject = str_replace("{" . $token . "}", $mailTokens[$token], $mailSubject);
+ $mailHtmlBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailHtmlBody);
+ $mailPlainBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailPlainBody);
}
-
- public static function resetPassword() {
- $mailSubject = "Password reset";
- $mailTokens = array(
- "title" => "Password reset",
- "description" => "If the link does not work, copy and paste this in your browser: " . BASEURL . "/change-password/?token={code}",
- "footer" => "",
- "buttonText" => "Reset password",
- "buttonLink" => BASEURL . "/change-password/?token={code}"
- );
-
- $mailHtmlBody = MailTemplateGenerator::mailTemplate($mailTokens);
-
- $mailPlainBody = implode("\n\n", array(
- $mailTokens['title'],
- $mailTokens['buttonText'],
- $mailTokens['description'],
- $mailTokens['footer']
- ));
- $mailPlainBody = $mailPlainBody;
-
- foreach ($mailTokens as $token => $value) {
- $mailSubject = str_replace("{" . $token . "}", $mailTokens[$token], $mailSubject);
- $mailHtmlBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailHtmlBody);
- $mailPlainBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailPlainBody);
- }
-
- return array(
- "mailSubject" => $mailSubject,
- "mailHtmlBody" => $mailHtmlBody,
- "mailPlainBody" => $mailPlainBody
- );
+
+ return array(
+ "mailSubject" => $mailSubject,
+ "mailHtmlBody" => $mailHtmlBody,
+ "mailPlainBody" => $mailPlainBody
+ );
+ }
+
+ public static function resetPassword()
+ {
+ $mailSubject = "Password reset";
+ $mailTokens = array(
+ "title" => "Password reset",
+ "description" => "If the link does not work, copy and paste this in your browser: " . BASEURL . "/change-password/?token={code}",
+ "footer" => "",
+ "buttonText" => "Reset password",
+ "buttonLink" => BASEURL . "/change-password/?token={code}"
+ );
+
+ $mailHtmlBody = MailTemplateGenerator::mailTemplate($mailTokens);
+
+ $mailPlainBody = implode("\n\n", array(
+ $mailTokens['title'],
+ $mailTokens['buttonText'],
+ $mailTokens['description'],
+ $mailTokens['footer']
+ ));
+ $mailPlainBody = $mailPlainBody;
+
+ foreach ($mailTokens as $token => $value) {
+ $mailSubject = str_replace("{" . $token . "}", $mailTokens[$token], $mailSubject);
+ $mailHtmlBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailHtmlBody);
+ $mailPlainBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailPlainBody);
}
- public static function deleteAccount() {
- $mailSubject = "Delete your account";
- $mailTokens = array(
- "title" => "Delete your account",
- "description" => "If the link does not work, copy and paste this in your browser: " . BASEURL . "/account/delete/confirm/?token={code}",
- "footer" => "",
- "buttonText" => "Delete account",
- "buttonLink" => BASEURL . "/account/delete/confirm/?token={code}"
- );
-
- $mailHtmlBody = MailTemplateGenerator::mailTemplate($mailTokens);
-
- $mailPlainBody = implode("\n\n", array(
- $mailTokens['title'],
- $mailTokens['buttonText'],
- $mailTokens['description'],
- $mailTokens['footer']
- ));
- $mailPlainBody = $mailPlainBody;
-
- foreach ($mailTokens as $token => $value) {
- $mailSubject = str_replace("{" . $token . "}", $mailTokens[$token], $mailSubject);
- $mailHtmlBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailHtmlBody);
- $mailPlainBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailPlainBody);
- }
-
- return array(
- "mailSubject" => $mailSubject,
- "mailHtmlBody" => $mailHtmlBody,
- "mailPlainBody" => $mailPlainBody
- );
+ return array(
+ "mailSubject" => $mailSubject,
+ "mailHtmlBody" => $mailHtmlBody,
+ "mailPlainBody" => $mailPlainBody
+ );
+ }
+
+ public static function deleteAccount()
+ {
+ $mailSubject = "Delete your account";
+ $mailTokens = array(
+ "title" => "Delete your account",
+ "description" => "If the link does not work, copy and paste this in your browser: " . BASEURL . "/account/delete/confirm/?token={code}",
+ "footer" => "",
+ "buttonText" => "Delete account",
+ "buttonLink" => BASEURL . "/account/delete/confirm/?token={code}"
+ );
+
+ $mailHtmlBody = MailTemplateGenerator::mailTemplate($mailTokens);
+
+ $mailPlainBody = implode("\n\n", array(
+ $mailTokens['title'],
+ $mailTokens['buttonText'],
+ $mailTokens['description'],
+ $mailTokens['footer']
+ ));
+ $mailPlainBody = $mailPlainBody;
+
+ foreach ($mailTokens as $token => $value) {
+ $mailSubject = str_replace("{" . $token . "}", $mailTokens[$token], $mailSubject);
+ $mailHtmlBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailHtmlBody);
+ $mailPlainBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailPlainBody);
}
-
- public static function accountCreated() {
- $mailTokens = array(
- "title" => "Welcome to Solid!",
- "description" => "Your online identity is ready to use. Your WebID is: {webId}",
- "footer" => "",
- );
-
- $mailSubject = "Welcome to Solid!";
-
- $mailHtmlBody = MailTemplateGenerator::mailTemplate($mailTokens);
-
- $mailPlainBody = implode("\n\n", array(
- $mailTokens['title'],
- // $mailTokens['buttonText'],
- $mailTokens['description'],
- $mailTokens['footer']
- ));
-
- foreach ($mailTokens as $token => $value) {
- $mailSubject = str_replace("{" . $token . "}", $mailTokens[$token], $mailSubject);
- $mailHtmlBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailHtmlBody);
- $mailPlainBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailPlainBody);
- }
-
- return array(
- "mailSubject" => $mailSubject,
- "mailHtmlBody" => $mailHtmlBody,
- "mailPlainBody" => $mailPlainBody
- );
+
+ return array(
+ "mailSubject" => $mailSubject,
+ "mailHtmlBody" => $mailHtmlBody,
+ "mailPlainBody" => $mailPlainBody
+ );
+ }
+
+ public static function accountCreated()
+ {
+ $mailTokens = array(
+ "title" => "Welcome to Solid!",
+ "description" => "Your online identity is ready to use. Your WebID is: {webId}",
+ "footer" => "",
+ );
+
+ $mailSubject = "Welcome to Solid!";
+
+ $mailHtmlBody = MailTemplateGenerator::mailTemplate($mailTokens);
+
+ $mailPlainBody = implode("\n\n", array(
+ $mailTokens['title'],
+ // $mailTokens['buttonText'],
+ $mailTokens['description'],
+ $mailTokens['footer']
+ ));
+
+ foreach ($mailTokens as $token => $value) {
+ $mailSubject = str_replace("{" . $token . "}", $mailTokens[$token], $mailSubject);
+ $mailHtmlBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailHtmlBody);
+ $mailPlainBody = str_replace("{" . $token . "}", $mailTokens[$token], $mailPlainBody);
}
+
+ return array(
+ "mailSubject" => $mailSubject,
+ "mailHtmlBody" => $mailHtmlBody,
+ "mailPlainBody" => $mailPlainBody
+ );
}
+}
diff --git a/lib/Mailer.php b/lib/Mailer.php
index 7d50853..aae8a83 100644
--- a/lib/Mailer.php
+++ b/lib/Mailer.php
@@ -1,143 +1,151 @@
IsSMTP();
- $mailer->CharSet = 'UTF-8';
- $mailer->Host = MAILER['host'];
- $mailer->SMTPDebug = 0;
- $mailer->Port = MAILER['port'];
- if (isset(MAILER['user'])) {
- $mailer->SMTPAuth = true;
- $mailer->Username = MAILER['user'];
- $mailer->Password = MAILER['password'];
- }
- $mailer->isHTML(true);
- $mailer->setFrom(MAILER['from']);
- $mailer->XMailer = null; // don't add PHPmailer user agent information;
- return $mailer;
+
+namespace Pdsinterop\PhpSolid;
+
+use Pdsinterop\PhpSolid\MailTemplates;
+use PHPMailer\PHPMailer\PHPMailer;
+
+class Mailer
+{
+ public static $mailer = null;
+
+ public static function getMailer()
+ {
+ if (self::$mailer) {
+ return self::$mailer;
}
-
- public static function sendAccountCreated($data) {
- $mailTemplate = MailTemplates::accountCreated();
- $mailSubject = $mailTemplate["mailSubject"];
- $mailHtmlBody = $mailTemplate["mailHtmlBody"];
- $mailPlainBody = $mailTemplate["mailPlainBody"];
-
- $mailTo = $data['email'];
- $mailTokens = array("webId", "email");
-
- foreach ($mailTokens as $token) {
- $mailSubject = str_replace("{" . $token . "}", $data[$token], $mailSubject);
- $mailHtmlBody = str_replace("{" . $token . "}", $data[$token], $mailHtmlBody);
- $mailPlainBody = str_replace("{" . $token . "}", $data[$token], $mailPlainBody);
- }
-
- // $emailCheck = "#^[a-z0-9_\+-]+(\.[a-z0-9_\+-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,4})" . '$#';
-
- $mailer = self::getMailer();
- // Content
- $mailer->addAddress($mailTo);
-
- $mailer->Subject = $mailSubject;
- $mailer->Body = $mailHtmlBody;
- $mailer->AltBody = $mailPlainBody;
-
- return $mailer->send();
+ $mailer = new PHPMailer();
+ // Settings
+ $mailer->IsSMTP();
+ $mailer->CharSet = 'UTF-8';
+ $mailer->Host = MAILER['host'];
+ $mailer->SMTPDebug = 0;
+ $mailer->Port = MAILER['port'];
+ if (isset(MAILER['user'])) {
+ $mailer->SMTPAuth = true;
+ $mailer->Username = MAILER['user'];
+ $mailer->Password = MAILER['password'];
}
+ $mailer->isHTML(true);
+ $mailer->setFrom(MAILER['from']);
+ $mailer->XMailer = null; // don't add PHPmailer user agent information;
+ return $mailer;
+ }
+
+ public static function sendAccountCreated($data)
+ {
+ $mailTemplate = MailTemplates::accountCreated();
+ $mailSubject = $mailTemplate["mailSubject"];
+ $mailHtmlBody = $mailTemplate["mailHtmlBody"];
+ $mailPlainBody = $mailTemplate["mailPlainBody"];
- public static function sendVerify($data) {
- $mailTemplate = MailTemplates::verify();
+ $mailTo = $data['email'];
+ $mailTokens = array("webId", "email");
- $mailSubject = $mailTemplate["mailSubject"];
- $mailHtmlBody = $mailTemplate["mailHtmlBody"];
- $mailPlainBody = $mailTemplate["mailPlainBody"];
+ foreach ($mailTokens as $token) {
+ $mailSubject = str_replace("{" . $token . "}", $data[$token], $mailSubject);
+ $mailHtmlBody = str_replace("{" . $token . "}", $data[$token], $mailHtmlBody);
+ $mailPlainBody = str_replace("{" . $token . "}", $data[$token], $mailPlainBody);
+ }
- $mailTo = $data['email'];
- $mailTokens = array("code", "email");
+ // $emailCheck = "#^[a-z0-9_\+-]+(\.[a-z0-9_\+-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,4})" . '$#';
- foreach ($mailTokens as $token) {
- $mailSubject = str_replace("{" . $token . "}", $data[$token], $mailSubject);
- $mailHtmlBody = str_replace("{" . $token . "}", $data[$token], $mailHtmlBody);
- $mailPlainBody = str_replace("{" . $token . "}", $data[$token], $mailPlainBody);
- }
+ $mailer = self::getMailer();
+ // Content
+ $mailer->addAddress($mailTo);
- // $emailCheck = "#^[a-z0-9_\+-]+(\.[a-z0-9_\+-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,4})" . '$#';
+ $mailer->Subject = $mailSubject;
+ $mailer->Body = $mailHtmlBody;
+ $mailer->AltBody = $mailPlainBody;
- $mailer = self::getMailer();
- // Content
- $mailer->addAddress($mailTo);
-
- $mailer->Subject = $mailSubject;
- $mailer->Body = $mailHtmlBody;
- $mailer->AltBody = $mailPlainBody;
+ return $mailer->send();
+ }
- return $mailer->send();
+ public static function sendVerify($data)
+ {
+ $mailTemplate = MailTemplates::verify();
+
+ $mailSubject = $mailTemplate["mailSubject"];
+ $mailHtmlBody = $mailTemplate["mailHtmlBody"];
+ $mailPlainBody = $mailTemplate["mailPlainBody"];
+
+ $mailTo = $data['email'];
+ $mailTokens = array("code", "email");
+
+ foreach ($mailTokens as $token) {
+ $mailSubject = str_replace("{" . $token . "}", $data[$token], $mailSubject);
+ $mailHtmlBody = str_replace("{" . $token . "}", $data[$token], $mailHtmlBody);
+ $mailPlainBody = str_replace("{" . $token . "}", $data[$token], $mailPlainBody);
}
- public static function sendResetPassword($data) {
- $mailTemplate = MailTemplates::resetPassword();
- $mailSubject = $mailTemplate["mailSubject"];
- $mailHtmlBody = $mailTemplate["mailHtmlBody"];
- $mailPlainBody = $mailTemplate["mailPlainBody"];
-
- $mailTo = $data['email'];
- $mailTokens = array("code", "email");
-
- foreach ($mailTokens as $token) {
- $mailSubject = str_replace("{" . $token . "}", $data[$token], $mailSubject);
- $mailHtmlBody = str_replace("{" . $token . "}", $data[$token], $mailHtmlBody);
- $mailPlainBody = str_replace("{" . $token . "}", $data[$token], $mailPlainBody);
- }
-
- // $emailCheck = "#^[a-z0-9_\+-]+(\.[a-z0-9_\+-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,4})" . '$#';
-
- $mailer = self::getMailer();
- // Content
- $mailer->addAddress($mailTo);
-
- $mailer->Subject = $mailSubject;
- $mailer->Body = $mailHtmlBody;
- $mailer->AltBody = $mailPlainBody;
-
- return $mailer->send();
+ // $emailCheck = "#^[a-z0-9_\+-]+(\.[a-z0-9_\+-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,4})" . '$#';
+
+ $mailer = self::getMailer();
+ // Content
+ $mailer->addAddress($mailTo);
+
+ $mailer->Subject = $mailSubject;
+ $mailer->Body = $mailHtmlBody;
+ $mailer->AltBody = $mailPlainBody;
+
+ return $mailer->send();
+ }
+
+ public static function sendResetPassword($data)
+ {
+ $mailTemplate = MailTemplates::resetPassword();
+ $mailSubject = $mailTemplate["mailSubject"];
+ $mailHtmlBody = $mailTemplate["mailHtmlBody"];
+ $mailPlainBody = $mailTemplate["mailPlainBody"];
+
+ $mailTo = $data['email'];
+ $mailTokens = array("code", "email");
+
+ foreach ($mailTokens as $token) {
+ $mailSubject = str_replace("{" . $token . "}", $data[$token], $mailSubject);
+ $mailHtmlBody = str_replace("{" . $token . "}", $data[$token], $mailHtmlBody);
+ $mailPlainBody = str_replace("{" . $token . "}", $data[$token], $mailPlainBody);
}
- public static function sendDeleteAccount($data) {
- $mailTemplate = MailTemplates::deleteAccount();
- $mailSubject = $mailTemplate["mailSubject"];
- $mailHtmlBody = $mailTemplate["mailHtmlBody"];
- $mailPlainBody = $mailTemplate["mailPlainBody"];
-
- $mailTo = $data['email'];
- $mailTokens = array("code", "email");
-
- foreach ($mailTokens as $token) {
- $mailSubject = str_replace("{" . $token . "}", $data[$token], $mailSubject);
- $mailHtmlBody = str_replace("{" . $token . "}", $data[$token], $mailHtmlBody);
- $mailPlainBody = str_replace("{" . $token . "}", $data[$token], $mailPlainBody);
- }
-
- // $emailCheck = "#^[a-z0-9_\+-]+(\.[a-z0-9_\+-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,4})" . '$#';
-
- $mailer = self::getMailer();
- // Content
- $mailer->addAddress($mailTo);
-
- $mailer->Subject = $mailSubject;
- $mailer->Body = $mailHtmlBody;
- $mailer->AltBody = $mailPlainBody;
-
- return $mailer->send();
+ // $emailCheck = "#^[a-z0-9_\+-]+(\.[a-z0-9_\+-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,4})" . '$#';
+
+ $mailer = self::getMailer();
+ // Content
+ $mailer->addAddress($mailTo);
+
+ $mailer->Subject = $mailSubject;
+ $mailer->Body = $mailHtmlBody;
+ $mailer->AltBody = $mailPlainBody;
+
+ return $mailer->send();
+ }
+
+ public static function sendDeleteAccount($data)
+ {
+ $mailTemplate = MailTemplates::deleteAccount();
+ $mailSubject = $mailTemplate["mailSubject"];
+ $mailHtmlBody = $mailTemplate["mailHtmlBody"];
+ $mailPlainBody = $mailTemplate["mailPlainBody"];
+
+ $mailTo = $data['email'];
+ $mailTokens = array("code", "email");
+
+ foreach ($mailTokens as $token) {
+ $mailSubject = str_replace("{" . $token . "}", $data[$token], $mailSubject);
+ $mailHtmlBody = str_replace("{" . $token . "}", $data[$token], $mailHtmlBody);
+ $mailPlainBody = str_replace("{" . $token . "}", $data[$token], $mailPlainBody);
}
+
+ // $emailCheck = "#^[a-z0-9_\+-]+(\.[a-z0-9_\+-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,4})" . '$#';
+
+ $mailer = self::getMailer();
+ // Content
+ $mailer->addAddress($mailTo);
+
+ $mailer->Subject = $mailSubject;
+ $mailer->Body = $mailHtmlBody;
+ $mailer->AltBody = $mailPlainBody;
+
+ return $mailer->send();
}
+}
diff --git a/lib/Middleware.php b/lib/Middleware.php
index 76cb63c..91c6c25 100644
--- a/lib/Middleware.php
+++ b/lib/Middleware.php
@@ -1,33 +1,39 @@
addPlugin(new \Pdsinterop\Rdf\Flysystem\Plugin\AsMime($formats));
- $plugin = new \Pdsinterop\Rdf\Flysystem\Plugin\ReadRdf($graph);
- $filesystem->addPlugin($plugin);
- return $filesystem;
- }
- public static function respond($response) {
- $statusCode = $response->getStatusCode();
- $response->getBody()->rewind();
- $headers = $response->getHeaders();
-
- $body = $response->getBody()->getContents();
- header("HTTP/1.1 $statusCode");
- foreach ($headers as $header => $values) {
- foreach ($values as $value) {
- if ($header == "Location") {
- $value = preg_replace("|%26%2334%3B|", "%22", $value); // odoo weird encoding
- }
- header($header . ":" . $value);
+namespace Pdsinterop\PhpSolid;
+
+use Pdsinterop\PhpSolid\Server;
+use Pdsinterop\PhpSolid\User;
+use Pdsinterop\PhpSolid\Util;
+
+class ProfileServer extends Server
+{
+ public static function getFileSystem()
+ {
+ $profileId = self::getProfileId();
+
+ // The internal adapter
+ $adapter = new \League\Flysystem\Adapter\Local(
+ // Determine root directory
+ PROFILEBASE . "$profileId/"
+ );
+
+ $graph = new \EasyRdf\Graph();
+ // Create Formats objects
+ $formats = new \Pdsinterop\Rdf\Formats();
+ $serverUri = Util::getServerUri();
+
+ // Create the RDF Adapter
+ $rdfAdapter = new \Pdsinterop\Rdf\Flysystem\Adapter\Rdf($adapter, $graph, $formats, $serverUri);
+
+ $filesystem = new \League\Flysystem\Filesystem($rdfAdapter);
+ $filesystem->addPlugin(new \Pdsinterop\Rdf\Flysystem\Plugin\AsMime($formats));
+ $plugin = new \Pdsinterop\Rdf\Flysystem\Plugin\ReadRdf($graph);
+ $filesystem->addPlugin($plugin);
+ return $filesystem;
+ }
+
+ public static function respond($response)
+ {
+ $statusCode = $response->getStatusCode();
+ $response->getBody()->rewind();
+ $headers = $response->getHeaders();
+
+ $body = $response->getBody()->getContents();
+ header("HTTP/1.1 $statusCode");
+ foreach ($headers as $header => $values) {
+ foreach ($values as $value) {
+ if ($header == "Location") {
+ $value = preg_replace("|%26%2334%3B|", "%22", $value); // odoo weird encoding
}
+ header($header . ":" . $value);
}
- echo $body;
}
+ echo $body;
+ }
- public static function getWebId($rawRequest) {
- $dpop = self::getDpop();
- $webId = $dpop->getWebId($rawRequest);
- if (!isset($webId)) {
- $bearer = self::getBearer();
- $webId = $bearer->getWebId($rawRequest);
- }
- return $webId;
+ public static function getWebId($rawRequest)
+ {
+ $dpop = self::getDpop();
+ $webId = $dpop->getWebId($rawRequest);
+ if (!isset($webId)) {
+ $bearer = self::getBearer();
+ $webId = $bearer->getWebId($rawRequest);
}
+ return $webId;
+ }
- private static function getProfileId() {
- $serverName = Util::getServerName();
- $idParts = explode(".", $serverName, 2);
- $profileId = preg_replace("/^id-/", "", $idParts[0]);
- return $profileId;
- }
-
- public static function getOwner() {
- $profileId = self::getProfileId();
- return User::getUserById($profileId);
- }
+ private static function getProfileId()
+ {
+ $serverName = Util::getServerName();
+ $idParts = explode(".", $serverName, 2);
+ $profileId = preg_replace("/^id-/", "", $idParts[0]);
+ return $profileId;
+ }
+
+ public static function getOwner()
+ {
+ $profileId = self::getProfileId();
+ return User::getUserById($profileId);
+ }
+
+ public static function getOwnerWebId()
+ {
+ $owner = self::getOwner();
+ return $owner['webId'];
+ }
- public static function getOwnerWebId() {
- $owner = self::getOwner();
- return $owner['webId'];
+ public static function initializeProfile()
+ {
+ $filesystem = self::getFilesystem();
+ if (!$filesystem->has("/.acl")) {
+ $defaultAcl = self::generateDefaultAcl();
+ $filesystem->write("/.acl", $defaultAcl);
}
-
- public static function initializeProfile() {
- $filesystem = self::getFilesystem();
- if (!$filesystem->has("/.acl")) {
- $defaultAcl = self::generateDefaultAcl();
- $filesystem->write("/.acl", $defaultAcl);
- }
- // Generate default folders and ACLs:
- if (!$filesystem->has("/profile.ttl")) {
- $profile = self::generateDefaultProfile();
- $filesystem->write("/profile.ttl", $profile);
- }
+ // Generate default folders and ACLs:
+ if (!$filesystem->has("/profile.ttl")) {
+ $profile = self::generateDefaultProfile();
+ $filesystem->write("/profile.ttl", $profile);
}
-
- public static function generateDefaultAcl() {
- $webId = self::getOwnerWebId();
- $acl = <<< "EOF"
+ }
+
+ public static function generateDefaultAcl()
+ {
+ $webId = self::getOwnerWebId();
+ $acl = <<< "EOF"
# Root ACL resource for the user account
@prefix acl: .
@prefix foaf: .
# The homepage is readable by the public
<#public>
- a acl:Authorization;
- acl:agentClass foaf:Agent;
- acl:accessTo <./>;
- # All resources will inherit this authorization, by default
- acl:default <./>;
- acl:mode acl:Read.
+a acl:Authorization;
+acl:agentClass foaf:Agent;
+acl:accessTo <./>;
+# All resources will inherit this authorization, by default
+acl:default <./>;
+acl:mode acl:Read.
# The owner has full access to every resource in their pod.
# Other agents have no access rights,
# unless specifically authorized in other .acl resources.
<#owner>
- a acl:Authorization;
- acl:agent <$webId>;
- # Set the access to the root storage folder itself
- acl:accessTo <./>;
- # All resources will inherit this authorization, by default
- acl:default <./>;
- # The owner has all of the access modes allowed
- acl:mode
- acl:Read, acl:Write, acl:Control.
+a acl:Authorization;
+acl:agent <$webId>;
+# Set the access to the root storage folder itself
+acl:accessTo <./>;
+# All resources will inherit this authorization, by default
+acl:default <./>;
+# The owner has all of the access modes allowed
+acl:mode
+ acl:Read, acl:Write, acl:Control.
EOF;
- return $acl;
- }
+ return $acl;
+ }
- public static function generateDefaultProfile() {
- $user = self::getOwner();
- if (!isset($user['storage']) || !$user['storage']) {
- $user['storage'] = "https://storage-" . self::getProfileId() . "." . BASEDOMAIN . "/";
- }
- if (is_array($user['storage'])) { // empty array is already handled
- $user['storage'] = array_values($user['storage'])[0]; // FIXME: Handle multiple storage pods
- }
- if (!isset($user['issuer'])) {
- $user['issuer'] = BASEURL;
- }
+ public static function generateDefaultProfile()
+ {
+ $user = self::getOwner();
+ if (!isset($user['storage']) || !$user['storage']) {
+ $user['storage'] = "https://storage-" . self::getProfileId() . "." . BASEDOMAIN . "/";
+ }
+ if (is_array($user['storage'])) { // empty array is already handled
+ $user['storage'] = array_values($user['storage'])[0]; // FIXME: Handle multiple storage pods
+ }
+ if (!isset($user['issuer'])) {
+ $user['issuer'] = BASEURL;
+ }
- $profile = <<< "EOF"
+ $profile = <<< "EOF"
@prefix : <#>.
@prefix acl: .
@prefix foaf: .
@@ -149,15 +160,15 @@ public static function generateDefaultProfile() {
<> a foaf:PersonalProfileDocument; foaf:maker :me; foaf:primaryTopic :me.
:me
- a schema:Person, foaf:Person;
- ldp:inbox inbox:;
- space:preferencesFile <{$user['storage']}settings/preferences.ttl>;
- space:storage <{$user['storage']}>;
- solid:account <{$user['storage']}>;
- solid:oidcIssuer <{$user['issuer']}>;
- solid:privateTypeIndex <{$user['storage']}settings/privateTypeIndex.ttl>;
- solid:publicTypeIndex <{$user['storage']}settings/publicTypeIndex.ttl>.
+a schema:Person, foaf:Person;
+ldp:inbox inbox:;
+space:preferencesFile <{$user['storage']}settings/preferences.ttl>;
+space:storage <{$user['storage']}>;
+solid:account <{$user['storage']}>;
+solid:oidcIssuer <{$user['issuer']}>;
+solid:privateTypeIndex <{$user['storage']}settings/privateTypeIndex.ttl>;
+solid:publicTypeIndex <{$user['storage']}settings/publicTypeIndex.ttl>.
EOF;
- return $profile;
- }
+ return $profile;
}
+}
diff --git a/lib/Routes/Account.php b/lib/Routes/Account.php
index 55e08df..d9fb789 100644
--- a/lib/Routes/Account.php
+++ b/lib/Routes/Account.php
@@ -1,190 +1,202 @@
$_POST['email']
- ];
+ public static function respondToAccountVerify()
+ {
+ $verifyData = [
+ 'email' => $_POST['email']
+ ];
- $verifyToken = User::saveVerifyToken('verify', $verifyData);
- Mailer::sendVerify($verifyToken);
+ $verifyToken = User::saveVerifyToken('verify', $verifyData);
+ Mailer::sendVerify($verifyToken);
- $responseData = "OK";
- header("HTTP/1.1 201 Created");
- header("Content-type: application/json");
- echo json_encode($responseData, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
+ $responseData = "OK";
+ header("HTTP/1.1 201 Created");
+ header("Content-type: application/json");
+ echo json_encode($responseData, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
+ }
+
+ public static function respondToAccountNew()
+ {
+ $verifyToken = User::getVerifyToken($_POST['confirm']);
+ if (!$verifyToken) {
+ error_log("Could not read verify token");
+ header("HTTP/1.1 400 Bad Request");
+ exit();
+ }
+ if ($verifyToken['email'] !== $_POST['email']) {
+ error_log("Verify token does not match email");
+ header("HTTP/1.1 400 Bad Request");
+ exit();
+ }
+ if (User::userEmailExists($_POST['email'])) {
+ error_log("Account already exists");
+ header("HTTP/1.1 400 Bad Request");
+ exit();
+ }
+ if (!$_POST['password'] === $_POST['repeat_password']) {
+ error_log("Password repeat does not match");
+ header("HTTP/1.1 400 Bad Request");
+ exit();
}
- public static function respondToAccountNew() {
- $verifyToken = User::getVerifyToken($_POST['confirm']);
- if (!$verifyToken) {
- error_log("Could not read verify token");
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
- if ($verifyToken['email'] !== $_POST['email']) {
- error_log("Verify token does not match email");
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
- if (User::userEmailExists($_POST['email'])) {
- error_log("Account already exists");
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
- if (!$_POST['password'] === $_POST['repeat_password']) {
- error_log("Password repeat does not match");
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
+ $newUser = [
+ "email" => $_POST['email'],
+ "password" => $_POST['password']
+ ];
- $newUser = [
- "email" => $_POST['email'],
- "password" => $_POST['password']
- ];
+ $createdUser = User::createUser($newUser);
+ if (!$createdUser) {
+ error_log("Failed to create user");
+ header("HTTP/1.1 400 Bad Request");
+ exit();
+ }
+ $createdStorage = StorageServer::createStorage($createdUser['webId']);
+ User::setStorage($createdUser['userId'], $createdStorage['storageUrl']);
- $createdUser = User::createUser($newUser);
- if (!$createdUser) {
- error_log("Failed to create user");
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
- $createdStorage = StorageServer::createStorage($createdUser['webId']);
- User::setStorage($createdUser['userId'], $createdStorage['storageUrl']);
+ Mailer::sendAccountCreated($createdUser);
- Mailer::sendAccountCreated($createdUser);
+ $responseData = array(
+ "webId" => $createdUser['webId'],
+ "storageUrl" => $createdStorage['storageUrl']
+ );
- $responseData = array(
- "webId" => $createdUser['webId'],
- "storageUrl" => $createdStorage['storageUrl']
- );
+ header("HTTP/1.1 201 Created");
+ header("Content-type: application/json");
+ Session::start($_POST['email']);
+ echo json_encode($responseData, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
+ }
- header("HTTP/1.1 201 Created");
+ public static function respondToAccountResetPassword()
+ {
+ if (!User::userEmailExists($_POST['email'])) {
+ header("HTTP/1.1 200 OK"); // Return OK even when user is not found;
header("Content-type: application/json");
- Session::start($_POST['email']);
- echo json_encode($responseData, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
+ echo json_encode("OK");
+ exit();
}
-
- public static function respondToAccountResetPassword() {
- if (!User::userEmailExists($_POST['email'])) {
- header("HTTP/1.1 200 OK"); // Return OK even when user is not found;
- header("Content-type: application/json");
- echo json_encode("OK");
- exit();
- }
- $verifyData = [
- 'email' => $_POST['email']
- ];
+ $verifyData = [
+ 'email' => $_POST['email']
+ ];
- $verifyToken = User::saveVerifyToken('passwordReset', $verifyData);
- Mailer::sendResetPassword($verifyToken);
- header("HTTP/1.1 200 OK");
- header("Content-type: application/json");
- echo json_encode("OK");
+ $verifyToken = User::saveVerifyToken('passwordReset', $verifyData);
+ Mailer::sendResetPassword($verifyToken);
+ header("HTTP/1.1 200 OK");
+ header("Content-type: application/json");
+ echo json_encode("OK");
+ }
+
+ public static function respondToAccountChangePassword()
+ {
+ $verifyToken = User::getVerifyToken($_POST['token']);
+ if (!$verifyToken) {
+ header("HTTP/1.1 400 Bad Request");
+ exit();
}
-
- public static function respondToAccountChangePassword() {
- $verifyToken = User::getVerifyToken($_POST['token']);
- if (!$verifyToken) {
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
- $result = User::setUserPassword($verifyToken['email'], $_POST['newPassword']);
- if (!$result) {
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
- header("HTTP/1.1 200 OK");
- header("Content-type: application/json");
- echo json_encode("OK");
+ $result = User::setUserPassword($verifyToken['email'], $_POST['newPassword']);
+ if (!$result) {
+ header("HTTP/1.1 400 Bad Request");
+ exit();
}
-
- public static function respondToAccountDelete() {
- if (!User::userEmailExists($_POST['email'])) {
- header("HTTP/1.1 200 OK"); // Return OK even when user is not found;
- header("Content-type: application/json");
- echo json_encode("OK");
- exit();
- }
- $verifyData = [
- 'email' => $_POST['email']
- ];
+ header("HTTP/1.1 200 OK");
+ header("Content-type: application/json");
+ echo json_encode("OK");
+ }
- $verifyToken = User::saveVerifyToken('deleteAccount', $verifyData);
- Mailer::sendDeleteAccount($verifyToken);
- header("HTTP/1.1 200 OK");
+ public static function respondToAccountDelete()
+ {
+ if (!User::userEmailExists($_POST['email'])) {
+ header("HTTP/1.1 200 OK"); // Return OK even when user is not found;
header("Content-type: application/json");
echo json_encode("OK");
+ exit();
}
-
- public static function respondToAccountDeleteConfirm() {
- $verifyToken = User::getVerifyToken($_POST['token']);
- if (!$verifyToken) {
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
- User::deleteAccount($verifyToken['email']);
- header("HTTP/1.1 200 OK");
- header("Content-type: application/json");
- echo json_encode("OK");
+ $verifyData = [
+ 'email' => $_POST['email']
+ ];
+
+ $verifyToken = User::saveVerifyToken('deleteAccount', $verifyData);
+ Mailer::sendDeleteAccount($verifyToken);
+ header("HTTP/1.1 200 OK");
+ header("Content-type: application/json");
+ echo json_encode("OK");
+ }
+
+ public static function respondToAccountDeleteConfirm()
+ {
+ $verifyToken = User::getVerifyToken($_POST['token']);
+ if (!$verifyToken) {
+ header("HTTP/1.1 400 Bad Request");
+ exit();
+ }
+ User::deleteAccount($verifyToken['email']);
+ header("HTTP/1.1 200 OK");
+ header("Content-type: application/json");
+ echo json_encode("OK");
+ }
+
+ public static function respondToLogin()
+ {
+ $failureCount = IpAttempts::getAttemptsCount($_SERVER['REMOTE_ADDR'], "login");
+ if ($failureCount > 5) {
+ header("HTTP/1.1 400 Bad Request");
+ exit();
}
-
- public static function respondToLogin() {
- $failureCount = IpAttempts::getAttemptsCount($_SERVER['REMOTE_ADDR'], "login");
- if ($failureCount > 5) {
- header("HTTP/1.1 400 Bad Request");
+ if (User::checkPassword($_POST['username'], $_POST['password'])) {
+ Session::start($_POST['username']);
+ $user = User::getUser($_POST['username']);
+ if (!isset($_POST['redirect_uri']) || $_POST['redirect_uri'] === '') {
+ header("Location: /dashboard/#autologin/" . urlencode($user['webId']));
exit();
}
- if (User::checkPassword($_POST['username'], $_POST['password'])) {
- Session::start($_POST['username']);
- $user = User::getUser($_POST['username']);
- if (!isset($_POST['redirect_uri']) || $_POST['redirect_uri'] === '') {
- header("Location: /dashboard/#autologin/" . urlencode($user['webId']));
- exit();
- }
- header("Location: " . urldecode($_POST['redirect_uri'])); // FIXME: Do we need to harden this?
- } else {
- IpAttempts::logFailedAttempt($_SERVER['REMOTE_ADDR'], "login", time() + 3600);
- header("Location: /login/");
- }
+ header("Location: " . urldecode($_POST['redirect_uri'])); // FIXME: Do we need to harden this?
+ } else {
+ IpAttempts::logFailedAttempt($_SERVER['REMOTE_ADDR'], "login", time() + 3600);
+ header("Location: /login/");
}
}
+}
diff --git a/lib/Routes/SolidIdp.php b/lib/Routes/SolidIdp.php
index 6cc3225..9e628bc 100644
--- a/lib/Routes/SolidIdp.php
+++ b/lib/Routes/SolidIdp.php
@@ -1,220 +1,230 @@
respondToJwksMetadataRequest();
- Server::respond($response);
+
+// phpcs:disable Generic.Files.LineLength.TooLong
+
+namespace Pdsinterop\PhpSolid\Routes;
+
+use Pdsinterop\PhpSolid\Server;
+use Pdsinterop\PhpSolid\ClientRegistration;
+use Pdsinterop\PhpSolid\User;
+use Pdsinterop\PhpSolid\Session;
+
+class SolidIdp
+{
+ public static function respondToJwks()
+ {
+ $authServer = Server::getAuthServer();
+ $response = $authServer->respondToJwksMetadataRequest();
+ Server::respond($response);
+ }
+
+ public static function respondToWellKnownOpenIdConfiguration()
+ {
+ $authServer = Server::getAuthServer();
+ $response = $authServer->respondToOpenIdMetadataRequest();
+ Server::respond($response);
+ }
+
+ public static function respondToAuthorize()
+ {
+ $user = User::getUser(Session::getLoggedInUser());
+
+ $clientId = $_GET['client_id'];
+ $getVars = $_GET;
+
+ if (!isset($getVars['grant_type'])) {
+ $getVars['grant_type'] = 'implicit';
}
+ $getVars['scope'] = "openid" ;
+ $getVars['response_type'] = "token";
- public static function respondToWellKnownOpenIdConfiguration() {
- $authServer = Server::getAuthServer();
- $response = $authServer->respondToOpenIdMetadataRequest();
- Server::respond($response);
+ $requestedResponseTypes = explode(" ", ($_GET['response_type'] ?? ''));
+ if (in_array("code", $requestedResponseTypes)) {
+ $getVars['response_type'] = "code";
}
- public static function respondToAuthorize() {
- $user = User::getUser(Session::getLoggedInUser());
+ $keys = Server::getKeys();
+ if (isset($_GET['request'])) {
+ $jwtConfig = \Lcobucci\JWT\Configuration::forSymmetricSigner(
+ new \Lcobucci\JWT\Signer\Rsa\Sha256(),
+ \Lcobucci\JWT\Signer\Key\InMemory::plainText($keys['privateKey'])
+ );
- $clientId = $_GET['client_id'];
- $getVars = $_GET;
-
- if (!isset($getVars['grant_type'])) {
- $getVars['grant_type'] = 'implicit';
+ if (isset($_GET['nonce'])) {
+ $_SESSION['nonce'] = $_GET['nonce'];
+ } else if (isset($_GET['request'])) {
+ $token = $jwtConfig->parser()->parse($_GET['request']);
+ $_SESSION['nonce'] = $token->claims()->get('nonce');
}
- $getVars['scope'] = "openid" ;
- $getVars['response_type'] = "token";
-
- $requestedResponseTypes = explode(" ", ($_GET['response_type'] ?? ''));
- if (in_array("code", $requestedResponseTypes)) {
- $getVars['response_type'] = "code";
- }
-
- $keys = Server::getKeys();
- if (isset($_GET['request'])) {
- $jwtConfig = \Lcobucci\JWT\Configuration::forSymmetricSigner(
- new \Lcobucci\JWT\Signer\Rsa\Sha256(),
- \Lcobucci\JWT\Signer\Key\InMemory::plainText($keys['privateKey']
- ));
-
- if (isset($_GET['nonce'])) {
- $_SESSION['nonce'] = $_GET['nonce'];
- } else if (isset($_GET['request'])) {
- $token = $jwtConfig->parser()->parse($_GET['request']);
- $_SESSION['nonce'] = $token->claims()->get('nonce');
- }
- if (!isset($getVars["redirect_uri"])) {
- if (isset($token)) {
- $getVars['redirect_uri'] = $token->claims()->get("redirect_uri");
- }
+ if (!isset($getVars["redirect_uri"])) {
+ if (isset($token)) {
+ $getVars['redirect_uri'] = $token->claims()->get("redirect_uri");
}
}
+ }
- $requestFactory = new \Laminas\Diactoros\ServerRequestFactory();
- $request = $requestFactory->fromGlobals($_SERVER, $getVars, $_POST, $_COOKIE, $_FILES);
+ $requestFactory = new \Laminas\Diactoros\ServerRequestFactory();
+ $request = $requestFactory->fromGlobals($_SERVER, $getVars, $_POST, $_COOKIE, $_FILES);
- $authServer = Server::getAuthServer();
-
- $approval = false;
- // check clientId approval for the user
- if (in_array($clientId, ($user['allowedClients'] ?? []))) {
- $approval = true;
- } else {
- $clientRegistration = ClientRegistration::getRegistration($clientId);
- if (isset($clientRegistration['origin']) && in_array($clientRegistration['origin'], TRUSTED_APPS)) {
- $approval = true;
- }
- }
+ $authServer = Server::getAuthServer();
- if (!$approval) {
- header('Location: ' . BASEURL . '/sharing/' . "?" . http_build_query(
- array(
- "returnUrl" => urlencode($_SERVER["REQUEST_URI"]),
- "client_id" => $clientId,
- "redirect_uri" => $getVars['redirect_uri']
- )
- ));
- exit();
- }
-
- $webId = "https://id-" . $user['userId'] . "." . BASEDOMAIN . "/#me";
- $user = new \Pdsinterop\Solid\Auth\Entity\User();
- $user->setIdentifier($webId);
-
- $response = $authServer->respondToAuthorizationRequest($request, $user, $approval);
-
- if (in_array("id_token", $requestedResponseTypes)) {
- $tokenGenerator = Server::getTokenGenerator();
-
- $response = $tokenGenerator->addIdTokenToResponse(
- $response,
- $clientId,
- $webId,
- $_SESSION['nonce'] ?? '',
- Server::getKeys()["privateKey"]
- );
+ $approval = false;
+ // check clientId approval for the user
+ if (in_array($clientId, ($user['allowedClients'] ?? []))) {
+ $approval = true;
+ } else {
+ $clientRegistration = ClientRegistration::getRegistration($clientId);
+ if (isset($clientRegistration['origin']) && in_array($clientRegistration['origin'], TRUSTED_APPS)) {
+ $approval = true;
}
+ }
- Server::respond($response);
+ if (!$approval) {
+ header('Location: ' . BASEURL . '/sharing/' . "?" . http_build_query(
+ array(
+ "returnUrl" => urlencode($_SERVER["REQUEST_URI"]),
+ "client_id" => $clientId,
+ "redirect_uri" => $getVars['redirect_uri']
+ )
+ ));
+ exit();
}
- public static function respondToRegister() {
- $postData = file_get_contents("php://input");
- $clientData = json_decode($postData, true);
- if (!isset($clientData)) {
- header("HTTP/1.1 400 Bad request");
- return;
- }
- $parsedOrigin = parse_url($clientData['redirect_uris'][0]); // FIXME: Should we have multiple origins?
- $origin = $parsedOrigin['scheme'] . '://' . $parsedOrigin['host'];
- if (isset($parsedOrigin['port'])) {
- $origin .= ":" . $parsedOrigin['port'];
- }
+ $webId = "https://id-" . $user['userId'] . "." . BASEDOMAIN . "/#me";
+ $user = new \Pdsinterop\Solid\Auth\Entity\User();
+ $user->setIdentifier($webId);
+ $response = $authServer->respondToAuthorizationRequest($request, $user, $approval);
- $generatedClientId = bin2hex(random_bytes(16)); // 32 chars for the client Id
- $generatedClientSecret = bin2hex(random_bytes(32)); // and 64 chars for the client secret
-
- $clientData['client_id_issued_at'] = time();
- $clientData['client_id'] = $generatedClientId;
- $clientData['client_secret'] = $generatedClientSecret;
- $clientData['origin'] = $origin;
- ClientRegistration::saveClientRegistration($clientData);
-
- $client = ClientRegistration::getRegistration($generatedClientId);
-
- $responseData = array(
- 'redirect_uris' => $client['redirect_uris'],
- 'client_id' => $client['client_id'],
- 'client_secret' => $client['client_secret'],
- 'response_types' => array('code'),
- 'grant_types' => array('authorization_code', 'refresh_token'),
- 'application_type' => $client['application_type'] ?? 'web',
- 'client_name' => $client['client_name'] ?? $client['client_id'],
- 'id_token_signed_response_alg' => 'RS256',
- 'token_endpoint_auth_method' => 'client_secret_basic',
- 'client_id_issued_at' => $client['client_id_issued_at'],
- 'client_secret_expires_at' => 0
+ if (in_array("id_token", $requestedResponseTypes)) {
+ $tokenGenerator = Server::getTokenGenerator();
+
+ $response = $tokenGenerator->addIdTokenToResponse(
+ $response,
+ $clientId,
+ $webId,
+ $_SESSION['nonce'] ?? '',
+ Server::getKeys()["privateKey"]
);
- header("HTTP/1.1 201 Created");
- header("Content-type: application/json");
- echo json_encode($responseData, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
}
-
- public static function respondToSharing() {
- $user = User::getUser(Session::getLoggedInUser());
- $clientId = $_POST['client_id'];
- $userId = $user['userId'];
- if ($_POST['consent'] === 'true') {
- User::allowClientForUser($clientId, $userId);
- }
- $returnUrl = urldecode($_POST['returnUrl']);
- header("Location: $returnUrl");
+
+ Server::respond($response);
+ }
+
+ public static function respondToRegister()
+ {
+ $postData = file_get_contents("php://input");
+ $clientData = json_decode($postData, true);
+ if (!isset($clientData)) {
+ header("HTTP/1.1 400 Bad request");
+ return;
+ }
+ $parsedOrigin = parse_url($clientData['redirect_uris'][0]); // FIXME: Should we have multiple origins?
+ $origin = $parsedOrigin['scheme'] . '://' . $parsedOrigin['host'];
+ if (isset($parsedOrigin['port'])) {
+ $origin .= ":" . $parsedOrigin['port'];
}
-
- public static function respondToToken() {
- $authServer = Server::getAuthServer();
- $tokenGenerator = Server::getTokenGenerator();
- $requestFactory = new \Laminas\Diactoros\ServerRequestFactory();
- $request = $requestFactory->fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
- $requestBody = $request->getParsedBody();
-
- $grantType = $requestBody['grant_type'] ?? null;
- $clientId = $requestBody['client_id'] ?? null;
- switch ($grantType) {
- case "authorization_code":
- $code = $requestBody['code'];
- $codeInfo = $tokenGenerator->getCodeInfo($code);
- $userId = $codeInfo['user_id'];
- if (!$clientId) {
- $clientId = $codeInfo['client_id'];
- }
- break;
- case "refresh_token":
- $refreshToken = $requestBody['refresh_token'];
- $tokenInfo = $tokenGenerator->getCodeInfo($refreshToken); // FIXME: getCodeInfo should be named 'decrypt' or 'getInfo'?
- $userId = $tokenInfo['user_id'];
- if (!$clientId) {
- $clientId = $tokenInfo['client_id'];
- }
- break;
- default:
- $userId = false;
- break;
- }
-
- $httpDpop = $request->getServerParams()['HTTP_DPOP'];
-
- $response = $authServer->respondToAccessTokenRequest($request);
-
- if (isset($userId)) {
- $response = $tokenGenerator->addIdTokenToResponse(
- $response,
- $clientId,
- $userId,
- ($_SESSION['nonce'] ?? ''),
- Server::getKeys()['privateKey'],
- $httpDpop
- );
- }
- // Hack for podpro
- if (PODPRO_COMPATIBILITY && strstr($clientId, "podpro.dev")) {
- $response->getBody()->rewind();
- $responseBody = $response->getBody()->getContents();
- $body = json_decode($responseBody, true);
- $body['refresh_token'] = str_repeat('a', 209); // Podpro doesn't like refresh tokens longer than 209 characters; Sad.
- Server::respondPodPro($response, $body);
- } else {
- Server::respond($response);
- }
+ $generatedClientId = bin2hex(random_bytes(16)); // 32 chars for the client Id
+ $generatedClientSecret = bin2hex(random_bytes(32)); // and 64 chars for the client secret
+
+ $clientData['client_id_issued_at'] = time();
+ $clientData['client_id'] = $generatedClientId;
+ $clientData['client_secret'] = $generatedClientSecret;
+ $clientData['origin'] = $origin;
+ ClientRegistration::saveClientRegistration($clientData);
+
+ $client = ClientRegistration::getRegistration($generatedClientId);
+
+ $responseData = array(
+ 'redirect_uris' => $client['redirect_uris'],
+ 'client_id' => $client['client_id'],
+ 'client_secret' => $client['client_secret'],
+ 'response_types' => array('code'),
+ 'grant_types' => array('authorization_code', 'refresh_token'),
+ 'application_type' => $client['application_type'] ?? 'web',
+ 'client_name' => $client['client_name'] ?? $client['client_id'],
+ 'id_token_signed_response_alg' => 'RS256',
+ 'token_endpoint_auth_method' => 'client_secret_basic',
+ 'client_id_issued_at' => $client['client_id_issued_at'],
+ 'client_secret_expires_at' => 0
+ );
+ header("HTTP/1.1 201 Created");
+ header("Content-type: application/json");
+ echo json_encode($responseData, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
+ }
+
+ public static function respondToSharing()
+ {
+ $user = User::getUser(Session::getLoggedInUser());
+ $clientId = $_POST['client_id'];
+ $userId = $user['userId'];
+ if ($_POST['consent'] === 'true') {
+ User::allowClientForUser($clientId, $userId);
+ }
+ $returnUrl = urldecode($_POST['returnUrl']);
+ header("Location: $returnUrl");
+ }
+
+ public static function respondToToken()
+ {
+ $authServer = Server::getAuthServer();
+ $tokenGenerator = Server::getTokenGenerator();
+
+ $requestFactory = new \Laminas\Diactoros\ServerRequestFactory();
+ $request = $requestFactory->fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
+ $requestBody = $request->getParsedBody();
+
+ $grantType = $requestBody['grant_type'] ?? null;
+ $clientId = $requestBody['client_id'] ?? null;
+ switch ($grantType) {
+ case "authorization_code":
+ $code = $requestBody['code'];
+ $codeInfo = $tokenGenerator->getCodeInfo($code);
+ $userId = $codeInfo['user_id'];
+ if (!$clientId) {
+ $clientId = $codeInfo['client_id'];
+ }
+ break;
+ case "refresh_token":
+ $refreshToken = $requestBody['refresh_token'];
+ $tokenInfo = $tokenGenerator->getCodeInfo($refreshToken); // FIXME: getCodeInfo should be named 'decrypt' or 'getInfo'?
+ $userId = $tokenInfo['user_id'];
+ if (!$clientId) {
+ $clientId = $tokenInfo['client_id'];
+ }
+ break;
+ default:
+ $userId = false;
+ break;
+ }
+
+ $httpDpop = $request->getServerParams()['HTTP_DPOP'];
+
+ $response = $authServer->respondToAccessTokenRequest($request);
+
+ if (isset($userId)) {
+ $response = $tokenGenerator->addIdTokenToResponse(
+ $response,
+ $clientId,
+ $userId,
+ ($_SESSION['nonce'] ?? ''),
+ Server::getKeys()['privateKey'],
+ $httpDpop
+ );
+ }
+
+ // Hack for podpro
+ if (PODPRO_COMPATIBILITY && strstr($clientId, "podpro.dev")) {
+ $response->getBody()->rewind();
+ $responseBody = $response->getBody()->getContents();
+ $body = json_decode($responseBody, true);
+ $body['refresh_token'] = str_repeat('a', 209); // Podpro doesn't like refresh tokens longer than 209 characters; Sad.
+ Server::respondPodPro($response, $body);
+ } else {
+ Server::respond($response);
}
}
+}
diff --git a/lib/Routes/SolidStorage.php b/lib/Routes/SolidStorage.php
index 1201725..8f942a8 100644
--- a/lib/Routes/SolidStorage.php
+++ b/lib/Routes/SolidStorage.php
@@ -1,86 +1,88 @@
fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
-
- try {
- StorageServer::initializeStorage();
- $filesystem = StorageServer::getFileSystem();
- } catch (\Exception $e) {
- $response = new Response();
- $response = $response->withStatus(404, "Not found");
- StorageServer::respond($response);
- exit();
- }
-
- $resourceServer = new ResourceServer($filesystem, new Response(), null);
- $solidNotifications = new SolidNotifications();
- $resourceServer->setNotifications($solidNotifications);
-
- $wac = new WAC($filesystem);
-
- $baseUrl = Util::getServerBaseUrl();
- $resourceServer->setBaseUrl($baseUrl);
- $wac->setBaseUrl($baseUrl);
-
- try {
- $webId = StorageServer::getWebId($rawRequest);
- } catch(\Exception $e) {
- $response = $resourceServer->getResponse()
- -> withStatus(400, "Bad request");
- StorageServer::respond($response);
- exit();
- }
-
- if (!isset($webId)) {
- $response = $resourceServer->getResponse()
- ->withStatus(409, "Invalid token");
- StorageServer::respond($response);
- exit();
- }
-
- $origin = $rawRequest->getHeaderLine("Origin");
-
- // FIXME: Read allowed clients from the profile instead;
-
- $ownerWebId = StorageServer::getOwnerWebId();
- $owner = User::getUserByWebId($ownerWebId);
-
- $allowedClients = $owner['allowedClients'] ?? [];
- $allowedOrigins = array_merge(
- ($owner['allowedOrigins'] ?? []),
- (TRUSTED_APPS ?? [])
- );
- $allowedOrigins = array_unique($allowedOrigins);
-
- if (!isset($origin) || ($origin === "")) {
- $allowedOrigins[] = "app://unset"; // FIXME: this should not be here.
- $origin = "app://unset";
- }
-
- if (!$wac->isAllowed($rawRequest, $webId, $origin, $allowedOrigins)) {
- $response = new Response();
- $response = $response->withStatus(403, "Access denied!");
- StorageServer::respond($response);
- exit();
- }
-
- $response = $resourceServer->respondToRequest($rawRequest);
- $response = $wac->addWACHeaders($rawRequest, $response, $webId);
+
+namespace Pdsinterop\PhpSolid\Routes;
+
+use Pdsinterop\PhpSolid\User;
+use Pdsinterop\PhpSolid\StorageServer;
+use Pdsinterop\PhpSolid\ClientRegistration;
+use Pdsinterop\PhpSolid\SolidNotifications;
+use Pdsinterop\PhpSolid\Util;
+use Pdsinterop\Solid\Auth\WAC;
+use Pdsinterop\Solid\Resources\Server as ResourceServer;
+use Laminas\Diactoros\ServerRequestFactory;
+use Laminas\Diactoros\Response;
+
+class SolidStorage
+{
+ public static function respondToStorage()
+ {
+ $requestFactory = new ServerRequestFactory();
+ $rawRequest = $requestFactory->fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
+
+ try {
+ StorageServer::initializeStorage();
+ $filesystem = StorageServer::getFileSystem();
+ } catch (\Exception $e) {
+ $response = new Response();
+ $response = $response->withStatus(404, "Not found");
+ StorageServer::respond($response);
+ exit();
+ }
+
+ $resourceServer = new ResourceServer($filesystem, new Response(), null);
+ $solidNotifications = new SolidNotifications();
+ $resourceServer->setNotifications($solidNotifications);
+
+ $wac = new WAC($filesystem);
+
+ $baseUrl = Util::getServerBaseUrl();
+ $resourceServer->setBaseUrl($baseUrl);
+ $wac->setBaseUrl($baseUrl);
+
+ try {
+ $webId = StorageServer::getWebId($rawRequest);
+ } catch (\Exception $e) {
+ $response = $resourceServer->getResponse()
+ -> withStatus(400, "Bad request");
StorageServer::respond($response);
+ exit();
}
+
+ if (!isset($webId)) {
+ $response = $resourceServer->getResponse()
+ ->withStatus(409, "Invalid token");
+ StorageServer::respond($response);
+ exit();
+ }
+
+ $origin = $rawRequest->getHeaderLine("Origin");
+
+ // FIXME: Read allowed clients from the profile instead;
+
+ $ownerWebId = StorageServer::getOwnerWebId();
+ $owner = User::getUserByWebId($ownerWebId);
+
+ $allowedClients = $owner['allowedClients'] ?? [];
+ $allowedOrigins = array_merge(
+ ($owner['allowedOrigins'] ?? []),
+ (TRUSTED_APPS ?? [])
+ );
+ $allowedOrigins = array_unique($allowedOrigins);
+
+ if (!isset($origin) || ($origin === "")) {
+ $allowedOrigins[] = "app://unset"; // FIXME: this should not be here.
+ $origin = "app://unset";
+ }
+
+ if (!$wac->isAllowed($rawRequest, $webId, $origin, $allowedOrigins)) {
+ $response = new Response();
+ $response = $response->withStatus(403, "Access denied!");
+ StorageServer::respond($response);
+ exit();
+ }
+
+ $response = $resourceServer->respondToRequest($rawRequest);
+ $response = $wac->addWACHeaders($rawRequest, $response, $webId);
+ StorageServer::respond($response);
}
-
\ No newline at end of file
+}
diff --git a/lib/Routes/SolidStorageProvider.php b/lib/Routes/SolidStorageProvider.php
index 6bc3a31..d20eec5 100644
--- a/lib/Routes/SolidStorageProvider.php
+++ b/lib/Routes/SolidStorageProvider.php
@@ -1,35 +1,37 @@
fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
- $webId = StorageServer::getWebId($rawRequest);
+use Pdsinterop\PhpSolid\StorageServer;
+use Laminas\Diactoros\ServerRequestFactory;
- if (!isset($webId) || $webId === "public") {
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
+class SolidStorageProvider
+{
+ public static function respondToStorageNew()
+ {
+ $requestFactory = new ServerRequestFactory();
+ $rawRequest = $requestFactory->fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
+ $webId = StorageServer::getWebId($rawRequest);
- // FIXME: Get the webID issuer and validate that we allow storage creation for that issuer
+ if (!isset($webId) || $webId === "public") {
+ header("HTTP/1.1 400 Bad Request");
+ exit();
+ }
- $createdStorage = StorageServer::createStorage($webId);
- if (!$createdStorage) {
- error_log("Failed to create storage");
- header("HTTP/1.1 400 Bad Request");
- exit();
- }
+ // FIXME: Get the webID issuer and validate that we allow storage creation for that issuer
- $responseData = array(
- "storage" => $createdStorage['storageUrl']
- );
- header("HTTP/1.1 201 Created");
- header("Content-type: application/json");
- echo json_encode($responseData, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
+ $createdStorage = StorageServer::createStorage($webId);
+ if (!$createdStorage) {
+ error_log("Failed to create storage");
+ header("HTTP/1.1 400 Bad Request");
+ exit();
}
+
+ $responseData = array(
+ "storage" => $createdStorage['storageUrl']
+ );
+ header("HTTP/1.1 201 Created");
+ header("Content-type: application/json");
+ echo json_encode($responseData, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
}
-
\ No newline at end of file
+}
diff --git a/lib/Routes/SolidUserProfile.php b/lib/Routes/SolidUserProfile.php
index f650917..d900458 100644
--- a/lib/Routes/SolidUserProfile.php
+++ b/lib/Routes/SolidUserProfile.php
@@ -1,71 +1,73 @@
fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
- ProfileServer::initializeProfile();
- $filesystem = ProfileServer::getFileSystem();
+class SolidUserProfile
+{
+ public static function respondToProfile()
+ {
+ $requestFactory = new ServerRequestFactory();
+ $serverData = $_SERVER;
- $resourceServer = new ResourceServer($filesystem, new Response(), null);
- $solidNotifications = new SolidNotifications();
- $resourceServer->setNotifications($solidNotifications);
+ $rawRequest = $requestFactory->fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
+ ProfileServer::initializeProfile();
+ $filesystem = ProfileServer::getFileSystem();
- $wac = new WAC($filesystem);
+ $resourceServer = new ResourceServer($filesystem, new Response(), null);
+ $solidNotifications = new SolidNotifications();
+ $resourceServer->setNotifications($solidNotifications);
- $baseUrl = Util::getServerBaseUrl();
- $resourceServer->setBaseUrl($baseUrl);
- $resourceServer->lockToPath("/profile.ttl");
- $wac->setBaseUrl($baseUrl);
+ $wac = new WAC($filesystem);
- // use the original $_SERVER without modified path, otherwise the htu check for DPOP will fail
- $webId = ProfileServer::getWebId($requestFactory->fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES));
+ $baseUrl = Util::getServerBaseUrl();
+ $resourceServer->setBaseUrl($baseUrl);
+ $resourceServer->lockToPath("/profile.ttl");
+ $wac->setBaseUrl($baseUrl);
- if (!isset($webId)) {
- $response = $resourceServer->getResponse()
- ->withStatus(409, "Invalid token");
- ProfileServer::respond($response);
- exit();
- }
+ // use the original $_SERVER without modified path, otherwise the htu check for DPOP will fail
+ $webId = ProfileServer::getWebId($requestFactory->fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES));
- $origin = $rawRequest->getHeaderLine("Origin");
+ if (!isset($webId)) {
+ $response = $resourceServer->getResponse()
+ ->withStatus(409, "Invalid token");
+ ProfileServer::respond($response);
+ exit();
+ }
- // FIXME: Read allowed clients from the profile instead;
- $owner = ProfileServer::getOwner();
+ $origin = $rawRequest->getHeaderLine("Origin");
- $allowedClients = $owner['allowedClients'] ?? [];
- $allowedOrigins = array_merge(
- ($owner['allowedOrigins'] ?? []),
- (TRUSTED_APPS ?? [])
- );
- $allowedOrigins = array_unique($allowedOrigins);
- if (!isset($origin) || ($origin === "")) {
- $allowedOrigins[] = "app://unset"; // FIXME: this should not be here.
- $origin = "app://unset";
- }
+ // FIXME: Read allowed clients from the profile instead;
+ $owner = ProfileServer::getOwner();
- if (!$wac->isAllowed($rawRequest, $webId, $origin, $allowedOrigins)) {
- $response = new Response();
- $response = $response->withStatus(403, "Access denied!");
- ProfileServer::respond($response);
- exit();
- }
+ $allowedClients = $owner['allowedClients'] ?? [];
+ $allowedOrigins = array_merge(
+ ($owner['allowedOrigins'] ?? []),
+ (TRUSTED_APPS ?? [])
+ );
+ $allowedOrigins = array_unique($allowedOrigins);
+ if (!isset($origin) || ($origin === "")) {
+ $allowedOrigins[] = "app://unset"; // FIXME: this should not be here.
+ $origin = "app://unset";
+ }
- $response = $resourceServer->respondToRequest($rawRequest);
- $response = $wac->addWACHeaders($rawRequest, $response, $webId);
+ if (!$wac->isAllowed($rawRequest, $webId, $origin, $allowedOrigins)) {
+ $response = new Response();
+ $response = $response->withStatus(403, "Access denied!");
ProfileServer::respond($response);
+ exit();
}
+
+ $response = $resourceServer->respondToRequest($rawRequest);
+ $response = $wac->addWACHeaders($rawRequest, $response, $webId);
+ ProfileServer::respond($response);
}
-
\ No newline at end of file
+}
diff --git a/lib/Server.php b/lib/Server.php
index ab128a8..204f5ab 100644
--- a/lib/Server.php
+++ b/lib/Server.php
@@ -1,183 +1,196 @@
"sha256",
- "private_key_bits" => 2048,
- "private_key_type" => OPENSSL_KEYTYPE_RSA,
- );
- // Create the private and public key
- $key = openssl_pkey_new($config);
- $publicKey = openssl_pkey_get_details($key)['key'];
-
- // Extract the private key from $key to $privateKey
- openssl_pkey_export($key, $privateKey);
- $encryptionKey = base64_encode(random_bytes(32));
- $result = array(
- "privateKey" => $privateKey,
- "publicKey" => $publicKey,
- "encryptionKey" => $encryptionKey
- );
- return $result;
- }
+namespace Pdsinterop\PhpSolid;
- public static function getAuthServer() {
- $authServerConfig = self::getAuthServerConfig();
- $authServerFactory = new AuthorizationServerFactory($authServerConfig);
- $authServer = $authServerFactory->create();
- $response = new Response();
- $server = new SolidAuthServer($authServer, $authServerConfig, $response);
- return $server;
- }
+use Pdsinterop\Solid\Auth\Factory\AuthorizationServerFactory;
+use Laminas\Diactoros\Response;
+use Pdsinterop\Solid\Auth\Server as SolidAuthServer;
+use Pdsinterop\Solid\Auth\Factory\ConfigFactory;
+use Pdsinterop\Solid\Auth\Config\Client as ConfigClient;
+use Pdsinterop\Solid\Auth\Utils\ReplayDetector;
+use Pdsinterop\Solid\Auth\Utils\DPop;
+use Pdsinterop\Solid\Auth\Utils\Bearer;
+use Pdsinterop\Solid\Auth\Utils\JtiValidator;
+use Pdsinterop\Solid\Auth\TokenGenerator;
+use Pdsinterop\PhpSolid\ClientRegistration;
+use Pdsinterop\PhpSolid\JtiStore;
- public static function getAuthServerConfig() {
- $keys = self::getKeys();
- $configClient = self::getConfigClient();
- $endpoints = self::getEndpoints();
- $authServerConfigFactory = new ConfigFactory(
- $configClient,
- $keys['encryptionKey'],
- $keys['privateKey'],
- $keys['publicKey'],
- $endpoints
- );
- $authServerConfig = $authServerConfigFactory->create();
- return $authServerConfig;
+class Server
+{
+ public static function generateKeySet()
+ {
+ $config = array(
+ "digest_alg" => "sha256",
+ "private_key_bits" => 2048,
+ "private_key_type" => OPENSSL_KEYTYPE_RSA,
+ );
+ // Create the private and public key
+ $key = openssl_pkey_new($config);
+ $publicKey = openssl_pkey_get_details($key)['key'];
+
+ // Extract the private key from $key to $privateKey
+ openssl_pkey_export($key, $privateKey);
+ $encryptionKey = base64_encode(random_bytes(32));
+ $result = array(
+ "privateKey" => $privateKey,
+ "publicKey" => $publicKey,
+ "encryptionKey" => $encryptionKey
+ );
+
+ return $result;
+ }
+
+ public static function getAuthServer()
+ {
+ $authServerConfig = self::getAuthServerConfig();
+ $authServerFactory = new AuthorizationServerFactory($authServerConfig);
+ $authServer = $authServerFactory->create();
+ $response = new Response();
+ $server = new SolidAuthServer($authServer, $authServerConfig, $response);
+ return $server;
+ }
+
+ public static function getAuthServerConfig()
+ {
+ $keys = self::getKeys();
+ $configClient = self::getConfigClient();
+ $endpoints = self::getEndpoints();
+ $authServerConfigFactory = new ConfigFactory(
+ $configClient,
+ $keys['encryptionKey'],
+ $keys['privateKey'],
+ $keys['publicKey'],
+ $endpoints
+ );
+ $authServerConfig = $authServerConfigFactory->create();
+ return $authServerConfig;
+ }
+
+ public static function getConfigClient()
+ {
+ $clientId = $_GET['client_id'] ?? $_POST['client_id'] ?? null;
+ if ($clientId) {
+ $registeredClient = ClientRegistration::getRegistration($clientId);
}
-
- public static function getConfigClient() {
- $clientId = $_GET['client_id'] ?? $_POST['client_id'] ?? null;
- if ($clientId) {
- $registeredClient = ClientRegistration::getRegistration($clientId);
- }
- if (isset($registeredClient)) {
- return new ConfigClient(
- $clientId,
- $registeredClient['client_secret'] ?? '',
- $registeredClient['redirect_uris'],
- $registeredClient['client_name']
- );
- } else {
- return new ConfigClient(
- '',
- '',
- array(),
- ''
- );
- }
+ if (isset($registeredClient)) {
+ return new ConfigClient(
+ $clientId,
+ $registeredClient['client_secret'] ?? '',
+ $registeredClient['redirect_uris'],
+ $registeredClient['client_name']
+ );
+ } else {
+ return new ConfigClient(
+ '',
+ '',
+ array(),
+ ''
+ );
}
-
- public static function getDpop() {
- $replayDetector = new ReplayDetector(
- function($jti, $targetUri) {
- if (JtiStore::hasJti($jti)) {
- return true;
- } else {
- JtiStore::saveJti($jti);
- return false;
- }
+ }
+
+ public static function getDpop()
+ {
+ $replayDetector = new ReplayDetector(
+ function ($jti, $targetUri) {
+ if (JtiStore::hasJti($jti)) {
+ return true;
+ } else {
+ JtiStore::saveJti($jti);
return false;
}
- );
- $jtiValidator = new JtiValidator($replayDetector);
- return new DPop($jtiValidator);
- }
-
- public static function getBearer() {
- $replayDetector = new ReplayDetector(
- function($jti, $targetUri) {
- if (JtiStore::hasJti($jti)) {
- return true;
- } else {
- JtiStore::saveJti($jti);
- return false;
- }
+ return false;
+ }
+ );
+ $jtiValidator = new JtiValidator($replayDetector);
+ return new DPop($jtiValidator);
+ }
+
+ public static function getBearer()
+ {
+ $replayDetector = new ReplayDetector(
+ function ($jti, $targetUri) {
+ if (JtiStore::hasJti($jti)) {
+ return true;
+ } else {
+ JtiStore::saveJti($jti);
return false;
}
- );
- $jtiValidator = new JtiValidator($replayDetector);
- return new Bearer($jtiValidator);
- }
-
- public static function getEndpoints() {
- return array(
- "issuer" => BASEURL,
- "jwks_uri" => BASEURL . "/jwks/",
- "check_session_iframe" => BASEURL . "/session/",
- "end_session_endpoint" => BASEURL . "/logout/",
- "authorization_endpoint" => BASEURL . "/authorize/",
- "token_endpoint" => BASEURL . "/token/",
- "userinfo_endpoint" => BASEURL . "/userinfo/",
- "registration_endpoint" => BASEURL . "/register/"
- );
- }
-
- public static function getKeys() {
- $keys = array(
- 'encryptionKey' => file_get_contents(KEYDIR . "encryption.key"),
- 'privateKey' => file_get_contents(KEYDIR . "private.key"),
- 'publicKey' => file_get_contents(KEYDIR . "public.key")
- );
- return $keys;
- }
+ return false;
+ }
+ );
+ $jtiValidator = new JtiValidator($replayDetector);
+ return new Bearer($jtiValidator);
+ }
- public static function getTokenGenerator() {
- $dpopValidFor = new \DateInterval('PT10M');
- return new TokenGenerator(
- self::getAuthServerConfig(),
- $dpopValidFor,
- self::getDpop()
- );
- }
-
- public static function respond($response) {
- $statusCode = $response->getStatusCode();
- $response->getBody()->rewind();
- $headers = $response->getHeaders();
-
- $body = json_decode($response->getBody()->getContents());
- header("HTTP/1.1 $statusCode");
- foreach ($headers as $header => $values) {
- foreach ($values as $value) {
- if ($header == "Location") {
- $value = preg_replace("|%26%2334%3B|", "%22", $value); // odoo weird encoding
- }
- header($header . ":" . $value);
+ public static function getEndpoints()
+ {
+ return array(
+ "issuer" => BASEURL,
+ "jwks_uri" => BASEURL . "/jwks/",
+ "check_session_iframe" => BASEURL . "/session/",
+ "end_session_endpoint" => BASEURL . "/logout/",
+ "authorization_endpoint" => BASEURL . "/authorize/",
+ "token_endpoint" => BASEURL . "/token/",
+ "userinfo_endpoint" => BASEURL . "/userinfo/",
+ "registration_endpoint" => BASEURL . "/register/"
+ );
+ }
+
+ public static function getKeys()
+ {
+ $keys = array(
+ 'encryptionKey' => file_get_contents(KEYDIR . "encryption.key"),
+ 'privateKey' => file_get_contents(KEYDIR . "private.key"),
+ 'publicKey' => file_get_contents(KEYDIR . "public.key")
+ );
+ return $keys;
+ }
+
+ public static function getTokenGenerator()
+ {
+ $dpopValidFor = new \DateInterval('PT10M');
+ return new TokenGenerator(
+ self::getAuthServerConfig(),
+ $dpopValidFor,
+ self::getDpop()
+ );
+ }
+
+ public static function respond($response)
+ {
+ $statusCode = $response->getStatusCode();
+ $response->getBody()->rewind();
+ $headers = $response->getHeaders();
+
+ $body = json_decode($response->getBody()->getContents());
+ header("HTTP/1.1 $statusCode");
+ foreach ($headers as $header => $values) {
+ foreach ($values as $value) {
+ if ($header == "Location") {
+ $value = preg_replace("|%26%2334%3B|", "%22", $value); // odoo weird encoding
}
+ header($header . ":" . $value);
}
- echo json_encode($body, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
}
+ echo json_encode($body, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
+ }
+
+ public static function respondPodPro($response, $body)
+ {
+ $statusCode = $response->getStatusCode();
+ $response->getBody()->rewind();
+ $headers = $response->getHeaders();
- public static function respondPodPro($response, $body) {
- $statusCode = $response->getStatusCode();
- $response->getBody()->rewind();
- $headers = $response->getHeaders();
-
- header("HTTP/1.1 $statusCode");
- foreach ($headers as $header => $values) {
- foreach ($values as $value) {
- if ($header == "Location") {
- $value = preg_replace("|%26%2334%3B|", "%22", $value); // odoo weird encoding
- }
- header($header . ":" . $value);
+ header("HTTP/1.1 $statusCode");
+ foreach ($headers as $header => $values) {
+ foreach ($values as $value) {
+ if ($header == "Location") {
+ $value = preg_replace("|%26%2334%3B|", "%22", $value); // odoo weird encoding
}
+ header($header . ":" . $value);
}
- echo json_encode($body, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
}
+ echo json_encode($body, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
}
+}
diff --git a/lib/Session.php b/lib/Session.php
index 7a707e3..dd1235e 100644
--- a/lib/Session.php
+++ b/lib/Session.php
@@ -1,23 +1,27 @@
24*60*60 // 1 day
- ]);
- }
- $_SESSION['username'] = $username;
+namespace Pdsinterop\PhpSolid;
+
+class Session
+{
+ public static function start($username)
+ {
+ if (session_status() === PHP_SESSION_NONE) {
+ session_start([
+ 'cookie_lifetime' => 24 * 60 * 60 // 1 day
+ ]);
+ }
+ $_SESSION['username'] = $username;
+ }
+
+ public static function getLoggedInUser()
+ {
+ if (session_status() === PHP_SESSION_NONE) {
+ session_start();
}
-
- public static function getLoggedInUser() {
- if (session_status() === PHP_SESSION_NONE) {
- session_start();
- }
- if (!isset($_SESSION['username'])) {
- return false;
- }
- return $_SESSION['username'];
+ if (!isset($_SESSION['username'])) {
+ return false;
}
+ return $_SESSION['username'];
}
+}
diff --git a/lib/SolidNotifications.php b/lib/SolidNotifications.php
index ecafa9f..b1d5cab 100644
--- a/lib/SolidNotifications.php
+++ b/lib/SolidNotifications.php
@@ -1,26 +1,30 @@
notifications = $notifications;
+ public function __construct()
+ {
+ $pubsub = PUBSUB_SERVER;
+ if ($pubsub) {
+ $notifications[] = new SolidPubSub($pubsub);
}
- public function send($path, $type) {
- ob_start();
- foreach ($this->notifications as $notification) {
- $notification->send($path, $type);
- }
- ob_end_clean();
+ $this->notifications = $notifications;
+ }
+
+ public function send($path, $type)
+ {
+ ob_start();
+ foreach ($this->notifications as $notification) {
+ $notification->send($path, $type);
}
+ ob_end_clean();
}
+}
diff --git a/lib/SolidPubSub.php b/lib/SolidPubSub.php
index 36f49d1..b7df02c 100644
--- a/lib/SolidPubSub.php
+++ b/lib/SolidPubSub.php
@@ -1,30 +1,33 @@
pubsub = $pubsubUrl;
- }
+ $this->pubsub = $pubsubUrl;
+ }
- public function send($path, $type) {
- $pubsub = str_replace(["https://", "http://"], "wss://", $this->pubsub);
+ public function send($path, $type)
+ {
+ $pubsub = str_replace(["https://", "http://"], "wss://", $this->pubsub);
- $client = new Client($pubsub);
- $client->setContext(['ssl' => [
- 'verify_peer' => false, // if false, accept SSL handshake without client certificate
- 'verify_peer_name' => false,
- 'allow_self_signed' => true,
- ]]);
- $client->addHeader("Sec-WebSocket-Protocol", "solid-0.1");
- try {
- $client->text("pub $path\n");
- } catch (\Throwable $exception) {
- throw new \Exception('Could not write to pubsub server', 502, $exception);
- }
+ $client = new Client($pubsub);
+ $client->setContext(['ssl' => [
+ 'verify_peer' => false, // if false, accept SSL handshake without client certificate
+ 'verify_peer_name' => false,
+ 'allow_self_signed' => true,
+ ]]);
+ $client->addHeader("Sec-WebSocket-Protocol", "solid-0.1");
+ try {
+ $client->text("pub $path\n");
+ } catch (\Throwable $exception) {
+ throw new \Exception('Could not write to pubsub server', 502, $exception);
}
}
+}
diff --git a/lib/StorageServer.php b/lib/StorageServer.php
index 5b43e3d..fcb09c7 100644
--- a/lib/StorageServer.php
+++ b/lib/StorageServer.php
@@ -1,318 +1,336 @@
prepare(
- 'SELECT * FROM storage WHERE storage_id=:storageId'
- );
- $query->execute([
- ':storageId' => $storageId
- ]);
- return $query->fetchAll();
+
+namespace Pdsinterop\PhpSolid;
+
+use Pdsinterop\PhpSolid\Server;
+use Pdsinterop\PhpSolid\User;
+use Pdsinterop\PhpSolid\Util;
+use Pdsinterop\PhpSolid\Db;
+
+class StorageServer extends Server
+{
+ public static function getStorage($storageId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT * FROM storage WHERE storage_id=:storageId'
+ );
+ $query->execute([
+ ':storageId' => $storageId
+ ]);
+ return $query->fetchAll();
+ }
+
+ public static function setStorageOwner($storageId, $owner)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'UPDATE storage SET owner=:owner WHERE storage_id=:storageId'
+ );
+ $query->execute([
+ ':storageId' => $storageId,
+ ':owner' => $owner
+ ]);
+ }
+
+ public static function createStorage($ownerWebId)
+ {
+ $generatedStorageId = bin2hex(random_bytes(16));
+ while (self::storageIdExists($generatedStorageId)) {
+ $generatedStorageId = bin2hex(random_bytes(16));
}
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'INSERT OR REPLACE INTO storage VALUES(:storageId, :owner)'
+ );
+ $query->execute([
+ ':storageId' => $generatedStorageId,
+ ':owner' => $ownerWebId
+ ]);
+ return [
+ "storageId" => $generatedStorageId,
+ "storageUrl" => "https://storage-" . $generatedStorageId . "." . BASEDOMAIN . "/"
+ ];
+ }
- public static function setStorageOwner($storageId, $owner) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'UPDATE storage SET owner=:owner WHERE storage_id=:storageId'
- );
- $query->execute([
- ':storageId' => $storageId,
- ':owner' => $owner
- ]);
+ public static function storageIdExists($storageId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT storage_id FROM storage WHERE storage_id=:storageId'
+ );
+ $query->execute([
+ ':storageId' => $storageId
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ return true;
}
+ return false;
+ }
- public static function createStorage($ownerWebId) {
- $generatedStorageId = bin2hex(random_bytes(16));
- while (self::storageIdExists($generatedStorageId)) {
- $generatedStorageId = bin2hex(random_bytes(16));
- }
- Db::connect();
- $query = Db::$pdo->prepare(
- 'INSERT OR REPLACE INTO storage VALUES(:storageId, :owner)'
- );
- $query->execute([
- ':storageId' => $generatedStorageId,
- ':owner' => $ownerWebId
- ]);
- return [
- "storageId" => $generatedStorageId,
- "storageUrl" => "https://storage-" . $generatedStorageId . "." . BASEDOMAIN . "/"
- ];
+ public static function getOwnerWebId()
+ {
+ $storageId = self::getStorageId();
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT owner FROM storage WHERE storage_id=:storageId'
+ );
+ $query->execute([
+ ':storageId' => $storageId
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ return $result[0]['owner'];
}
+ return false;
+ }
- public static function storageIdExists($storageId) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT storage_id FROM storage WHERE storage_id=:storageId'
- );
- $query->execute([
- ':storageId' => $storageId
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- return true;
- }
- return false;
- }
-
- public static function getOwnerWebId() {
- $storageId = self::getStorageId();
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT owner FROM storage WHERE storage_id=:storageId'
- );
- $query->execute([
- ':storageId' => $storageId
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- return $result[0]['owner'];
- }
- return false;
+ public static function getFileSystem()
+ {
+ $storageId = self::getStorageId();
+ if (!self::storageIdExists($storageId)) {
+ throw new \Exception("Storage does not exist");
+ }
+ if (is_dir(STORAGEBASE . "$storageId/")) { // backwards compatiblity check
+ $storagePath = $storageId;
+ } else {
+ $storagePath = implode("/", str_split($storageId, 4));
}
- public static function getFileSystem() {
- $storageId = self::getStorageId();
- if (!self::storageIdExists($storageId)) {
- throw new \Exception("Storage does not exist");
- }
- if (is_dir(STORAGEBASE . "$storageId/")) { // backwards compatiblity check
- $storagePath = $storageId;
- } else {
- $storagePath = implode("/", str_split($storageId, 4));
- }
+ // The internal adapter
+ $adapter = new \League\Flysystem\Adapter\Local(
+ // Determine root directory
+ STORAGEBASE . "$storagePath/"
+ );
- // The internal adapter
- $adapter = new \League\Flysystem\Adapter\Local(
- // Determine root directory
- STORAGEBASE . "$storagePath/"
- );
-
- $graph = new \EasyRdf\Graph();
- // Create Formats objects
- $formats = new \Pdsinterop\Rdf\Formats();
- $serverUri = Util::getServerUri();
-
- // Create the RDF Adapter
- $rdfAdapter = new \Pdsinterop\Rdf\Flysystem\Adapter\Rdf($adapter, $graph, $formats, $serverUri);
-
- $filesystem = new \League\Flysystem\Filesystem($rdfAdapter);
- $filesystem->addPlugin(new \Pdsinterop\Rdf\Flysystem\Plugin\AsMime($formats));
- $plugin = new \Pdsinterop\Rdf\Flysystem\Plugin\ReadRdf($graph);
- $filesystem->addPlugin($plugin);
- return $filesystem;
- }
+ $graph = new \EasyRdf\Graph();
+ // Create Formats objects
+ $formats = new \Pdsinterop\Rdf\Formats();
+ $serverUri = Util::getServerUri();
+
+ // Create the RDF Adapter
+ $rdfAdapter = new \Pdsinterop\Rdf\Flysystem\Adapter\Rdf($adapter, $graph, $formats, $serverUri);
- public static function respond($response) {
- $statusCode = $response->getStatusCode();
- $response->getBody()->rewind();
- $headers = $response->getHeaders();
-
- $body = $response->getBody()->getContents();
- header("HTTP/1.1 $statusCode");
- foreach ($headers as $header => $values) {
- foreach ($values as $value) {
- if ($header == "Location") {
- $value = preg_replace("|%26%2334%3B|", "%22", $value); // odoo weird encoding
- }
- header($header . ":" . $value);
+ $filesystem = new \League\Flysystem\Filesystem($rdfAdapter);
+ $filesystem->addPlugin(new \Pdsinterop\Rdf\Flysystem\Plugin\AsMime($formats));
+ $plugin = new \Pdsinterop\Rdf\Flysystem\Plugin\ReadRdf($graph);
+ $filesystem->addPlugin($plugin);
+ return $filesystem;
+ }
+
+ public static function respond($response)
+ {
+ $statusCode = $response->getStatusCode();
+ $response->getBody()->rewind();
+ $headers = $response->getHeaders();
+
+ $body = $response->getBody()->getContents();
+ header("HTTP/1.1 $statusCode");
+ foreach ($headers as $header => $values) {
+ foreach ($values as $value) {
+ if ($header == "Location") {
+ $value = preg_replace("|%26%2334%3B|", "%22", $value); // odoo weird encoding
}
+ header($header . ":" . $value);
}
- echo $body;
}
+ echo $body;
+ }
- public static function getWebId($rawRequest) {
- $dpop = self::getDpop();
- $webId = $dpop->getWebId($rawRequest);
- if (!isset($webId)) {
- $bearer = self::getBearer();
- $webId = $bearer->getWebId($rawRequest);
- }
- return $webId;
+ public static function getWebId($rawRequest)
+ {
+ $dpop = self::getDpop();
+ $webId = $dpop->getWebId($rawRequest);
+ if (!isset($webId)) {
+ $bearer = self::getBearer();
+ $webId = $bearer->getWebId($rawRequest);
}
+ return $webId;
+ }
+
+ private static function getStorageId()
+ {
+ $serverName = Util::getServerName();
+ $idParts = explode(".", $serverName, 2);
+ $storageId = preg_replace("/^storage-/", "", $idParts[0]);
+ return $storageId;
+ }
- private static function getStorageId() {
- $serverName = Util::getServerName();
- $idParts = explode(".", $serverName, 2);
- $storageId = preg_replace("/^storage-/", "", $idParts[0]);
- return $storageId;
+ public static function initializeStorage()
+ {
+ $filesystem = self::getFilesystem();
+ if (!$filesystem->has("/.acl")) {
+ $defaultAcl = self::generateDefaultAcl();
+ $filesystem->write("/.acl", $defaultAcl);
}
-
- public static function initializeStorage() {
- $filesystem = self::getFilesystem();
- if (!$filesystem->has("/.acl")) {
- $defaultAcl = self::generateDefaultAcl();
- $filesystem->write("/.acl", $defaultAcl);
- }
- // Generate default folders and ACLs:
- if (!$filesystem->has("/inbox")) {
- $filesystem->createDir("/inbox");
- }
- if (!$filesystem->has("/inbox/.acl")) {
- $inboxAcl = self::generatePublicAppendAcl();
- $filesystem->write("/inbox/.acl", $inboxAcl);
- }
- if (!$filesystem->has("/settings")) {
- $filesystem->createDir("/settings");
- }
- if (!$filesystem->has("/settings/privateTypeIndex.ttl")) {
- $privateTypeIndex = self::generateDefaultPrivateTypeIndex();
- $filesystem->write("/settings/privateTypeIndex.ttl", $privateTypeIndex);
- }
- if (!$filesystem->has("/settings/publicTypeIndex.ttl")) {
- $publicTypeIndex = self::generateDefaultPublicTypeIndex();
- $filesystem->write("/settings/publicTypeIndex.ttl", $publicTypeIndex);
- }
- if (!$filesystem->has("/settings/preferences.ttl")) {
- $preferences = self::generateDefaultPreferences();
- $filesystem->write("/settings/preferences.ttl", $preferences);
- }
- if (!$filesystem->has("/public")) {
- $filesystem->createDir("/public");
- }
- if (!$filesystem->has("/public/.acl")) {
- $publicAcl = self::generatePublicReadAcl();
- $filesystem->write("/public/.acl", $publicAcl);
- }
- if (!$filesystem->has("/private")) {
- $filesystem->createDir("/private");
- }
+ // Generate default folders and ACLs:
+ if (!$filesystem->has("/inbox")) {
+ $filesystem->createDir("/inbox");
}
-
- public static function generateDefaultAcl() {
- $webId = self::getOwnerWebId();
- if (!$webId) {
- throw new \Exception("No owner found for storage");
- }
- $acl = <<< "EOF"
+ if (!$filesystem->has("/inbox/.acl")) {
+ $inboxAcl = self::generatePublicAppendAcl();
+ $filesystem->write("/inbox/.acl", $inboxAcl);
+ }
+ if (!$filesystem->has("/settings")) {
+ $filesystem->createDir("/settings");
+ }
+ if (!$filesystem->has("/settings/privateTypeIndex.ttl")) {
+ $privateTypeIndex = self::generateDefaultPrivateTypeIndex();
+ $filesystem->write("/settings/privateTypeIndex.ttl", $privateTypeIndex);
+ }
+ if (!$filesystem->has("/settings/publicTypeIndex.ttl")) {
+ $publicTypeIndex = self::generateDefaultPublicTypeIndex();
+ $filesystem->write("/settings/publicTypeIndex.ttl", $publicTypeIndex);
+ }
+ if (!$filesystem->has("/settings/preferences.ttl")) {
+ $preferences = self::generateDefaultPreferences();
+ $filesystem->write("/settings/preferences.ttl", $preferences);
+ }
+ if (!$filesystem->has("/public")) {
+ $filesystem->createDir("/public");
+ }
+ if (!$filesystem->has("/public/.acl")) {
+ $publicAcl = self::generatePublicReadAcl();
+ $filesystem->write("/public/.acl", $publicAcl);
+ }
+ if (!$filesystem->has("/private")) {
+ $filesystem->createDir("/private");
+ }
+ }
+
+ public static function generateDefaultAcl()
+ {
+ $webId = self::getOwnerWebId();
+ if (!$webId) {
+ throw new \Exception("No owner found for storage");
+ }
+ $acl = <<< "EOF"
# Root ACL resource for the user account
@prefix acl: .
@prefix foaf: .
# The homepage is readable by the public
<#public>
- a acl:Authorization;
- acl:agentClass foaf:Agent;
- acl:accessTo <./>;
- acl:mode acl:Read.
+a acl:Authorization;
+acl:agentClass foaf:Agent;
+acl:accessTo <./>;
+acl:mode acl:Read.
# The owner has full access to every resource in their pod.
# Other agents have no access rights,
# unless specifically authorized in other .acl resources.
<#owner>
- a acl:Authorization;
- acl:agent <$webId>;
- # Set the access to the root storage folder itself
- acl:accessTo <./>;
- # All resources will inherit this authorization, by default
- acl:default <./>;
- # The owner has all of the access modes allowed
- acl:mode
- acl:Read, acl:Write, acl:Control.
+a acl:Authorization;
+acl:agent <$webId>;
+# Set the access to the root storage folder itself
+acl:accessTo <./>;
+# All resources will inherit this authorization, by default
+acl:default <./>;
+# The owner has all of the access modes allowed
+acl:mode
+ acl:Read, acl:Write, acl:Control.
EOF;
- return $acl;
- }
+ return $acl;
+ }
- public static function generatePublicAppendAcl() {
- $webId = self::getOwnerWebId();
- if (!$webId) {
- throw new \Exception("No owner found for storage ID");
- }
- $acl = <<< "EOF"
+ public static function generatePublicAppendAcl()
+ {
+ $webId = self::getOwnerWebId();
+ if (!$webId) {
+ throw new \Exception("No owner found for storage ID");
+ }
+ $acl = <<< "EOF"
# Inbox ACL resource for the user account
@prefix acl: .
@prefix foaf: .
<#public>
- a acl:Authorization;
- acl:agentClass foaf:Agent;
- acl:accessTo <./>;
- acl:default <./>;
- acl:mode
- acl:Append.
+a acl:Authorization;
+acl:agentClass foaf:Agent;
+acl:accessTo <./>;
+acl:default <./>;
+acl:mode
+ acl:Append.
<#owner>
- a acl:Authorization;
- acl:agent <$webId>;
- # Set the access to the root storage folder itself
- acl:accessTo <./>;
- # All resources will inherit this authorization, by default
- acl:default <./>;
- # The owner has all of the access modes allowed
- acl:mode
- acl:Read, acl:Write, acl:Control.
+a acl:Authorization;
+acl:agent <$webId>;
+# Set the access to the root storage folder itself
+acl:accessTo <./>;
+# All resources will inherit this authorization, by default
+acl:default <./>;
+# The owner has all of the access modes allowed
+acl:mode
+ acl:Read, acl:Write, acl:Control.
EOF;
- return $acl;
- }
+ return $acl;
+ }
- public static function generatePublicReadAcl() {
- $webId = self::getOwnerWebId();
- if (!$webId) {
- throw new \Exception("No owner found for storage ID");
- }
- $acl = <<< "EOF"
+ public static function generatePublicReadAcl()
+ {
+ $webId = self::getOwnerWebId();
+ if (!$webId) {
+ throw new \Exception("No owner found for storage ID");
+ }
+ $acl = <<< "EOF"
# Inbox ACL resource for the user account
@prefix acl: .
@prefix foaf: .
<#public>
- a acl:Authorization;
- acl:agentClass foaf:Agent;
- acl:accessTo <./>;
- acl:default <./>;
- acl:mode
- acl:Read.
+a acl:Authorization;
+acl:agentClass foaf:Agent;
+acl:accessTo <./>;
+acl:default <./>;
+acl:mode
+ acl:Read.
<#owner>
- a acl:Authorization;
- acl:agent <$webId>;
- # Set the access to the root storage folder itself
- acl:accessTo <./>;
- # All resources will inherit this authorization, by default
- acl:default <./>;
- # The owner has all of the access modes allowed
- acl:mode
- acl:Read, acl:Write, acl:Control.
+a acl:Authorization;
+acl:agent <$webId>;
+# Set the access to the root storage folder itself
+acl:accessTo <./>;
+# All resources will inherit this authorization, by default
+acl:default <./>;
+# The owner has all of the access modes allowed
+acl:mode
+ acl:Read, acl:Write, acl:Control.
EOF;
- return $acl;
- }
+ return $acl;
+ }
- public static function generateDefaultPrivateTypeIndex() {
- $typeIndex = <<< "EOF"
+ public static function generateDefaultPrivateTypeIndex()
+ {
+ $typeIndex = <<< "EOF"
# Private type index
@prefix : <#>.
@prefix solid: .
<>
- a solid:UnlistedDocument, solid:TypeIndex.
+a solid:UnlistedDocument, solid:TypeIndex.
EOF;
- return $typeIndex;
- }
+ return $typeIndex;
+ }
- public static function generateDefaultPublicTypeIndex() {
- $typeIndex = <<< "EOF"
+ public static function generateDefaultPublicTypeIndex()
+ {
+ $typeIndex = <<< "EOF"
# Public type index
@prefix : <#>.
@prefix solid: .
<>
- a solid:ListedDocument, solid:TypeIndex.
+a solid:ListedDocument, solid:TypeIndex.
EOF;
- return $typeIndex;
- }
+ return $typeIndex;
+ }
- public static function generateDefaultPreferences() {
- $webId = self::getOwnerWebId();
- $preferences = <<< "EOF"
+ public static function generateDefaultPreferences()
+ {
+ $webId = self::getOwnerWebId();
+ $preferences = <<< "EOF"
# Preferences
@prefix : <#>.
@prefix sp: .
@@ -320,15 +338,14 @@ public static function generateDefaultPreferences() {
@prefix solid: .
<>
- a sp:ConfigurationFile;
- dct:title "Preferences file".
+a sp:ConfigurationFile;
+dct:title "Preferences file".
<$webId>
- a solid:Developer;
- solid:privateTypeIndex ;
- solid:publicTypeIndex .
+a solid:Developer;
+solid:privateTypeIndex ;
+solid:publicTypeIndex .
EOF;
- return $preferences;
- }
+ return $preferences;
}
-
\ No newline at end of file
+}
diff --git a/lib/User.php b/lib/User.php
index bfb758b..34ae5fe 100644
--- a/lib/User.php
+++ b/lib/User.php
@@ -1,384 +1,413 @@
add(new \DateInterval($lifetime));
- return $expires->getTimestamp();
+ while (in_array($code, $existingTokens)) { // make sure we have no collissions;
+ $code = random_int(0, 1000000);
+ $code = str_pad($code, $digits, '0', STR_PAD_LEFT);
}
- public static function saveVerifyToken($tokenType, $tokenData) {
- switch ($tokenType) {
- case "verify":
- $tokenData['code'] = self::generateTokenCode();
- $tokenData['expires'] = self::generateExpiresTimestamp('PT30M'); // expires after 30 minutes
- break;
- case "passwordReset":
- case "deleteAccount":
- default:
- $tokenData['code'] = self::generateTokenHex();
- $tokenData['expires'] = self::generateExpiresTimestamp('PT30M'); // expires after 30 minutes
- break;
- }
-
- Db::connect();
- $query = Db::$pdo->prepare(
- 'INSERT INTO verify VALUES(:code, :data)'
- );
- $query->execute([
- ':code' => $tokenData['code'],
- ':data' => json_encode($tokenData)
- ]);
- return $tokenData;
- }
-
- public static function getVerifyToken($code) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT data FROM verify WHERE code=:code'
- );
- $query->execute([
- ':code' => $code
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- $result = json_decode($result[0]['data'], true);
- if (!self::isExpired($result)) {
- return $result;
- }
- }
- return false;
- }
-
- private static function isExpired($token) {
- $now = new \DateTime();
- if ($token['expires'] > $now->getTimestamp()) {
- return false;
- }
-
- return true;
- }
-
- public static function validatePasswordStrength($password) {
- $entropy = PasswordValidator::getEntropy($password, BANNED_PASSWORDS);
- $minimumEntropy = MINIMUM_PASSWORD_ENTROPY;
- if ($entropy < $minimumEntropy) {
- error_log("Entered pasword does not satisfy minimum entropy");
- return false;
- }
- return true;
+ return $code;
+ }
+
+ private static function generateTokenHex()
+ {
+ return bin2hex(random_bytes(16));
+ }
+
+ private static function generateExpiresTimestamp($lifetime)
+ {
+ $expires = new \DateTime();
+ $expires->add(new \DateInterval($lifetime));
+ return $expires->getTimestamp();
+ }
+
+ public static function saveVerifyToken($tokenType, $tokenData)
+ {
+ switch ($tokenType) {
+ case "verify":
+ $tokenData['code'] = self::generateTokenCode();
+ $tokenData['expires'] = self::generateExpiresTimestamp('PT30M'); // expires after 30 minutes
+ break;
+ case "passwordReset":
+ case "deleteAccount":
+ default:
+ $tokenData['code'] = self::generateTokenHex();
+ $tokenData['expires'] = self::generateExpiresTimestamp('PT30M'); // expires after 30 minutes
+ break;
}
- public static function createUser($newUser) {
- Db::connect();
- if (!self::validatePasswordStrength($newUser['password'])) {
- return false;
- }
- $generatedUserId = bin2hex(random_bytes(16));
- while (self::userIdExists($generatedUserId)) {
- $generatedUserId = bin2hex(random_bytes(16));
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'INSERT INTO verify VALUES(:code, :data)'
+ );
+ $query->execute([
+ ':code' => $tokenData['code'],
+ ':data' => json_encode($tokenData)
+ ]);
+ return $tokenData;
+ }
+
+ public static function getVerifyToken($code)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT data FROM verify WHERE code=:code'
+ );
+ $query->execute([
+ ':code' => $code
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ $result = json_decode($result[0]['data'], true);
+ if (!self::isExpired($result)) {
+ return $result;
}
- $query = Db::$pdo->prepare(
- 'INSERT INTO users VALUES (:userId, :email, :passwordHash, :data)'
- );
-
- $queryParams = [];
- $queryParams[':userId'] = $generatedUserId;
- $queryParams[':email'] = $newUser['email'];
- $queryParams[':passwordHash'] = password_hash($newUser['password'], PASSWORD_BCRYPT);
- unset($newUser['password']);
-
- $newUser['webId'] = "https://id-" . $generatedUserId . "." . BASEDOMAIN . "/#me";
- $queryParams[':data'] = json_encode($newUser);
- $query->execute($queryParams);
-
- return [
- "userId" => $generatedUserId,
- "email" => $newUser['email'],
- "webId" => $newUser['webId']
- ];
}
+ return false;
+ }
- public static function setUserPassword($email, $newPassword) {
- if (!self::userEmailExists($email)) {
- return false;
- }
- if (!self::validatePasswordStrength($newPassword)) {
- return false;
- }
- Db::connect();
- $query = Db::$pdo->prepare(
- 'UPDATE users SET password=:passwordHash WHERE email=:email'
- );
- $queryParams = [];
- $queryParams[':email'] = $email;
- $queryParams[':passwordHash'] = password_hash($newPassword, PASSWORD_BCRYPT);
-
- $query->execute($queryParams);
- return true;
+ private static function isExpired($token)
+ {
+ $now = new \DateTime();
+ if ($token['expires'] > $now->getTimestamp()) {
+ return false;
}
- public static function allowClientForUser($clientId, $userId) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'INSERT OR REPLACE INTO allowedClients VALUES(:userId, :clientId)'
- );
- $query->execute([
- ':userId' => $userId,
- ':clientId' => $clientId
- ]);
- return true;
- }
+ return true;
+ }
- public static function getAllowedClients($userId) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT clientId FROM allowedClients WHERE userId=:userId'
- );
- $query->execute([
- ':userId' => $userId
- ]);
- $result = [];
- while($row = $query->fetch()) {
- $result[] = $row['clientId'];
- }
- return $result;
+ public static function validatePasswordStrength($password)
+ {
+ $entropy = PasswordValidator::getEntropy($password, BANNED_PASSWORDS);
+ $minimumEntropy = MINIMUM_PASSWORD_ENTROPY;
+ if ($entropy < $minimumEntropy) {
+ error_log("Entered pasword does not satisfy minimum entropy");
+ return false;
}
+ return true;
+ }
- public static function getAllowedOrigins($userId) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT origin from clients LEFT JOIN allowedClients ON clients.clientId=allowedClients.clientId where allowedClients.userId=:userId'
- );
- $query->execute([
- ':userId' => $userId
- ]);
- $result = [];
- while($row = $query->fetch()) {
- $result[] = $row['origin'];
- }
- return $result;
+ public static function createUser($newUser)
+ {
+ Db::connect();
+ if (!self::validatePasswordStrength($newUser['password'])) {
+ return false;
}
-
- public static function getStorage($userId) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT storageUrl FROM userStorage WHERE userId=:userId'
- );
- $query->execute([
- ':userId' => $userId
- ]);
- $result = [];
- while($row = $query->fetch()) {
- $result[] = $row['storageUrl'];
- }
- return $result;
+ $generatedUserId = bin2hex(random_bytes(16));
+ while (self::userIdExists($generatedUserId)) {
+ $generatedUserId = bin2hex(random_bytes(16));
}
-
- public static function setStorage($userId, $storageUrl) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'INSERT OR REPLACE INTO userStorage VALUES(:userId, :storageUrl)'
- );
- $query->execute([
- ':userId' => $userId,
- ':storageUrl' => $storageUrl
- ]);
+ $query = Db::$pdo->prepare(
+ 'INSERT INTO users VALUES (:userId, :email, :passwordHash, :data)'
+ );
+
+ $queryParams = [];
+ $queryParams[':userId'] = $generatedUserId;
+ $queryParams[':email'] = $newUser['email'];
+ $queryParams[':passwordHash'] = password_hash($newUser['password'], PASSWORD_BCRYPT);
+ unset($newUser['password']);
+
+ $newUser['webId'] = "https://id-" . $generatedUserId . "." . BASEDOMAIN . "/#me";
+ $queryParams[':data'] = json_encode($newUser);
+ $query->execute($queryParams);
+
+ return [
+ "userId" => $generatedUserId,
+ "email" => $newUser['email'],
+ "webId" => $newUser['webId']
+ ];
+ }
+
+ public static function setUserPassword($email, $newPassword)
+ {
+ if (!self::userEmailExists($email)) {
+ return false;
}
-
- public static function getUser($email) {
- if (!isset($email)) {
- return false;
- }
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT user_id, data FROM users WHERE email=:email'
- );
- $query->execute([
- ':email' => $email
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- $userData = json_decode($result[0]['data'], true);
- $userData['userId'] = $result[0]['user_id'];
-
- $allowedClients = self::getAllowedClients($userData['userId']);
- $userData['allowedClients'] = $allowedClients;
- $allowedOrigins = self::getAllowedOrigins($userData['userId']);
- $userData['allowedOrigins'] = $allowedOrigins;
- $userData['issuer'] = BASEURL;
- $storage = self::getStorage($userData['userId']);
- if ($storage) {
- $userData['storage'] = $storage;
- }
- return $userData;
- }
+ if (!self::validatePasswordStrength($newPassword)) {
return false;
}
-
- public static function getUserById($userId) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT user_id, data FROM users WHERE user_id=:userId'
- );
- $query->execute([
- ':userId' => $userId
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- $userData = json_decode($result[0]['data'], true);
- $userData['userId'] = $result[0]['user_id'];
-
- $allowedClients = self::getAllowedClients($userData['userId']);
- $userData['allowedClients'] = $allowedClients;
- $allowedOrigins = self::getAllowedOrigins($userData['userId']);
- $userData['allowedOrigins'] = $allowedOrigins;
- $userData['issuer'] = BASEURL;
- $storage = self::getStorage($userData['userId']);
- if ($storage) {
- $userData['storage'] = $storage;
- }
- return $userData;
- }
- return false;
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'UPDATE users SET password=:passwordHash WHERE email=:email'
+ );
+ $queryParams = [];
+ $queryParams[':email'] = $email;
+ $queryParams[':passwordHash'] = password_hash($newPassword, PASSWORD_BCRYPT);
+
+ $query->execute($queryParams);
+ return true;
+ }
+
+ public static function allowClientForUser($clientId, $userId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'INSERT OR REPLACE INTO allowedClients VALUES(:userId, :clientId)'
+ );
+ $query->execute([
+ ':userId' => $userId,
+ ':clientId' => $clientId
+ ]);
+ return true;
+ }
+
+ public static function getAllowedClients($userId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT clientId FROM allowedClients WHERE userId=:userId'
+ );
+ $query->execute([
+ ':userId' => $userId
+ ]);
+ $result = [];
+ while ($row = $query->fetch()) {
+ $result[] = $row['clientId'];
}
-
- public static function getUserByWebId($webId) {
- $webIdParts = parse_url($webId);
- $idParts = explode(".", $webIdParts['host'], 2);
- if ($idParts[1] !== BASEDOMAIN) {
- return false;
- }
- $userId = preg_replace("/^.*?id-/", "", $idParts[0]);
-
- return self::getUserById($userId);
+ return $result;
+ }
+
+ public static function getAllowedOrigins($userId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT origin from clients LEFT JOIN allowedClients ON clients.clientId=allowedClients.clientId where allowedClients.userId=:userId'
+ );
+ $query->execute([
+ ':userId' => $userId
+ ]);
+ $result = [];
+ while ($row = $query->fetch()) {
+ $result[] = $row['origin'];
}
-
- public static function checkPassword($email, $password) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT password FROM users WHERE email=:email'
- );
- $query->execute([
- ':email' => $email
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- if (password_verify($password, $result[0]['password'])) {
- return true;
- }
- }
+ return $result;
+ }
+
+ public static function getStorage($userId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT storageUrl FROM userStorage WHERE userId=:userId'
+ );
+ $query->execute([
+ ':userId' => $userId
+ ]);
+ $result = [];
+ while ($row = $query->fetch()) {
+ $result[] = $row['storageUrl'];
+ }
+ return $result;
+ }
+
+ public static function setStorage($userId, $storageUrl)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'INSERT OR REPLACE INTO userStorage VALUES(:userId, :storageUrl)'
+ );
+ $query->execute([
+ ':userId' => $userId,
+ ':storageUrl' => $storageUrl
+ ]);
+ }
+
+ public static function getUser($email)
+ {
+ if (!isset($email)) {
return false;
}
-
- public static function userIdExists($userId) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT user_id FROM users WHERE user_id=:userId'
- );
- $query->execute([
- ':userId' => $userId
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- return true;
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT user_id, data FROM users WHERE email=:email'
+ );
+ $query->execute([
+ ':email' => $email
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ $userData = json_decode($result[0]['data'], true);
+ $userData['userId'] = $result[0]['user_id'];
+
+ $allowedClients = self::getAllowedClients($userData['userId']);
+ $userData['allowedClients'] = $allowedClients;
+ $allowedOrigins = self::getAllowedOrigins($userData['userId']);
+ $userData['allowedOrigins'] = $allowedOrigins;
+ $userData['issuer'] = BASEURL;
+ $storage = self::getStorage($userData['userId']);
+ if ($storage) {
+ $userData['storage'] = $storage;
}
- return false;
+ return $userData;
}
-
- public static function userEmailExists($email) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT user_id FROM users WHERE email=:email'
- );
- $query->execute([
- ':email' => $email
- ]);
- $result = $query->fetchAll();
- if (sizeof($result) === 1) {
- return true;
+ return false;
+ }
+
+ public static function getUserById($userId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT user_id, data FROM users WHERE user_id=:userId'
+ );
+ $query->execute([
+ ':userId' => $userId
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ $userData = json_decode($result[0]['data'], true);
+ $userData['userId'] = $result[0]['user_id'];
+
+ $allowedClients = self::getAllowedClients($userData['userId']);
+ $userData['allowedClients'] = $allowedClients;
+ $allowedOrigins = self::getAllowedOrigins($userData['userId']);
+ $userData['allowedOrigins'] = $allowedOrigins;
+ $userData['issuer'] = BASEURL;
+ $storage = self::getStorage($userData['userId']);
+ if ($storage) {
+ $userData['storage'] = $storage;
}
- return false;
+ return $userData;
}
-
- private static function deleteUser($email) {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'DELETE FROM users WHERE email=:email'
- );
- $query->execute([
- ':email' => $email
- ]);
+ return false;
+ }
+
+ public static function getUserByWebId($webId)
+ {
+ $webIdParts = parse_url($webId);
+ $idParts = explode(".", $webIdParts['host'], 2);
+ if ($idParts[1] !== BASEDOMAIN) {
+ return false;
}
-
- private static function deleteAllowedClients($email) {
- $user = self::getUser($email);
- if (!$user) {
- return;
+ $userId = preg_replace("/^.*?id-/", "", $idParts[0]);
+
+ return self::getUserById($userId);
+ }
+
+ public static function checkPassword($email, $password)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT password FROM users WHERE email=:email'
+ );
+ $query->execute([
+ ':email' => $email
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ if (password_verify($password, $result[0]['password'])) {
+ return true;
}
-
- Db::connect();
- $query = Db::$pdo->prepare(
- 'DELETE FROM allowedClients WHERE userId=:userId'
- );
- $query->execute([
- ':userId' => $user['userId']
- ]);
}
-
- public static function deleteAccount($email) {
- if (!self::userEmailExists($email)) {
- return;
- }
- // FIXME: Delete storage;
- self::deleteAllowedClients($email);
- self::deleteUser($email);
+ return false;
+ }
+
+ public static function userIdExists($userId)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT user_id FROM users WHERE user_id=:userId'
+ );
+ $query->execute([
+ ':userId' => $userId
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ return true;
}
-
- public static function cleanupTokens() {
- Db::connect();
-
- $now = new \DateTime();
- $query = Db::$pdo->prepare(
- 'DELETE FROM verify WHERE json_extract(data, \'$.expires\') < :now'
- );
- $query->execute([
- ':now' => $now->getTimestamp()
- ]);
+ return false;
+ }
+
+ public static function userEmailExists($email)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT user_id FROM users WHERE email=:email'
+ );
+ $query->execute([
+ ':email' => $email
+ ]);
+ $result = $query->fetchAll();
+ if (sizeof($result) === 1) {
+ return true;
+ }
+ return false;
+ }
+
+ private static function deleteUser($email)
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'DELETE FROM users WHERE email=:email'
+ );
+ $query->execute([
+ ':email' => $email
+ ]);
+ }
+
+ private static function deleteAllowedClients($email)
+ {
+ $user = self::getUser($email);
+ if (!$user) {
+ return;
}
- public static function getExistingVerifyTokens() {
- Db::connect();
- $query = Db::$pdo->prepare(
- 'SELECT code FROM verify'
- );
- $query->execute();
- $existingTokens = $query->fetchAll();
- return $existingTokens;
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'DELETE FROM allowedClients WHERE userId=:userId'
+ );
+ $query->execute([
+ ':userId' => $user['userId']
+ ]);
+ }
+
+ public static function deleteAccount($email)
+ {
+ if (!self::userEmailExists($email)) {
+ return;
}
- }
+ // FIXME: Delete storage;
+ self::deleteAllowedClients($email);
+ self::deleteUser($email);
+ }
+
+ public static function cleanupTokens()
+ {
+ Db::connect();
+
+ $now = new \DateTime();
+ $query = Db::$pdo->prepare(
+ 'DELETE FROM verify WHERE json_extract(data, \'$.expires\') < :now'
+ );
+ $query->execute([
+ ':now' => $now->getTimestamp()
+ ]);
+ }
+
+ public static function getExistingVerifyTokens()
+ {
+ Db::connect();
+ $query = Db::$pdo->prepare(
+ 'SELECT code FROM verify'
+ );
+ $query->execute();
+ $existingTokens = $query->fetchAll();
+ return $existingTokens;
+ }
+}
diff --git a/lib/Util.php b/lib/Util.php
index 642e687..639a61c 100644
--- a/lib/Util.php
+++ b/lib/Util.php
@@ -1,27 +1,39 @@
exec($statement);
- }
- } catch(\PDOException $e) {
- echo $e->getMessage();
- }
+ Db::connect();
+ try {
+ // create tables
+ foreach ($statements as $statement) {
+ Db::$pdo->exec($statement);
+ }
+ } catch (\PDOException $e) {
+ echo $e->getMessage();
+ }
- ClientRegistration::saveClientRegistration([
- "client_id" => "12345",
- "origin" => "https://example.com",
- "client_name" => "Client name"
- ]);
+ ClientRegistration::saveClientRegistration([
+ "client_id" => "12345",
+ "origin" => "https://example.com",
+ "client_name" => "Client name"
+ ]);
- ClientRegistration::saveClientRegistration([
- "client_id" => "23456",
- "origin" => "https://example2.com"
- ]);
+ ClientRegistration::saveClientRegistration([
+ "client_id" => "23456",
+ "origin" => "https://example2.com"
+ ]);
- ClientRegistration::saveClientRegistration([
- "client_id" => "34567",
- "origin" => "https://example2.com"
- ]);
- }
+ ClientRegistration::saveClientRegistration([
+ "client_id" => "34567",
+ "origin" => "https://example2.com"
+ ]);
+ }
- public function testGetRegistration() {
- $storedData = ClientRegistration::getRegistration("12345");
- $this->assertEquals("12345", $storedData['client_id']);
- $this->assertEquals("https://example.com", $storedData['origin']);
- $this->assertEquals("Client name", $storedData['client_name']);
- }
+ public function testGetRegistration()
+ {
+ $storedData = ClientRegistration::getRegistration("12345");
+ $this->assertEquals("12345", $storedData['client_id']);
+ $this->assertEquals("https://example.com", $storedData['origin']);
+ $this->assertEquals("Client name", $storedData['client_name']);
+ }
- public function testClientNameAutofill() {
- $storedData = ClientRegistration::getRegistration("23456");
- $this->assertEquals("23456", $storedData['client_id']);
- $this->assertEquals("https://example2.com", $storedData['origin']);
- $this->assertEquals("https://example2.com", $storedData['client_name']);
- }
+ public function testClientNameAutofill()
+ {
+ $storedData = ClientRegistration::getRegistration("23456");
+ $this->assertEquals("23456", $storedData['client_id']);
+ $this->assertEquals("https://example2.com", $storedData['origin']);
+ $this->assertEquals("https://example2.com", $storedData['client_name']);
+ }
- public function testClientByOrigin() {
- $storedData = ClientRegistration::getClientByOrigin("https://example.com");
- $this->assertEquals("12345", $storedData['client_id']);
- $this->assertEquals("https://example.com", $storedData['origin']);
- $this->assertEquals("Client name", $storedData['client_name']);
- }
+ public function testClientByOrigin()
+ {
+ $storedData = ClientRegistration::getClientByOrigin("https://example.com");
+ $this->assertEquals("12345", $storedData['client_id']);
+ $this->assertEquals("https://example.com", $storedData['origin']);
+ $this->assertEquals("Client name", $storedData['client_name']);
+ }
- public function testClientByDuplicateOrigin() {
- $storedData = ClientRegistration::getClientByOrigin("https://example2.com");
- $this->assertFalse($storedData); // false because we have 2 clients with the same origin
- }
+ public function testClientByDuplicateOrigin()
+ {
+ $storedData = ClientRegistration::getClientByOrigin("https://example2.com");
+ $this->assertFalse($storedData); // false because we have 2 clients with the same origin
+ }
}
diff --git a/tests/phpunit/DbTest.php b/tests/phpunit/DbTest.php
index b4e1d07..1a8885f 100644
--- a/tests/phpunit/DbTest.php
+++ b/tests/phpunit/DbTest.php
@@ -1,13 +1,15 @@
assertInstanceOf("PDO", Db::$pdo);
- }
- }
+use Pdsinterop\PhpSolid\Db;
+
+const DBPATH = ":memory:";
+class DbTest extends \PHPUnit\Framework\TestCase
+{
+ public function testConnect()
+ {
+ Db::connect();
+ $this->assertInstanceOf("PDO", Db::$pdo);
+ }
+}
diff --git a/tests/phpunit/IpAttemptsTest.php b/tests/phpunit/IpAttemptsTest.php
index df0373d..06d3635 100644
--- a/tests/phpunit/IpAttemptsTest.php
+++ b/tests/phpunit/IpAttemptsTest.php
@@ -1,4 +1,7 @@
exec($statement);
- }
- } catch(\PDOException $e) {
- echo $e->getMessage();
- }
- }
-
- public function testGetAttemptsCountZero() {
- $ip = "10.0.0.1";
- $count = IpAttempts::getAttemptsCount($ip, "test");
- $this->assertEquals(0, $count);
- }
-
- public function testGetAttemptsCountOne() {
- $ip = "10.0.0.1";
-
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
- $count = IpAttempts::getAttemptsCount($ip, "test");
- $this->assertEquals(1, $count);
- }
-
- public function testGetAttemptsCountTwo() {
- $ip = "10.0.0.1";
-
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
-
- $count = IpAttempts::getAttemptsCount($ip, "test");
- $this->assertEquals(2, $count);
- }
-
- public function testGetAttemptsCountExpired() {
- $ip = "10.0.0.1";
-
- IpAttempts::logFailedAttempt($ip, "test", time() - 1);
- IpAttempts::logFailedAttempt($ip, "test", time() - 1);
-
- $count = IpAttempts::getAttemptsCount($ip, "test");
- $this->assertEquals(0, $count);
- }
-
- public function testGetAttemptsCountOneExpired() {
- $ip = "10.0.0.1";
-
- IpAttempts::logFailedAttempt($ip, "test", time() + 10);
- IpAttempts::logFailedAttempt($ip, "test", time() - 1);
-
- $count = IpAttempts::getAttemptsCount($ip, "test");
- $this->assertEquals(1, $count);
- }
-
- public function testCleanup() {
- $ip = "10.0.0.1";
-
- IpAttempts::logFailedAttempt($ip, "test", time() - 1);
- IpAttempts::logFailedAttempt($ip, "test", time() - 1);
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
-
- $query = Db::$pdo->prepare('SELECT count(*) AS count FROM ipAttempts');
- $query->execute();
- $result = $query->fetchAll();
- $beforeCleanup = $result[0]['count'];
-
- $this->assertEquals(4, $beforeCleanup);
-
- IpAttempts::cleanupAttempts();
- $query = Db::$pdo->prepare('SELECT count(*) AS count FROM ipAttempts');
- $query->execute();
- $result = $query->fetchAll();
- $afterCleanup = $result[0]['count'];
-
- $this->assertEquals(2, $afterCleanup);
- }
-
- public function testTrustedIpGetAttempts() {
- $ip = "127.0.0.100"; // trusted IP
-
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
-
- $count = IpAttempts::getAttemptsCount($ip, "test");
- $this->assertEquals(0, $count);
- }
-
- public function testTrustedIpGetAttemptsSkipsDb() {
- $ip = "127.0.0.100"; // trusted IP
-
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
- IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
-
- $query = Db::$pdo->prepare('SELECT count(*) AS count FROM ipAttempts');
- $query->execute();
- $result = $query->fetchAll();
- $count = $result[0]['count'];
- $this->assertEquals(0, $count);
- }
+ )'
+ ];
+
+ Db::connect();
+ try {
+ // create tables
+ foreach ($statements as $statement) {
+ Db::$pdo->exec($statement);
+ }
+ } catch (\PDOException $e) {
+ echo $e->getMessage();
+ }
+ }
+
+ public function testGetAttemptsCountZero()
+ {
+ $ip = "10.0.0.1";
+ $count = IpAttempts::getAttemptsCount($ip, "test");
+ $this->assertEquals(0, $count);
+ }
+
+ public function testGetAttemptsCountOne()
+ {
+ $ip = "10.0.0.1";
+
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+ $count = IpAttempts::getAttemptsCount($ip, "test");
+ $this->assertEquals(1, $count);
+ }
+
+ public function testGetAttemptsCountTwo()
+ {
+ $ip = "10.0.0.1";
+
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+
+ $count = IpAttempts::getAttemptsCount($ip, "test");
+ $this->assertEquals(2, $count);
+ }
+
+ public function testGetAttemptsCountExpired()
+ {
+ $ip = "10.0.0.1";
+
+ IpAttempts::logFailedAttempt($ip, "test", time() - 1);
+ IpAttempts::logFailedAttempt($ip, "test", time() - 1);
+
+ $count = IpAttempts::getAttemptsCount($ip, "test");
+ $this->assertEquals(0, $count);
+ }
+
+ public function testGetAttemptsCountOneExpired()
+ {
+ $ip = "10.0.0.1";
+
+ IpAttempts::logFailedAttempt($ip, "test", time() + 10);
+ IpAttempts::logFailedAttempt($ip, "test", time() - 1);
+
+ $count = IpAttempts::getAttemptsCount($ip, "test");
+ $this->assertEquals(1, $count);
+ }
+
+ public function testCleanup()
+ {
+ $ip = "10.0.0.1";
+
+ IpAttempts::logFailedAttempt($ip, "test", time() - 1);
+ IpAttempts::logFailedAttempt($ip, "test", time() - 1);
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+
+ $query = Db::$pdo->prepare('SELECT count(*) AS count FROM ipAttempts');
+ $query->execute();
+ $result = $query->fetchAll();
+ $beforeCleanup = $result[0]['count'];
+
+ $this->assertEquals(4, $beforeCleanup);
+
+ IpAttempts::cleanupAttempts();
+ $query = Db::$pdo->prepare('SELECT count(*) AS count FROM ipAttempts');
+ $query->execute();
+ $result = $query->fetchAll();
+ $afterCleanup = $result[0]['count'];
+
+ $this->assertEquals(2, $afterCleanup);
+ }
+
+ public function testTrustedIpGetAttempts()
+ {
+ $ip = "127.0.0.100"; // trusted IP
+
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+
+ $count = IpAttempts::getAttemptsCount($ip, "test");
+ $this->assertEquals(0, $count);
+ }
+
+ public function testTrustedIpGetAttemptsSkipsDb()
+ {
+ $ip = "127.0.0.100"; // trusted IP
+
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+ IpAttempts::logFailedAttempt($ip, "test", time() + 3600);
+
+ $query = Db::$pdo->prepare('SELECT count(*) AS count FROM ipAttempts');
+ $query->execute();
+ $result = $query->fetchAll();
+ $count = $result[0]['count'];
+ $this->assertEquals(0, $count);
+ }
}
diff --git a/tests/phpunit/JtiStoreTest.php b/tests/phpunit/JtiStoreTest.php
index 602afa4..b0b2b53 100644
--- a/tests/phpunit/JtiStoreTest.php
+++ b/tests/phpunit/JtiStoreTest.php
@@ -1,4 +1,7 @@
exec($statement);
+ }
+ } catch (\PDOException $e) {
+ echo $e->getMessage();
+ }
+ }
- Db::connect();
- try {
- // create tables
- foreach($statements as $statement){
- Db::$pdo->exec($statement);
- }
- } catch(\PDOException $e) {
- echo $e->getMessage();
- }
- }
+ public function testNonExistingJti()
+ {
+ $jti = "123";
+ $found = JtiStore::hasJti($jti);
+ $this->assertFalse($found);
+ }
- public function testNonExistingJti() {
- $jti = "123";
- $found = JtiStore::hasJti($jti);
- $this->assertFalse($found);
- }
+ public function testExistingJti()
+ {
+ $jti = "123";
+ JtiStore::saveJti($jti, time() + 3600);
+ $found = JtiStore::hasJti($jti);
+ $this->assertTrue($found);
+ }
- public function testExistingJti() {
- $jti = "123";
- JtiStore::saveJti($jti, time() + 3600);
- $found = JtiStore::hasJti($jti);
- $this->assertTrue($found);
- }
+ public function testExpiredJti()
+ {
+ $jti = "123";
+ JtiStore::saveJti($jti);
+ $query = Db::$pdo->prepare('UPDATE jti SET expires=:expires WHERE jti=:jti');
+ $query->execute([
+ 'expires' => time() - 10,
+ 'jti' => $jti
+ ]);
+ $found = JtiStore::hasJti($jti);
+ $this->assertFalse($found);
+ }
- public function testExpiredJti() {
- $jti = "123";
- JtiStore::saveJti($jti);
- $query = Db::$pdo->prepare('UPDATE jti SET expires=:expires WHERE jti=:jti');
- $query->execute([
- 'expires' => time() - 10,
- 'jti' => $jti
- ]);
- $found = JtiStore::hasJti($jti);
- $this->assertFalse($found);
- }
+ public function testCleanup()
+ {
+ JtiStore::saveJti("123");
+ JtiStore::saveJti("234");
- public function testCleanup() {
- JtiStore::saveJti("123");
- JtiStore::saveJti("234");
+ $query = Db::$pdo->prepare('UPDATE jti SET expires=:expires WHERE jti=:jti');
+ $query->execute([
+ 'expires' => time() - 10,
+ 'jti' => "123"
+ ]);
+ $query = Db::$pdo->prepare('UPDATE jti SET expires=:expires WHERE jti=:jti');
+ $query->execute([
+ 'expires' => time() - 10,
+ 'jti' => "234"
+ ]);
- $query = Db::$pdo->prepare('UPDATE jti SET expires=:expires WHERE jti=:jti');
- $query->execute([
- 'expires' => time() - 10,
- 'jti' => "123"
- ]);
- $query = Db::$pdo->prepare('UPDATE jti SET expires=:expires WHERE jti=:jti');
- $query->execute([
- 'expires' => time() - 10,
- 'jti' => "234"
- ]);
+ $query = Db::$pdo->prepare('SELECT count(*) AS count FROM jti');
+ $query->execute();
+ $result = $query->fetchAll();
+ $beforeCleanup = $result[0]['count'];
+ $this->assertEquals(2, $beforeCleanup);
- $query = Db::$pdo->prepare('SELECT count(*) AS count FROM jti');
- $query->execute();
- $result = $query->fetchAll();
- $beforeCleanup = $result[0]['count'];
- $this->assertEquals(2, $beforeCleanup);
-
- JtiStore::cleanupJti();
- $query = Db::$pdo->prepare('SELECT count(*) AS count FROM jti');
- $query->execute();
- $result = $query->fetchAll();
- $afterCleanup = $result[0]['count'];
+ JtiStore::cleanupJti();
+ $query = Db::$pdo->prepare('SELECT count(*) AS count FROM jti');
+ $query->execute();
+ $result = $query->fetchAll();
+ $afterCleanup = $result[0]['count'];
- $this->assertEquals(0, $afterCleanup);
- }
+ $this->assertEquals(0, $afterCleanup);
+ }
}
diff --git a/tests/phpunit/MailerTest.php b/tests/phpunit/MailerTest.php
index 05bb284..222f592 100644
--- a/tests/phpunit/MailerTest.php
+++ b/tests/phpunit/MailerTest.php
@@ -1,132 +1,145 @@
"mailerHost",
- "user" => "mailerUser",
- "password" => "mailerPass",
- "port" => "1337",
- "from" => "alice@example.com"
- ];
+namespace Pdsinterop\PhpSolid;
- const MAILSTYLES = [];
+use Pdsinterop\PhpSolid\Mailer;
- const BASEURL = "https://example.com";
+const MAILER = [
+ "host" => "mailerHost",
+ "user" => "mailerUser",
+ "password" => "mailerPass",
+ "port" => "1337",
+ "from" => "alice@example.com"
+];
- class MailerMock {
- public $Subject;
- public $Body;
- public $AltBody;
- public $addresses = [];
+const MAILSTYLES = [];
- public function addAddress($address) {
- $this->addresses[] = $address;
- }
- public function send() {
- return true;
- }
- }
+const BASEURL = "https://example.com";
- class MailerTest extends \PHPUnit\Framework\TestCase
- {
- public function testGetMailer() {
- $mailer = Mailer::getMailer();
- $this->assertInstanceOf('\PHPMailer\PHPMailer\PHPMailer', $mailer);
- $this->assertEquals($mailer->Host, MAILER['host']);
- $this->assertEquals($mailer->From, MAILER['from']);
- $this->assertEquals($mailer->Port, MAILER['port']);
- $this->assertEquals($mailer->Username, MAILER['user']);
- $this->assertEquals($mailer->Password, MAILER['password']);
- $this->assertEquals($mailer->SMTPAuth, true);
- $this->assertEquals($mailer->SMTPDebug, 0);
- $this->assertEquals($mailer->XMailer, null);
- $this->assertEquals($mailer->ContentType, "text/html");
- $this->assertEquals($mailer->Mailer, "smtp");
- }
+class MailerMock
+{
+ public $Subject;
+ public $Body;
+ public $AltBody;
+ public $addresses = [];
- public function testAccountCreated() {
- Mailer::$mailer = new MailerMock();
- Mailer::sendAccountCreated([
- 'email' => 'alice@example.com',
- 'webId' => 'aliceWebId'
- ]);
- $this->assertContains("alice@example.com", Mailer::$mailer->addresses);
- $this->assertMatchesRegularExpression("/aliceWebId/", Mailer::$mailer->AltBody);
- $this->assertMatchesRegularExpression("/aliceWebId/", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("|Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $doc = new \DOMDocument();
- $doc->loadHTML(Mailer::$mailer->Body);
- $this->assertEquals("Welcome to Solid!", $doc->getElementsByTagName("title")[0]->textContent); // If this works, I'm assuming it is valid HTML.
- }
+ public function addAddress($address)
+ {
+ $this->addresses[] = $address;
+ }
- public function testVerify() {
- Mailer::$mailer = new MailerMock();
- Mailer::sendVerify([
- 'email' => 'alice@example.com',
- 'code' => '654321'
- ]);
- $this->assertContains("alice@example.com", Mailer::$mailer->addresses);
- $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->AltBody);
- $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("|Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $doc = new \DOMDocument();
- $doc->loadHTML(Mailer::$mailer->Body);
- $this->assertEquals("Confirm your e-mail", $doc->getElementsByTagName("title")[0]->textContent); // If this works, I'm assuming it is valid HTML.
- }
+ public function send()
+ {
+ return true;
+ }
+}
- public function testResetPassword() {
- Mailer::$mailer = new MailerMock();
- Mailer::sendResetPassword([
- 'email' => 'alice@example.com',
- 'code' => '654321'
- ]);
- $this->assertContains("alice@example.com", Mailer::$mailer->addresses);
- $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->AltBody);
- $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("|Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $doc = new \DOMDocument();
- $doc->loadHTML(Mailer::$mailer->Body);
- $this->assertEquals("Password reset", $doc->getElementsByTagName("title")[0]->textContent); // If this works, I'm assuming it is valid HTML.
- }
+class MailerTest extends \PHPUnit\Framework\TestCase
+{
+ public function testGetMailer()
+ {
+ $mailer = Mailer::getMailer();
+ $this->assertInstanceOf('\PHPMailer\PHPMailer\PHPMailer', $mailer);
+ $this->assertEquals($mailer->Host, MAILER['host']);
+ $this->assertEquals($mailer->From, MAILER['from']);
+ $this->assertEquals($mailer->Port, MAILER['port']);
+ $this->assertEquals($mailer->Username, MAILER['user']);
+ $this->assertEquals($mailer->Password, MAILER['password']);
+ $this->assertEquals($mailer->SMTPAuth, true);
+ $this->assertEquals($mailer->SMTPDebug, 0);
+ $this->assertEquals($mailer->XMailer, null);
+ $this->assertEquals($mailer->ContentType, "text/html");
+ $this->assertEquals($mailer->Mailer, "smtp");
+ }
- public function testDeleteAccount() {
- Mailer::$mailer = new MailerMock();
- Mailer::sendDeleteAccount([
- 'email' => 'alice@example.com',
- 'code' => '654321'
- ]);
- $this->assertContains("alice@example.com", Mailer::$mailer->addresses);
- $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->AltBody);
- $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $this->assertMatchesRegularExpression("|Body);
- $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
- $doc = new \DOMDocument();
- $doc->loadHTML(Mailer::$mailer->Body);
- $this->assertEquals("Delete your account", $doc->getElementsByTagName("title")[0]->textContent); // If this works, I'm assuming it is valid HTML.
- }
- }
+ public function testAccountCreated()
+ {
+ Mailer::$mailer = new MailerMock();
+ Mailer::sendAccountCreated([
+ 'email' => 'alice@example.com',
+ 'webId' => 'aliceWebId'
+ ]);
+ $this->assertContains("alice@example.com", Mailer::$mailer->addresses);
+ $this->assertMatchesRegularExpression("/aliceWebId/", Mailer::$mailer->AltBody);
+ $this->assertMatchesRegularExpression("/aliceWebId/", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("|Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $doc = new \DOMDocument();
+ $doc->loadHTML(Mailer::$mailer->Body);
+ $this->assertEquals("Welcome to Solid!", $doc->getElementsByTagName("title")[0]->textContent); // If this works, I'm assuming it is valid HTML.
+ }
+
+ public function testVerify()
+ {
+ Mailer::$mailer = new MailerMock();
+ Mailer::sendVerify([
+ 'email' => 'alice@example.com',
+ 'code' => '654321'
+ ]);
+ $this->assertContains("alice@example.com", Mailer::$mailer->addresses);
+ $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->AltBody);
+ $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("|Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $doc = new \DOMDocument();
+ $doc->loadHTML(Mailer::$mailer->Body);
+ $this->assertEquals("Confirm your e-mail", $doc->getElementsByTagName("title")[0]->textContent); // If this works, I'm assuming it is valid HTML.
+ }
+
+ public function testResetPassword()
+ {
+ Mailer::$mailer = new MailerMock();
+ Mailer::sendResetPassword([
+ 'email' => 'alice@example.com',
+ 'code' => '654321'
+ ]);
+ $this->assertContains("alice@example.com", Mailer::$mailer->addresses);
+ $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->AltBody);
+ $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("|Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $doc = new \DOMDocument();
+ $doc->loadHTML(Mailer::$mailer->Body);
+ $this->assertEquals("Password reset", $doc->getElementsByTagName("title")[0]->textContent); // If this works, I'm assuming it is valid HTML.
+ }
+
+ public function testDeleteAccount()
+ {
+ Mailer::$mailer = new MailerMock();
+ Mailer::sendDeleteAccount([
+ 'email' => 'alice@example.com',
+ 'code' => '654321'
+ ]);
+ $this->assertContains("alice@example.com", Mailer::$mailer->addresses);
+ $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->AltBody);
+ $this->assertMatchesRegularExpression("/654321/", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("//", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $this->assertMatchesRegularExpression("|Body);
+ $this->assertMatchesRegularExpression("||", Mailer::$mailer->Body);
+ $doc = new \DOMDocument();
+ $doc->loadHTML(Mailer::$mailer->Body);
+ $this->assertEquals("Delete your account", $doc->getElementsByTagName("title")[0]->textContent); // If this works, I'm assuming it is valid HTML.
+ }
+}
diff --git a/tests/phpunit/MiddlewareTest.php b/tests/phpunit/MiddlewareTest.php
index ca741c6..4f90347 100644
--- a/tests/phpunit/MiddlewareTest.php
+++ b/tests/phpunit/MiddlewareTest.php
@@ -1,40 +1,47 @@
assertTrue(in_array("Access-Control-Allow-Origin: *", self::$headers));
- $this->assertTrue(in_array("Access-Control-Allow-Headers: *, allow, accept, authorization, content-type, dpop, slug, link", self::$headers));
- $this->assertTrue(in_array("Access-Control-Allow-Methods: GET, PUT, POST, OPTIONS, DELETE, PATCH", self::$headers));
- $this->assertTrue(in_array("Access-Control-Max-Age: 1728000", self::$headers));
- $this->assertTrue(in_array("Access-Control-Allow-Credentials: true", self::$headers));
- $this->assertTrue(in_array("Accept-Patch: text/n3", self::$headers));
- $this->assertTrue(in_array("Access-Control-Expose-Headers: Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via", self::$headers));
- }
-
- public function testCorsWithOrigin() {
- $origin = "https://example.com";
- $_REQUEST['HTTP_ORIGIN'] = $origin;
-
- Middleware::cors();
- $this->assertTrue(in_array("Access-Control-Allow-Origin: $origin", self::$headers));
- $this->assertTrue(in_array("Access-Control-Allow-Headers: *, allow, accept, authorization, content-type, dpop, slug, link", self::$headers));
- $this->assertTrue(in_array("Access-Control-Allow-Methods: GET, PUT, POST, OPTIONS, DELETE, PATCH", self::$headers));
- $this->assertTrue(in_array("Access-Control-Max-Age: 1728000", self::$headers));
- $this->assertTrue(in_array("Access-Control-Allow-Credentials: true", self::$headers));
- $this->assertTrue(in_array("Accept-Patch: text/n3", self::$headers));
- $this->assertTrue(in_array("Access-Control-Expose-Headers: Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via", self::$headers));
- }
-
- public function testPubSub() {
- Middleware::pubsub();
- $this->assertTrue(in_array("updates-via: " . PUBSUB_SERVER, self::$headers));
- }
- }
+
+// phpcs:disable Generic.Files.LineLength.TooLong
+// phpcs:disable PSR1.Files.SideEffects.FoundWithSymbols
+
+namespace Pdsinterop\PhpSolid;
+
+require_once(__DIR__ . "/test-config.php");
+
+use Pdsinterop\PhpSolid\Middleware;
+
+class MiddlewareTest extends \PHPUnit\Framework\TestCase
+{
+ public static $headers = [];
+ public function testCors()
+ {
+ Middleware::cors();
+ $this->assertTrue(in_array("Access-Control-Allow-Origin: *", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Allow-Headers: *, allow, accept, authorization, content-type, dpop, slug, link", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Allow-Methods: GET, PUT, POST, OPTIONS, DELETE, PATCH", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Max-Age: 1728000", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Allow-Credentials: true", self::$headers));
+ $this->assertTrue(in_array("Accept-Patch: text/n3", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Expose-Headers: Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via", self::$headers));
+ }
+
+ public function testCorsWithOrigin()
+ {
+ $origin = "https://example.com";
+ $_REQUEST['HTTP_ORIGIN'] = $origin;
+
+ Middleware::cors();
+ $this->assertTrue(in_array("Access-Control-Allow-Origin: $origin", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Allow-Headers: *, allow, accept, authorization, content-type, dpop, slug, link", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Allow-Methods: GET, PUT, POST, OPTIONS, DELETE, PATCH", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Max-Age: 1728000", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Allow-Credentials: true", self::$headers));
+ $this->assertTrue(in_array("Accept-Patch: text/n3", self::$headers));
+ $this->assertTrue(in_array("Access-Control-Expose-Headers: Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via", self::$headers));
+ }
+
+ public function testPubSub()
+ {
+ Middleware::pubsub();
+ $this->assertTrue(in_array("updates-via: " . PUBSUB_SERVER, self::$headers));
+ }
+}
diff --git a/tests/phpunit/PasswordValidatorTest.php b/tests/phpunit/PasswordValidatorTest.php
index 9930219..8a62493 100644
--- a/tests/phpunit/PasswordValidatorTest.php
+++ b/tests/phpunit/PasswordValidatorTest.php
@@ -1,79 +1,80 @@
assertEquals(26, PasswordValidator::getBase($password));
- }
+ public function testBaseLower()
+ {
+ $password = "aaa";
+ $this->assertEquals(26, PasswordValidator::getBase($password));
+ }
- public function testBaseUpper()
- {
- $password = "AAA";
- $this->assertEquals(26, PasswordValidator::getBase($password));
- }
+ public function testBaseUpper()
+ {
+ $password = "AAA";
+ $this->assertEquals(26, PasswordValidator::getBase($password));
+ }
- public function testBaseNumbers()
- {
- $password = "123";
- $this->assertEquals(10, PasswordValidator::getBase($password));
- }
+ public function testBaseNumbers()
+ {
+ $password = "123";
+ $this->assertEquals(10, PasswordValidator::getBase($password));
+ }
- public function testBaseSpecial()
- {
- $password = "!@#$";
- $this->assertEquals(32, PasswordValidator::getBase($password));
- }
+ public function testBaseSpecial()
+ {
+ $password = "!@#$";
+ $this->assertEquals(32, PasswordValidator::getBase($password));
+ }
- public function testBaseUpperAndLower()
- {
- $password = "aaaAAA";
- $this->assertEquals(52, PasswordValidator::getBase($password));
- }
+ public function testBaseUpperAndLower()
+ {
+ $password = "aaaAAA";
+ $this->assertEquals(52, PasswordValidator::getBase($password));
+ }
- public function testLengthLower()
- {
- $password = "aaa";
- $this->assertEquals(2, PasswordValidator::getLength($password));
- }
+ public function testLengthLower()
+ {
+ $password = "aaa";
+ $this->assertEquals(2, PasswordValidator::getLength($password));
+ }
- public function testLengthUpper()
- {
- $password = "AAA";
- $this->assertEquals(2, PasswordValidator::getLength($password));
- }
+ public function testLengthUpper()
+ {
+ $password = "AAA";
+ $this->assertEquals(2, PasswordValidator::getLength($password));
+ }
- public function testLengthNumbers()
- {
- $password = "123";
- $this->assertEquals(3, PasswordValidator::getLength($password));
- }
+ public function testLengthNumbers()
+ {
+ $password = "123";
+ $this->assertEquals(3, PasswordValidator::getLength($password));
+ }
- public function testLengthSpecial()
- {
- $password = "!@#$";
- $this->assertEquals(4, PasswordValidator::getLength($password));
- }
+ public function testLengthSpecial()
+ {
+ $password = "!@#$";
+ $this->assertEquals(4, PasswordValidator::getLength($password));
+ }
- public function testLengthUpperAndLower()
- {
- $password = "aaaAAA";
- $this->assertEquals(4, PasswordValidator::getLength($password));
- }
+ public function testLengthUpperAndLower()
+ {
+ $password = "aaaAAA";
+ $this->assertEquals(4, PasswordValidator::getLength($password));
+ }
- public function testSimplyEntropy()
- {
- $values = [
- ["password" => "aaa", "expected" => 6.52],
- ["password" => "abc", "expected" => 9.77]
- ];
+ public function testSimplyEntropy()
+ {
+ $values = [
+ ["password" => "aaa", "expected" => 6.52],
+ ["password" => "abc", "expected" => 9.77]
+ ];
- foreach ($values as $value) {
- $this->assertEquals($value['expected'], PasswordValidator::getEntropy($value['password']));
- }
- }
+ foreach ($values as $value) {
+ $this->assertEquals($value['expected'], PasswordValidator::getEntropy($value['password']));
+ }
+ }
}
diff --git a/tests/phpunit/ServerTest.php b/tests/phpunit/ServerTest.php
index 4709147..f60cc83 100644
--- a/tests/phpunit/ServerTest.php
+++ b/tests/phpunit/ServerTest.php
@@ -1,125 +1,139 @@
exec($statement);
- }
- } catch(\PDOException $e) {
- echo $e->getMessage();
- }
-
- ClientRegistration::saveClientRegistration([
- "client_id" => "1234",
- "origin" => "https://example.com",
- "redirect_uris" => ["https://example.com"],
- "client_name" => "Client name"
- ]);
- }
-
- public function testGenerateKeySet() {
- $keys = Server::generateKeySet();
- $this->assertTrue(isset($keys['encryptionKey']));
- $this->assertTrue(isset($keys['publicKey']));
- $this->assertTrue(isset($keys['privateKey']));
- $this->assertMatchesRegularExpression("/BEGIN PUBLIC KEY/", $keys['publicKey']);
- $this->assertMatchesRegularExpression("/BEGIN PRIVATE KEY/", $keys['privateKey']);
- }
-
-
- public function testGetAuthServer() {
- $authServer = Server::getAuthServer();
- $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Server', $authServer);
- }
-
- public function testGetAuthServerConfig() {
- $authServerConfig = Server::getAuthServerConfig();
- $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Config', $authServerConfig);
- }
-
- public function testGetConfigClient() {
- $configClient = Server::getConfigClient();
- $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Config\Client', $configClient);
- }
-
- public function testGetConfigClientWithGetId() {
- $_GET['client_id'] = '1234';
- $configClient = Server::getConfigClient();
- $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Config\Client', $configClient);
- }
-
- public function testGetConfigClientWithPostd() {
- $_POST['client_id'] = '1234';
- $configClient = Server::getConfigClient();
- $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Config\Client', $configClient);
- }
- public function testGetDpop() {
- $dpop = Server::getDpop();
- $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Utils\Dpop', $dpop);
- }
- public function testGetBearer() {
- $bearer = Server::getBearer();
- $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Utils\Bearer', $bearer);
- }
- public function testGetEndpoints() {
- $endpoints = Server::getEndpoints();
- $this->assertEquals($endpoints["issuer"], "https://solid.example.com");
- $this->assertEquals($endpoints["jwks_uri"], "https://solid.example.com/jwks/");
- $this->assertEquals($endpoints["check_session_iframe"], "https://solid.example.com/session/");
- $this->assertEquals($endpoints["end_session_endpoint"], "https://solid.example.com/logout/");
- $this->assertEquals($endpoints["authorization_endpoint"], "https://solid.example.com/authorize/");
- $this->assertEquals($endpoints["token_endpoint"], "https://solid.example.com/token/");
- $this->assertEquals($endpoints["userinfo_endpoint"], "https://solid.example.com/userinfo/");
- $this->assertEquals($endpoints["registration_endpoint"], "https://solid.example.com/register/");
- }
-
- public function testGetKeys() {
- $keys = Server::getKeys();
- $this->assertTrue(isset($keys['encryptionKey']));
- $this->assertTrue(isset($keys['publicKey']));
- $this->assertTrue(isset($keys['privateKey']));
- $this->assertMatchesRegularExpression("/BEGIN PUBLIC KEY/", $keys['publicKey']);
- $this->assertMatchesRegularExpression("/BEGIN PRIVATE KEY/", $keys['privateKey']);
- }
-
- public function testGetTokenGenerator() {
- $tokenGenerator = Server::getTokenGenerator();
- $this->assertInstanceOf('\Pdsinterop\Solid\Auth\TokenGenerator', $tokenGenerator);
- }
-
- public function testRespond() {
- $response = new MockResponse();
- ob_start();
- Server::respond($response);
- $sentBody = ob_get_contents();
- ob_end_clean();
- $this->assertTrue(in_array("HTTP/1.1 200", ServerTest::$headers));
- $this->assertTrue(in_array("Foo:Bar", ServerTest::$headers));
- $this->assertTrue(in_array("Foo:Blah", ServerTest::$headers));
-
- $this->assertEquals($sentBody, "{\n \"Hello\": \"world\"\n}");
- }
- }
+// phpcs:disable PSR1.Files.SideEffects.FoundWithSymbols
+
+namespace Pdsinterop\PhpSolid;
+
+require_once(__DIR__ . "/test-config.php");
+
+use Pdsinterop\PhpSolid\Server;
+
+class ServerTest extends \PHPUnit\Framework\TestCase
+{
+ public static $headers = [];
+ public static $keys;
+
+ protected function setUp(): void
+ {
+ $statements = [
+ 'DROP TABLE IF EXISTS clients',
+ 'CREATE TABLE clients (
+ clientId VARCHAR(255) NOT NULL PRIMARY KEY,
+ origin TEXT NOT NULL,
+ clientData TEXT NOT NULL
+ )'
+ ];
+
+ Db::connect();
+ try {
+ // create tables
+ foreach ($statements as $statement) {
+ Db::$pdo->exec($statement);
+ }
+ } catch (\PDOException $e) {
+ echo $e->getMessage();
+ }
+
+ ClientRegistration::saveClientRegistration([
+ "client_id" => "1234",
+ "origin" => "https://example.com",
+ "redirect_uris" => ["https://example.com"],
+ "client_name" => "Client name"
+ ]);
+ }
+
+ public function testGenerateKeySet()
+ {
+ $keys = Server::generateKeySet();
+ $this->assertTrue(isset($keys['encryptionKey']));
+ $this->assertTrue(isset($keys['publicKey']));
+ $this->assertTrue(isset($keys['privateKey']));
+ $this->assertMatchesRegularExpression("/BEGIN PUBLIC KEY/", $keys['publicKey']);
+ $this->assertMatchesRegularExpression("/BEGIN PRIVATE KEY/", $keys['privateKey']);
+ }
+
+
+ public function testGetAuthServer()
+ {
+ $authServer = Server::getAuthServer();
+ $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Server', $authServer);
+ }
+
+ public function testGetAuthServerConfig()
+ {
+ $authServerConfig = Server::getAuthServerConfig();
+ $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Config', $authServerConfig);
+ }
+
+ public function testGetConfigClient()
+ {
+ $configClient = Server::getConfigClient();
+ $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Config\Client', $configClient);
+ }
+
+ public function testGetConfigClientWithGetId()
+ {
+ $_GET['client_id'] = '1234';
+ $configClient = Server::getConfigClient();
+ $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Config\Client', $configClient);
+ }
+
+ public function testGetConfigClientWithPostd()
+ {
+ $_POST['client_id'] = '1234';
+ $configClient = Server::getConfigClient();
+ $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Config\Client', $configClient);
+ }
+ public function testGetDpop()
+ {
+ $dpop = Server::getDpop();
+ $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Utils\Dpop', $dpop);
+ }
+ public function testGetBearer()
+ {
+ $bearer = Server::getBearer();
+ $this->assertInstanceOf('\Pdsinterop\Solid\Auth\Utils\Bearer', $bearer);
+ }
+ public function testGetEndpoints()
+ {
+ $endpoints = Server::getEndpoints();
+ $this->assertEquals($endpoints["issuer"], "https://solid.example.com");
+ $this->assertEquals($endpoints["jwks_uri"], "https://solid.example.com/jwks/");
+ $this->assertEquals($endpoints["check_session_iframe"], "https://solid.example.com/session/");
+ $this->assertEquals($endpoints["end_session_endpoint"], "https://solid.example.com/logout/");
+ $this->assertEquals($endpoints["authorization_endpoint"], "https://solid.example.com/authorize/");
+ $this->assertEquals($endpoints["token_endpoint"], "https://solid.example.com/token/");
+ $this->assertEquals($endpoints["userinfo_endpoint"], "https://solid.example.com/userinfo/");
+ $this->assertEquals($endpoints["registration_endpoint"], "https://solid.example.com/register/");
+ }
+
+ public function testGetKeys()
+ {
+ $keys = Server::getKeys();
+ $this->assertTrue(isset($keys['encryptionKey']));
+ $this->assertTrue(isset($keys['publicKey']));
+ $this->assertTrue(isset($keys['privateKey']));
+ $this->assertMatchesRegularExpression("/BEGIN PUBLIC KEY/", $keys['publicKey']);
+ $this->assertMatchesRegularExpression("/BEGIN PRIVATE KEY/", $keys['privateKey']);
+ }
+
+ public function testGetTokenGenerator()
+ {
+ $tokenGenerator = Server::getTokenGenerator();
+ $this->assertInstanceOf('\Pdsinterop\Solid\Auth\TokenGenerator', $tokenGenerator);
+ }
+
+ public function testRespond()
+ {
+ $response = new MockResponse();
+ ob_start();
+ Server::respond($response);
+ $sentBody = ob_get_contents();
+ ob_end_clean();
+ $this->assertTrue(in_array("HTTP/1.1 200", ServerTest::$headers));
+ $this->assertTrue(in_array("Foo:Bar", ServerTest::$headers));
+ $this->assertTrue(in_array("Foo:Blah", ServerTest::$headers));
+
+ $this->assertEquals($sentBody, "{\n \"Hello\": \"world\"\n}");
+ }
+}
diff --git a/tests/phpunit/SessionTest.php b/tests/phpunit/SessionTest.php
index cf176e0..1fa40e8 100644
--- a/tests/phpunit/SessionTest.php
+++ b/tests/phpunit/SessionTest.php
@@ -1,24 +1,28 @@
assertEquals($_SESSION['username'], "alice");
- $this->assertEquals(self::$sessionOptions, ['cookie_lifetime' => 86400]);
- }
+function session_start($options = [])
+{
+ SessionTest::$sessionOptions = $options;
+}
- public function testGetLoggedInUser() {
- Session::start("alice");
- $user = Session::getLoggedInUser();
- $this->assertEquals($user, "alice");
- }
- }
+class SessionTest extends \PHPUnit\Framework\TestCase
+{
+ public static $sessionOptions = [];
+ public function testStart()
+ {
+ Session::start("alice");
+ $this->assertEquals($_SESSION['username'], "alice");
+ $this->assertEquals(self::$sessionOptions, ['cookie_lifetime' => 86400]);
+ }
+
+ public function testGetLoggedInUser()
+ {
+ Session::start("alice");
+ $user = Session::getLoggedInUser();
+ $this->assertEquals($user, "alice");
+ }
+}
diff --git a/tests/phpunit/StorageServerTest.php b/tests/phpunit/StorageServerTest.php
index aa35038..c1c7fc7 100644
--- a/tests/phpunit/StorageServerTest.php
+++ b/tests/phpunit/StorageServerTest.php
@@ -1,137 +1,144 @@
exec($statement);
- }
- } catch(\PDOException $e) {
- echo $e->getMessage();
- }
-
- $newUser = [
- "password" => "hello123!@#ABC",
- "email" => "alice@example.com",
- "hello" => "world"
- ];
- self::$createdUser = User::createUser($newUser);
- self::$createdStorage = StorageServer::createStorage(self::$createdUser['webId']);
-
- $_SERVER['REQUEST_URI'] = "/test/";
- $_SERVER['REQUEST_SCHEME'] = "https";
- $_SERVER['SERVER_NAME'] = "storage-" . self::$createdStorage['storageId'] . ".example.com";
- }
-
- public function testGetFileSystem() {
- $filesystem = StorageServer::getFileSystem();
- $this->assertInstanceOf('\League\Flysystem\Filesystem', $filesystem);
- }
-
-
- public function testRespond() {
- $response = new MockResponse();
- ob_start();
- StorageServer::respond($response);
- $sentBody = ob_get_contents();
- ob_end_clean();
- $this->assertTrue(in_array("HTTP/1.1 200", StorageServerTest::$headers));
- $this->assertTrue(in_array("Foo:Bar", StorageServerTest::$headers));
- $this->assertTrue(in_array("Foo:Blah", StorageServerTest::$headers));
-
- $this->assertEquals($sentBody, "{\"Hello\":\"world\"}");
- }
-
- public function testGetOwnerWebId() {
- $webId = StorageServer::getOwnerWebId();
- $this->assertEquals(self::$createdUser['webId'], $webId);
- }
-
- public function testGenerateDefaultAcl() {
- $defaultAcl = StorageServer::generateDefaultAcl();
- $this->assertTrue(strpos($defaultAcl, self::$createdUser['webId']) > 0);
- $this->assertMatchesRegularExpression("/@prefix/", $defaultAcl);
- }
-
- public function testGeneratePublicAppendAcl() {
- $publicAppendAcl = StorageServer::generatePublicAppendAcl();
- $this->assertTrue(strpos($publicAppendAcl, self::$createdUser['webId']) > 0);
- $this->assertMatchesRegularExpression("/@prefix/", $publicAppendAcl);
- }
-
- public function testGeneratePublicReadAcl() {
- $publicReadAcl = StorageServer::generatePublicReadAcl();
- $this->assertTrue(strpos($publicReadAcl, self::$createdUser['webId']) > 0);
- $this->assertMatchesRegularExpression("/@prefix/", $publicReadAcl);
- }
-
- public function testGenerateDefaultPrivateTypeIndex() {
- $privateTypeIndex = StorageServer::generateDefaultPrivateTypeIndex();
- $this->assertTrue(strpos($privateTypeIndex, "UnlistedDocument") > 0);
- $this->assertMatchesRegularExpression("/@prefix/", $privateTypeIndex);
- }
-
- public function testGenerateDefaultPublicTypeIndex() {
- $publicTypeIndex = StorageServer::generateDefaultPublicTypeIndex();
- $this->assertTrue(strpos($publicTypeIndex, "ListedDocument") > 0);
- $this->assertMatchesRegularExpression("/@prefix/", $publicTypeIndex);
- }
-
- public function testGenerateDefaultPreferences() {
- $preferences = StorageServer::generateDefaultPreferences();
- $this->assertTrue(strpos($preferences, "ConfigurationFile") > 0);
- $this->assertMatchesRegularExpression("/@prefix/", $preferences);
- }
-
- /*
- Currently untested:
- public static function getWebId($rawRequest) {
- public static function initializeStorage() {
- public static function getStorage($storageId) {
- public static function setStorageOwner($storageId, $owner) {
- public static function createStorage($ownerWebId) {
- public static function storageIdExists($storageId) {
- */
- }
-
-
-
-
\ No newline at end of file
+
+// phpcs:disable PSR1.Files.SideEffects.FoundWithSymbols
+
+namespace Pdsinterop\PhpSolid;
+
+require_once(__DIR__ . "/test-config.php");
+
+use Pdsinterop\PhpSolid\StorageServer;
+
+class StorageServerTest extends \PHPUnit\Framework\TestCase
+{
+ public static $headers = [];
+ public static $createdUser;
+ public static $createdStorage;
+
+ protected function setUp(): void
+ {
+ $statements = [
+ 'DROP TABLE IF EXISTS allowedClients',
+ 'DROP TABLE IF EXISTS userStorage',
+ 'DROP TABLE IF EXISTS users',
+ 'DROP TABLE IF EXISTS storage',
+ 'CREATE TABLE IF NOT EXISTS allowedClients (
+ userId VARCHAR(255) NOT NULL PRIMARY KEY,
+ clientId VARCHAR(255) NOT NULL
+ )',
+ 'CREATE TABLE IF NOT EXISTS userStorage (
+ userId VARCHAR(255) NOT NULL PRIMARY KEY,
+ storageUrl VARCHAR(255) NOT NULL
+ )',
+ 'CREATE TABLE IF NOT EXISTS users (
+ user_id VARCHAR(255) NOT NULL PRIMARY KEY,
+ email TEXT NOT NULL,
+ password TEXT NOT NULL,
+ data TEXT
+ )',
+ 'CREATE TABLE IF NOT EXISTS storage (
+ storage_id VARCHAR(255) NOT NULL PRIMARY KEY,
+ owner VARCHAR(255) NOT NULL
+ )',
+ ];
+
+ Db::connect();
+ try {
+ // create tables
+ foreach ($statements as $statement) {
+ Db::$pdo->exec($statement);
+ }
+ } catch (\PDOException $e) {
+ echo $e->getMessage();
+ }
+
+ $newUser = [
+ "password" => "hello123!@#ABC",
+ "email" => "alice@example.com",
+ "hello" => "world"
+ ];
+ self::$createdUser = User::createUser($newUser);
+ self::$createdStorage = StorageServer::createStorage(self::$createdUser['webId']);
+
+ $_SERVER['REQUEST_URI'] = "/test/";
+ $_SERVER['REQUEST_SCHEME'] = "https";
+ $_SERVER['SERVER_NAME'] = "storage-" . self::$createdStorage['storageId'] . ".example.com";
+ }
+
+ public function testGetFileSystem()
+ {
+ $filesystem = StorageServer::getFileSystem();
+ $this->assertInstanceOf('\League\Flysystem\Filesystem', $filesystem);
+ }
+
+ public function testRespond()
+ {
+ $response = new MockResponse();
+ ob_start();
+ StorageServer::respond($response);
+ $sentBody = ob_get_contents();
+ ob_end_clean();
+ $this->assertTrue(in_array("HTTP/1.1 200", StorageServerTest::$headers));
+ $this->assertTrue(in_array("Foo:Bar", StorageServerTest::$headers));
+ $this->assertTrue(in_array("Foo:Blah", StorageServerTest::$headers));
+
+ $this->assertEquals($sentBody, "{\"Hello\":\"world\"}");
+ }
+
+ public function testGetOwnerWebId()
+ {
+ $webId = StorageServer::getOwnerWebId();
+ $this->assertEquals(self::$createdUser['webId'], $webId);
+ }
+
+ public function testGenerateDefaultAcl()
+ {
+ $defaultAcl = StorageServer::generateDefaultAcl();
+ $this->assertTrue(strpos($defaultAcl, self::$createdUser['webId']) > 0);
+ $this->assertMatchesRegularExpression("/@prefix/", $defaultAcl);
+ }
+
+ public function testGeneratePublicAppendAcl()
+ {
+ $publicAppendAcl = StorageServer::generatePublicAppendAcl();
+ $this->assertTrue(strpos($publicAppendAcl, self::$createdUser['webId']) > 0);
+ $this->assertMatchesRegularExpression("/@prefix/", $publicAppendAcl);
+ }
+
+ public function testGeneratePublicReadAcl()
+ {
+ $publicReadAcl = StorageServer::generatePublicReadAcl();
+ $this->assertTrue(strpos($publicReadAcl, self::$createdUser['webId']) > 0);
+ $this->assertMatchesRegularExpression("/@prefix/", $publicReadAcl);
+ }
+
+ public function testGenerateDefaultPrivateTypeIndex()
+ {
+ $privateTypeIndex = StorageServer::generateDefaultPrivateTypeIndex();
+ $this->assertTrue(strpos($privateTypeIndex, "UnlistedDocument") > 0);
+ $this->assertMatchesRegularExpression("/@prefix/", $privateTypeIndex);
+ }
+
+ public function testGenerateDefaultPublicTypeIndex()
+ {
+ $publicTypeIndex = StorageServer::generateDefaultPublicTypeIndex();
+ $this->assertTrue(strpos($publicTypeIndex, "ListedDocument") > 0);
+ $this->assertMatchesRegularExpression("/@prefix/", $publicTypeIndex);
+ }
+
+ public function testGenerateDefaultPreferences()
+ {
+ $preferences = StorageServer::generateDefaultPreferences();
+ $this->assertTrue(strpos($preferences, "ConfigurationFile") > 0);
+ $this->assertMatchesRegularExpression("/@prefix/", $preferences);
+ }
+
+ /*
+ Currently untested:
+ public static function getWebId($rawRequest) {
+ public static function initializeStorage() {
+ public static function getStorage($storageId) {
+ public static function setStorageOwner($storageId, $owner) {
+ public static function createStorage($ownerWebId) {
+ public static function storageIdExists($storageId) {
+ */
+}
diff --git a/tests/phpunit/UserTest.php b/tests/phpunit/UserTest.php
index 80cd184..be5e07f 100644
--- a/tests/phpunit/UserTest.php
+++ b/tests/phpunit/UserTest.php
@@ -1,4 +1,8 @@
exec($statement);
}
- } catch(\PDOException $e) {
+ } catch (\PDOException $e) {
echo $e->getMessage();
}
}
- public function testSaveVerifyToken() {
+ public function testSaveVerifyToken()
+ {
$beforeExpires = new \DateTime();
$beforeExpires->add(new \DateInterval('PT29M'));
@@ -66,7 +71,8 @@ public function testSaveVerifyToken() {
$this->assertEquals($storedToken['hello'], "world");
}
- public function testSavePasswordResetToken() {
+ public function testSavePasswordResetToken()
+ {
$beforeExpires = new \DateTime();
$beforeExpires->add(new \DateInterval('PT29M'));
@@ -82,7 +88,8 @@ public function testSavePasswordResetToken() {
$this->assertEquals($storedToken['hello'], "world");
}
- public function testSaveAccountDeleteToken() {
+ public function testSaveAccountDeleteToken()
+ {
$beforeExpires = new \DateTime();
$beforeExpires->add(new \DateInterval('PT29M'));
@@ -98,17 +105,20 @@ public function testSaveAccountDeleteToken() {
$this->assertEquals($storedToken['hello'], "world");
}
- public function testExpiredToken() {
+ public function testExpiredToken()
+ {
$token = User::getVerifyToken("test1");
$this->assertFalse($token);
}
- public function testNonExpiredToken() {
+ public function testNonExpiredToken()
+ {
$token = User::getVerifyToken("test2");
$this->assertEquals($token['hello'], "world");
}
- public function testCreateUser() {
+ public function testCreateUser()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user@example.com",
@@ -123,8 +133,9 @@ public function testCreateUser() {
$canLogIn = User::checkPassword($newUser['email'], $newUser['password']);
$this->assertTrue($canLogIn);
}
-
- public function testGetUser() {
+
+ public function testGetUser()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user2@example.com",
@@ -133,13 +144,14 @@ public function testGetUser() {
$createdUser = User::createUser($newUser);
$userByEmail = User::getUser($newUser['email']);
- $this->assertEquals($userByEmail['webId'], $createdUser['webId']);
+ $this->assertEquals($userByEmail['webId'], $createdUser['webId']);
$this->assertEquals($userByEmail['hello'], 'world');
$this->assertTrue(isset($userByEmail['allowedClients']));
$this->assertEquals($userByEmail['issuer'], "https://solid.example.com");
}
-
- public function testGetUserById() {
+
+ public function testGetUserById()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user3@example.com",
@@ -148,18 +160,20 @@ public function testGetUserById() {
$createdUser = User::createUser($newUser);
$userById = User::getUserById($createdUser['userId']);
- $this->assertEquals($userById['webId'], $createdUser['webId']);
+ $this->assertEquals($userById['webId'], $createdUser['webId']);
$this->assertEquals($userById['hello'], 'world');
$this->assertTrue(isset($userById['allowedClients']));
$this->assertEquals($userById['issuer'], "https://solid.example.com");
}
- public function testSetPasswordNonExistingUser() {
+ public function testSetPasswordNonExistingUser()
+ {
$result = User::setUserPassword("not_here@example.com", "hello123!@#ABC");
$this->assertFalse($result);
}
- public function testSetWeakPassword() {
+ public function testSetWeakPassword()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user4@example.com",
@@ -170,43 +184,47 @@ public function testSetWeakPassword() {
$this->assertFalse($result);
}
- public function testLogin() {
+ public function testLogin()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user5@example.com",
"hello" => "world"
];
$createdUser = User::createUser($newUser);
-
+
$canLogIn = User::checkPassword($newUser['email'], $newUser['password']);
$this->assertTrue($canLogIn);
}
- public function testLoginFailed() {
+ public function testLoginFailed()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user6@example.com",
"hello" => "world"
];
$createdUser = User::createUser($newUser);
-
+
$canLogIn = User::checkPassword($newUser['email'], "something else");
$this->assertFalse($canLogIn);
}
- public function testSetStrongPassword() {
+ public function testSetStrongPassword()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user7@example.com",
"hello" => "world"
];
$createdUser = User::createUser($newUser);
-
+
$result = User::setUserPassword($newUser['email'], "this is a strong password because it is long enough");
$this->assertTrue($result);
}
- public function testLoginAfterChange() {
+ public function testLoginAfterChange()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user8@example.com",
@@ -215,7 +233,7 @@ public function testLoginAfterChange() {
$createdUser = User::createUser($newUser);
$canLogIn = User::checkPassword($newUser['email'], $newUser['password']);
$this->assertTrue($canLogIn);
-
+
$newPassword = "this is a strong password because it is long enough";
$result = User::setUserPassword($newUser['email'], $newPassword);
$this->assertTrue($result);
@@ -229,8 +247,9 @@ public function testLoginAfterChange() {
$canLogIn = User::checkPassword($newUser['email'], $newPassword);
$this->assertTrue($canLogIn);
}
-
- public function testUserStorage() {
+
+ public function testUserStorage()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user9@example.com",
@@ -239,50 +258,55 @@ public function testUserStorage() {
$createdUser = User::createUser($newUser);
$storageUrl = "https://storage.example.com";
User::setStorage($createdUser['userId'], $storageUrl);
-
+
$savedStorage = User::getStorage($createdUser['userId']);
-
+
$this->assertTrue(in_array($storageUrl, $savedStorage));
$user = User::getUser($newUser['email']);
$this->assertTrue(in_array($storageUrl, $user['storage']));
}
- public function testUserExistsById() {
+ public function testUserExistsById()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user10@example.com",
"hello" => "world"
];
$createdUser = User::createUser($newUser);
-
+
$userExists = User::userIdExists($createdUser['userId']);
$this->assertTrue($userExists);
}
- public function testUserDoesNotExistsById() {
+ public function testUserDoesNotExistsById()
+ {
$userExists = User::userIdExists("foo");
$this->assertFalse($userExists);
}
- public function testUserExistsByEmail() {
+ public function testUserExistsByEmail()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user11@example.com",
"hello" => "world"
];
$createdUser = User::createUser($newUser);
-
+
$userExists = User::userEmailExists($newUser['email']);
$this->assertTrue($userExists);
}
- public function testUserDoesNotExistsByEmail() {
+ public function testUserDoesNotExistsByEmail()
+ {
$userExists = User::userEmailExists("foo@example.com");
$this->assertFalse($userExists);
}
- public function testAllowClientForUser() {
+ public function testAllowClientForUser()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user11@example.com",
@@ -301,7 +325,8 @@ public function testAllowClientForUser() {
$this->assertTrue(in_array($clientId, $user['allowedClients']));
}
- public function testDeleteAccount() {
+ public function testDeleteAccount()
+ {
$newUser = [
"password" => "hello123!@#ABC",
"email" => "user11@example.com",
@@ -324,7 +349,8 @@ public function testDeleteAccount() {
$this->assertEmpty($allowedClients);
}
- public function testCleanup() {
+ public function testCleanup()
+ {
// empty the verify table first so we have dependable numbers
$query = Db::$pdo->prepare('DELETE FROM verify WHERE NOT code=""');
$query->execute();
diff --git a/tests/phpunit/UtilTest.php b/tests/phpunit/UtilTest.php
index c92b71b..ea0b776 100644
--- a/tests/phpunit/UtilTest.php
+++ b/tests/phpunit/UtilTest.php
@@ -1,14 +1,16 @@
assertEquals($string, $decoded);
- }
+ public function testBase64EncodeDecode()
+ {
+ $string = "this is a test string with more stuffing";
+ $encoded = Util::base64_url_encode($string);
+ $decoded = Util::base64_url_decode($encoded);
+ $this->assertEquals($string, $decoded);
+ }
}
diff --git a/tests/phpunit/test-config.php b/tests/phpunit/test-config.php
index f91f9ac..57f99e1 100644
--- a/tests/phpunit/test-config.php
+++ b/tests/phpunit/test-config.php
@@ -1,4 +1,7 @@
"world"]);
- }
+class MockBody
+{
+ public function rewind()
+ {
+ return true;
+ }
+ public function getContents()
+ {
+ return json_encode(["Hello" => "world"]);
+ }
}
-class MockResponse {
- public function getStatusCode() {
- return 200;
- }
- public function getBody() {
- return new MockBody();
- }
- public function getHeaders() {
- return [
- "Foo" => ["Bar", "Blah"]
- ];
- }
+class MockResponse
+{
+ public function getStatusCode()
+ {
+ return 200;
+ }
+ public function getBody()
+ {
+ return new MockBody();
+ }
+ public function getHeaders()
+ {
+ return [
+ "Foo" => ["Bar", "Blah"]
+ ];
+ }
}
diff --git a/tests/testsuite/init-testsuite.php b/tests/testsuite/init-testsuite.php
index cb8026a..fa2f55c 100644
--- a/tests/testsuite/init-testsuite.php
+++ b/tests/testsuite/init-testsuite.php
@@ -1,58 +1,66 @@
prepare(
- 'INSERT INTO users VALUES (:userId, :email, :passwordHash, :data)'
- );
-
- $queryParams = [];
- $queryParams[':userId'] = $testUser['id'];
- $queryParams[':email'] = $testUser['email'];
- $queryParams[':passwordHash'] = password_hash($testUser['password'], PASSWORD_BCRYPT);
-
- $testUser['webId'] = "https://id-" . $testUser['id'] . "." . BASEDOMAIN . "/#me";
- $queryParams[':data'] = json_encode($testUser);
- $query->execute($queryParams);
+class TestUser
+{
+ private static $pdo;
+ private static function connect()
+ {
+ if (!isset(self::$pdo)) {
+ self::$pdo = new \PDO("sqlite:" . DBPATH);
}
+ }
- public static function createStorage($testUser) {
- self::connect();
- $query = self::$pdo->prepare(
- 'INSERT INTO storage VALUES (:storageId, :owner)'
- );
+ public static function createUser($testUser)
+ {
+ self::connect();
+ $query = self::$pdo->prepare(
+ 'INSERT INTO users VALUES (:userId, :email, :passwordHash, :data)'
+ );
- $queryParams = [];
- $queryParams[':storageId'] = $testUser['id'];
- $queryParams[':owner'] = "https://id-" . $testUser['id'] . "." . BASEDOMAIN . "/#me";
- $query->execute($queryParams);
- }
- }
-
- TestUser::createUser([
- "id" => "alice",
- "password" => "alice123",
- "email" => "alice"
- ]);
- TestUser::createStorage([
- "id" => "alice"
- ]);
-
- TestUser::createUser([
- "id" => "bob",
- "password" => "bob345",
- "email" => "bob"
- ]);
- TestUser::createStorage([
- "id" => "bob"
- ]);
-
\ No newline at end of file
+ $queryParams = [];
+ $queryParams[':userId'] = $testUser['id'];
+ $queryParams[':email'] = $testUser['email'];
+ $queryParams[':passwordHash'] = password_hash($testUser['password'], PASSWORD_BCRYPT);
+
+ $testUser['webId'] = "https://id-" . $testUser['id'] . "." . BASEDOMAIN . "/#me";
+ $queryParams[':data'] = json_encode($testUser);
+ $query->execute($queryParams);
+ }
+
+ public static function createStorage($testUser)
+ {
+ self::connect();
+ $query = self::$pdo->prepare(
+ 'INSERT INTO storage VALUES (:storageId, :owner)'
+ );
+
+ $queryParams = [];
+ $queryParams[':storageId'] = $testUser['id'];
+ $queryParams[':owner'] = "https://id-" . $testUser['id'] . "." . BASEDOMAIN . "/#me";
+ $query->execute($queryParams);
+ }
+}
+
+TestUser::createUser([
+ "id" => "alice",
+ "password" => "alice123",
+ "email" => "alice"
+]);
+TestUser::createStorage([
+ "id" => "alice"
+]);
+
+TestUser::createUser([
+ "id" => "bob",
+ "password" => "bob345",
+ "email" => "bob"
+]);
+
+TestUser::createStorage([
+ "id" => "bob"
+]);
diff --git a/www/idp/index.php b/www/idp/index.php
index 40d0473..b094054 100644
--- a/www/idp/index.php
+++ b/www/idp/index.php
@@ -1,141 +1,141 @@