Skip to content

refactor(puzzel-dashboard): rename directory from puzzle-dashboard to puzzel-dashboard#815

Closed
nicomiguelino wants to merge 2 commits into
feat/puzzle-dashboardfrom
feat/puzzel-app-2
Closed

refactor(puzzel-dashboard): rename directory from puzzle-dashboard to puzzel-dashboard#815
nicomiguelino wants to merge 2 commits into
feat/puzzle-dashboardfrom
feat/puzzel-app-2

Conversation

@nicomiguelino

@nicomiguelino nicomiguelino commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

User description

Renames the puzzle-dashboard directory to puzzel-dashboard to match the intended app name.


PR Type

Enhancement, Documentation


Description

  • Adds Puzzel dashboard Edge App

  • Embeds configured dashboard URL fullscreen

  • Automates two-step Puzzel login

  • Documents settings and deployment


Diagram Walkthrough

flowchart LR
  settings["Screenly settings"]
  app["Puzzel Edge App"]
  iframe["Fullscreen dashboard iframe"]
  inject["Injected login automation"]
  puzzel["Puzzel dashboard"]

  settings -- "provides URL and credentials" --> app
  app -- "loads dashboard_url" --> iframe
  iframe -- "opens" --> puzzel
  settings -- "provides username/password" --> inject
  inject -- "fills login forms" --> puzzel
Loading

File Walkthrough

Relevant files
Enhancement
screenly_inject.js
Automate Puzzel two-step login flow                                           

edge-apps/puzzel-dashboard/screenly_inject.js

  • Adds injected browser script for Puzzel login.
  • Fills #Input_Username from screenly_settings.username.
  • Fills #Input_Password from screenly_settings.password.
  • Clicks the visible submit button for each login step.
[link]   
index.html
Embed configured dashboard in fullscreen iframe                   

edge-apps/puzzel-dashboard/index.html

  • Adds the app entrypoint HTML page.
  • Renders a fullscreen iframe with no borders.
  • Loads screenly.js?version=1 for Screenly integration.
  • Sets iframe src from dashboard_url and signals readiness.
[link]   
Documentation
README.md
Document Puzzel dashboard app usage                                           

edge-apps/puzzel-dashboard/README.md

  • Documents the Puzzel Dashboard Edge App purpose.
  • Explains iframe loading and injected login behavior.
  • Lists required settings and login selectors.
  • Adds deployment commands for Screenly Edge Apps.
[link]   
Configuration changes
screenly.yml
Configure Puzzel Edge App manifest                                             

edge-apps/puzzel-dashboard/screenly.yml

  • Adds Screenly manifest for the Puzzel dashboard app.
  • Enables ready_signal integration.
  • Defines dashboard, username, and password settings.
  • Categorizes the app under dashboards.
[link]   

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

PR Reviewer Guide 🔍

(Review updated until commit cf11e1b)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 Security concerns

Credential leak:
screenly_inject.js enters and submits the configured username/password without checking that it is running on the expected Puzzel login origin. A malicious or accidentally configured dashboard_url could receive those credentials if it serves fields with the same IDs.

⚡ Recommended focus areas for review

Credential Leak

The injection script fills and submits credentials based only on field IDs, without verifying the current host or login path. If dashboard_url is misconfigured or redirects to a non-Puzzel page that contains matching selectors, the app can submit the configured Puzzel credentials to that page. Add an explicit location.hostname/path check before using screenly_settings.username or screenly_settings.password.

if (document.querySelector('#Input_Username')) {
  if (!setValue('#Input_Username', screenly_settings.username)) {
    console.log('[screenly_inject] Username field not found.')
  } else {
    const submitBtn = document.querySelector(
      'button.submit-button[type="submit"]:not(.hidden)',
    )
    if (submitBtn) {
      submitBtn.click()
    } else {
      console.log('[screenly_inject] Submit button not found.')
    }
  }
}

// Step 2 — password field
if (document.querySelector('#Input_Password')) {
  if (!setValue('#Input_Password', screenly_settings.password)) {
Broken Path

The manifest still points the icon URL at puzzle-dashboard while this app was added under puzzel-dashboard. If the hosted path follows the app directory name, the icon will 404 in the app listing.

icon: https://playground.srly.io/edge-apps/puzzle-dashboard/static/img/icon.svg

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

PR Code Suggestions ✨

Latest suggestions up to cf11e1b
Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix manifest identification

Set a concrete id value so the manifest does not serialize id as null, which can
cause deployment or app identification failures. Also update the icon path to match
the renamed puzzel-dashboard directory so the asset URL does not point at the old
app path.

edge-apps/puzzel-dashboard/screenly.yml [3-5]

-id:
+id: puzzel-dashboard
 description: Puzzel Dashboard
-icon: https://playground.srly.io/edge-apps/puzzle-dashboard/static/img/icon.svg
+icon: https://playground.srly.io/edge-apps/puzzel-dashboard/static/img/icon.svg
Suggestion importance[1-10]: 8

__

Why: The id: field is blank and likely serializes to null, which can break manifest validation or app identification. The icon URL also appears to use puzzle-dashboard instead of the PR's puzzel-dashboard path, so this is a relevant deployment-quality fix.

Medium
Prevent duplicate login submission

Avoid running the password-step logic in the same injection pass after submitting
the username step. If both fields are present in the DOM, the current code can click
the submit button twice or submit the wrong step before navigation completes.

edge-apps/puzzel-dashboard/screenly_inject.js [20-36]

 if (document.querySelector('#Input_Username')) {
   if (!setValue('#Input_Username', screenly_settings.username)) {
     console.log('[screenly_inject] Username field not found.')
   } else {
     const submitBtn = document.querySelector(
       'button.submit-button[type="submit"]:not(.hidden)',
     )
     if (submitBtn) {
       submitBtn.click()
     } else {
       console.log('[screenly_inject] Submit button not found.')
     }
   }
-}
+} else if (document.querySelector('#Input_Password')) {
 
-// Step 2 — password field
-if (document.querySelector('#Input_Password')) {
-
Suggestion importance[1-10]: 6

__

Why: The existing code uses two independent if blocks, so both login branches can run if both #Input_Username and #Input_Password exist in the DOM. Changing the second branch to else if is a reasonable defensive fix, though the actual Puzzel flow may normally expose only one field at a time.

Low
Avoid invalid credential submission

Guard against missing credential values before assigning them to an input. Without
this, undefined or null can be converted into literal field values and submitted to
the login form.

edge-apps/puzzel-dashboard/screenly_inject.js [7-13]

 function setValue(selector, value) {
   const el = document.querySelector(selector)
-  if (!el) return false
+  if (!el || value == null) return false
   el.value = value
   el.dispatchEvent(new Event('change', { bubbles: true }))
   return true
 }
Suggestion importance[1-10]: 5

__

Why: Guarding value == null prevents undefined or null credentials from being assigned to login inputs and submitted. This is a valid robustness improvement, but it is limited in impact and still allows empty strings from the configured defaults.

Low

Previous suggestions

Suggestions up to commit a333f44
CategorySuggestion                                                                                                                                    Impact
General
Wait for iframe readiness

screenly.signalReadyForRendering() is called immediately after assigning
dashboard.src, so the player may start rendering while the iframe is still blank or
loading. Wait for the iframe load event before signaling readiness when
dashboard_url is present.

edge-apps/puzzel-dashboard/index.html [43-50]

 const settings = await screenly.settings
 const url = settings.dashboard_url
+const dashboard = document.getElementById('dashboard')
 
 if (url) {
-  document.getElementById('dashboard').src = url
+  dashboard.addEventListener(
+    'load',
+    () => screenly.signalReadyForRendering(),
+    { once: true },
+  )
+  dashboard.src = url
+} else {
+  screenly.signalReadyForRendering()
 }
 
-screenly.signalReadyForRendering()
-
Suggestion importance[1-10]: 7

__

Why: The suggestion accurately targets the dashboard.src assignment and improves ready_signal correctness by avoiding rendering while the iframe may still be blank. It is a meaningful reliability improvement, though it could leave the app unready if the iframe never fires load.

Medium
Possible issue
Retry asynchronous login form

Auth0 pages often render form fields asynchronously after the page load event, so a
single immediate lookup can miss the inputs and permanently skip login. Retry
briefly until the fields and submit button exist before filling and clicking them.

edge-apps/puzzel-dashboard/screenly_inject.js [37-54]

 onPath('/u/login', () => {
-  if (
-    !setValue('#username', screenly_settings.username) ||
-    !setValue('#password', screenly_settings.password)
-  ) {
-    console.log('[screenly_inject] Login fields not found.')
-    return
+  const maxAttempts = 20
+  let attempts = 0
+
+  const tryLogin = () => {
+    attempts += 1
+
+    if (
+      !setReactValue('#username', screenly_settings.username) ||
+      !setReactValue('#password', screenly_settings.password)
+    ) {
+      if (attempts < maxAttempts) setTimeout(tryLogin, 500)
+      else console.log('[screenly_inject] Login fields not found.')
+      return
+    }
+
+    const submitBtn = document.querySelector(
+      'button[data-action-button-primary="true"]',
+    )
+    if (submitBtn) {
+      submitBtn.click()
+    } else if (attempts < maxAttempts) {
+      setTimeout(tryLogin, 500)
+    } else {
+      console.log('[screenly_inject] Submit button not found.')
+    }
   }
 
-  const submitBtn = document.querySelector(
-    'button[data-action-button-primary="true"]',
-  )
-  if (submitBtn) {
-    submitBtn.click()
-  } else {
-    console.log('[screenly_inject] Submit button not found.')
-  }
+  tryLogin()
 })
Suggestion importance[1-10]: 7

__

Why: The suggestion is contextually relevant because Auth0 login elements can appear after the injected script runs, and retrying makes the auto-login flow more robust. Using the existing setReactValue helper is also sensible for React-controlled fields.

Medium
Security
Validate embedded URL scheme

Assigning dashboard_url directly to iframe.src allows unsafe schemes such as
javascript: or unexpected local URLs if the setting is misconfigured. Validate that
url uses http: or https: before loading it.

edge-apps/puzzel-dashboard/index.html [46-48]

 if (url) {
-  document.getElementById('dashboard').src = url
+  const dashboardUrl = new URL(url)
+
+  if (['http:', 'https:'].includes(dashboardUrl.protocol)) {
+    document.getElementById('dashboard').src = dashboardUrl.href
+  } else {
+    console.log('[puzzel-dashboard] Invalid dashboard URL protocol.')
+  }
 }
Suggestion importance[1-10]: 4

__

Why: Restricting dashboard_url to http: and https: is a reasonable hardening step for an embedded iframe. However, the proposed new URL(url) can throw on malformed input and the suggestion does not actually address local/private URLs despite mentioning them.

Low

@nicomiguelino nicomiguelino marked this pull request as ready for review June 12, 2026 18:39
@github-actions

Copy link
Copy Markdown

Persistent review updated to latest commit cf11e1b

@nicomiguelino nicomiguelino deleted the feat/puzzel-app-2 branch June 12, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant