Unstyled browser-based activation process
authorChristian Weiske <cweiske@cweiske.de>
Wed, 24 May 2023 19:11:13 +0000 (21:11 +0200)
committerChristian Weiske <cweiske@cweiske.de>
Wed, 24 May 2023 19:11:13 +0000 (21:11 +0200)
src/ProfileDb.php
templates/activate-code.phtml [new file with mode: 0644]
templates/activate-profile.phtml [new file with mode: 0644]
templates/activate-success.phtml [new file with mode: 0644]
www/.htaccess
www/activate.php [new file with mode: 0644]

index 7f661b79bdac21e3df7019e6418d59815ace9e2d..5eed7262d1bbd16b246ec69f8f121b493f840a56 100644 (file)
@@ -40,6 +40,15 @@ class ProfileDb
         return $row === false ? null : $row;
     }
 
+    public function getProfileByVerificationCode(string $code): ?Profile
+    {
+        $stmt = $this->db->prepare('SELECT * FROM gamesticks WHERE verificationCode = :code');
+        $stmt->setFetchMode(PDO::FETCH_CLASS, 'Profile');
+        $stmt->execute([':code' => $code]);
+        $row = $stmt->fetch();
+        return $row === false ? null : $row;
+    }
+
     public function createProfile(string $hwId): Profile
     {
         $stmt = $this->db->prepare(
@@ -59,6 +68,26 @@ SQL
         return $this->getProfileByHardwareId($hwId);
     }
 
+    public function updateProfile(string $hwId, array $values): ?Profile
+    {
+        $params = [
+            'hwId' => $hwId,
+        ];
+
+        $sql = 'UPDATE gamesticks SET';
+        $sqlParts = [];
+        foreach ($values as $column => $value) {
+            $sqlParts[] = ' ' . $column . '= :' . $column;
+            $params[':' . $column] = $value;
+        }
+        $sql .= implode(', ', $sqlParts) . ' WHERE hwId = :hwId';
+
+        $stmt = $this->db->prepare($sql);
+        $stmt->execute($params);
+
+        return $this->getProfileByHardwareId($hwId);
+    }
+
     protected function createTablesIfNeeded()
     {
         $res = $this->db->query(
diff --git a/templates/activate-code.phtml b/templates/activate-code.phtml
new file mode 100644 (file)
index 0000000..16da967
--- /dev/null
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta charset="utf-8"/>
+    <title>GameStick activation: Code</title>
+    <style>
+      .error {
+        color: red;
+      }
+    </style>
+  </head>
+  <body>
+    <h1>PlayJam GameStick activation</h1>
+    <form method="post" action="activate.php">
+      <div>
+        <label for="code">Verification code:</label>
+        <input name="code" type="text" value="<?= htmlspecialchars($code) ?>"/>
+      </div>
+      <?php if ($error): ?>
+      <div>
+        <p class="error"><?= htmlspecialchars($error) ?></p>
+      </div>
+      <?php endif ?>
+      <button type="submit">Submit</button>
+    </form>
+  </body>
+</html>
diff --git a/templates/activate-profile.phtml b/templates/activate-profile.phtml
new file mode 100644 (file)
index 0000000..c455af6
--- /dev/null
@@ -0,0 +1,106 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta charset="utf-8"/>
+    <title>GameStick activation: Profile</title>
+    <style>
+      .error {
+        color: red;
+      }
+    </style>
+  </head>
+  <body>
+    <h1>PlayJam GameStick activation: Profile</h1>
+    <form method="post" action="activate.php">
+      <input type="hidden" name="code" value="<?= htmlspecialchars($code) ?>"/>
+
+      <?php if ($input['submit'] && count($errors)): ?>
+      <div style="color: red">
+        Errors:
+        <ul>
+          <?php foreach ($errors as $msg): ?>
+          <li><?= htmlspecialchars($msg) ?></li>
+          <?php endforeach ?>
+        </ul>
+      </div>
+      <?php endif ?>
+
+      <div>
+        <label for="gamerTag">Gamer tag:</label>
+        <input id="gamerTag" name="gamerTag" type="text"
+          value="<?= htmlspecialchars($input['gamerTag']) ?>"
+          pattern="[a-zA-Z0-9 ]+"
+          required=""
+          title="Allowed: A-Z, a-z, 0-9, space"
+        />
+      </div>
+
+      <div>
+        <label>
+          <input id="founderFlag" name="founderFlag" type="checkbox"
+            value="1"
+            <?php if ($input['founderFlag']) { echo 'checked=""';} ?>
+          />
+          I am a founder
+        </label>
+      </div>
+
+      <div>
+        <label for="founderName">Founder name:</label>
+        <input id="founderName" name="founderName" type="text"
+          value="<?= htmlspecialchars($input['founderName']) ?>"
+          pattern="[a-zA-Z0-9 ]*"
+          title="Allowed: A-Z, a-z, 0-9, space"
+          />
+      </div>
+
+      <div>
+        <label>Show games suitable for ages:</label>
+        <label>
+          <input type="radio" name="minAge" value="3"
+            <?php if ($input['minAge'] == 3) { echo 'checked=""';} ?>
+          />
+          3+
+        </label><br/>
+
+        <label>
+          <input type="radio" name="minAge" value="7"
+            <?php if ($input['minAge'] == 7) { echo 'checked=""';} ?>
+          />
+          7+
+        </label><br/>
+
+        <label>
+          <input type="radio" name="minAge" value="12"
+            <?php if ($input['minAge'] == 12) { echo 'checked=""';} ?>
+          />
+          12+
+        </label><br/>
+
+        <label>
+          <input type="radio" name="minAge" value="17"
+            <?php if ($input['minAge'] == 17) { echo 'checked=""';} ?>
+          />
+          17+
+        </label><br/>
+      </div>
+
+      <div>
+        <label>Avatar image:</label>
+        <?php foreach ($avatars as $key => $smallImagePath): ?>
+        <label>
+          <input type="radio" name="avatar" value="<?= htmlspecialchars($key) ?>"
+            <?php if ($input['avatar'] == $key) { echo 'checked=""';} ?>
+          />
+          <img src="<?= htmlspecialchars($smallImagePath) ?>"
+            alt="Avatar <?= htmlspecialchars($key) ?>"
+            width="118" height="118"
+          />
+        </label><br/>
+        <?php endforeach ?>
+
+      </div>
+
+      <button name="submit" value="1" type="submit">Submit</button>
+    </form>
+  </body>
+</html>
diff --git a/templates/activate-success.phtml b/templates/activate-success.phtml
new file mode 100644 (file)
index 0000000..cc7f858
--- /dev/null
@@ -0,0 +1,13 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta charset="utf-8"/>
+    <title>GameStick activation: Success</title>
+  </head>
+  <body>
+    <h1>PlayJam GameStick activation complete</h1>
+    <p>
+      Your profile has been updated.
+      You can continue with your GameStick setup.
+    </p>
+  </body>
+</html>
index 5c1b8bed93830f88e8021ae820d2046faf6bfd41..2e40d0b1da775eb6442a3f0945a2186faa937b22 100644 (file)
@@ -1,8 +1,7 @@
 RewriteEngine on
 RewriteBase /
 
-RewriteRule ^connect_check.php$ - [R=204,L]
-RewriteRule ^generate_204 - [R=204,L]
+RewriteRule ^activate$ /activate.php [END]
 
 RewriteRule ^api/rest/analytics/application-event/analytics/event/view.json(.*)$ /api/rest/analytics/application-event/analytics/event/view.json [END]
 RewriteRule ^api/rest/analytics/game/(.*)/event/(.*)/view.json(.*)$ /api/rest/analytics/application-event/analytics/event/view.json [END]
@@ -12,3 +11,6 @@ RewriteRule ^api/rest/connect/stick/stick/(.*)/view.json;jsessionid=(.*)$ /api/r
 
 RewriteRule ^api/rest/player/profile/view.json$ /api/rest/player/profile.php [END]
 RewriteRule ^api/rest/player/profile/view.json;jsessionid=(.*)$ /api/rest/player/profile.php?jsessionid=$1 [END]
+
+RewriteRule ^connect_check.php$ - [R=204,L]
+RewriteRule ^generate_204 - [R=204,L]
diff --git a/www/activate.php b/www/activate.php
new file mode 100644 (file)
index 0000000..454c7e0
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+$rootDir = dirname(__FILE__, 2);
+$tplDir = $rootDir . '/templates';
+
+require_once $rootDir . '/config.php';
+require $rootDir . '/src/ProfileDb.php';
+$profileDb = new ProfileDb();
+
+$error   = null;
+$code    = '';
+$profile = null;
+if (isset($_REQUEST['code']) && trim($_REQUEST['code']) !== '') {
+    $code = $_REQUEST['code'];
+
+    $profile = $profileDb->getProfileByVerificationCode($code);
+    if ($profile === null) {
+        $error = 'Invalid code';
+    }
+}
+
+if ($profile === null) {
+    require $tplDir . '/activate-code.phtml';
+    exit();
+}
+
+$input = [
+    'gamerTag'    => $_POST['gamerTag'] ?? null,
+    'founderFlag' => (bool) ($_POST['founderFlag'] ?? false),
+    'founderName' => $_POST['founderName'] ?? null,
+    'minAge'      => $_POST['minAge'] ?? 3,
+    'avatar'      => $_POST['avatar'] ?? 'avatar_1',
+    'submit'      => $_POST['submit'] ?? false,
+];
+
+$avatars = [];
+foreach (glob(__DIR__ . '/../www/resources/avatars/*.small.jpg') as $smallImage) {
+    $key = basename($smallImage, '.small.jpg');
+    $avatars[$key] = '/resources/avatars/' . basename($smallImage);
+}
+
+//input validation
+$errors = [];
+if (!preg_match('#^[A-Za-z0-9 ]+$#', $input['gamerTag'])) {
+    $errors['gamerTag'] = 'Invalid gamer tag';
+}
+if ($input['founderFlag']) {
+    if ($input['founderName'] === '') {
+        $errors['founderName'] = 'Founder name missing';
+    } else if (!preg_match('#^[A-Za-z0-9 ]+$#', $input['founderName'])) {
+        $errors['founderName'] = 'Invalid founder name';
+    }
+}
+if (!in_array($input['minAge'], [3, 7, 12, 17])) {
+    $errors['minAge'] = 'Invalid age';
+}
+if (!in_array($input['avatar'], array_keys($avatars))) {
+    $errors['avatar'] = 'Invalid avatar image';
+}
+
+if (!$input['submit'] || count($errors)) {
+    require $tplDir . '/activate-profile.phtml';
+    exit();
+}
+
+//validation successful, store the profile
+//$input['verificationCode'] => null;
+unset($input['submit']);
+$profile = $profileDb->updateProfile($profile->hwId, $input);
+
+require $tplDir . '/activate-success.phtml';