Complete modernization of PowerShell module with security enhancements#7
Closed
dutch2005 wants to merge 93 commits intolazywinadmin:masterfrom
Closed
Complete modernization of PowerShell module with security enhancements#7dutch2005 wants to merge 93 commits intolazywinadmin:masterfrom
dutch2005 wants to merge 93 commits intolazywinadmin:masterfrom
Conversation
Implemented bilingual IT Adventures blog with dark tech design: - Added hero image asset - Created AboutSection with multilingual skills and stats - Implemented BlogSection, NewsletterSection, Navbar, Hero, Footer - Added LanguageContext for NL/EN translations - Integrated Tailwind design tokens and responsive components - Updated index.html and app structure to support the new pages X-Lovable-Edit-ID: edt-40cb6f45-e272-48bd-a0c8-f1503becccd5
Edited UI in Lovable
Set up Supabase backend and migrations for blog, messages, and auth; added admin UI, blog detail routing, and frontend DB-backed data fetching. Also implemented cloud-backed contact form, profile placeholder, and translations integration. X-Lovable-Edit-ID: edt-73c9fc5e-3bb8-4246-9b1d-3cf4797e3abc
Edited UI in Lovable
Implemented a rich Markdown editor for blog content: - Added MarkdownEditor component with toolbar (Bold, Italic, Headings, Code, Lists, Links, HR) and live preview rendering. - Wired MarkdownEditor into Admin.tsx for NL/EN content fields. - Replaced NL/EN content textareas with MarkdownEditor instances. - Fixed NewsletterSection section id to newsletter and updated related usage. - Updated BlogPost rendering to better handle MD-to-HTML conversion (internal rendering already present). Also granted admin access and adjusted About/CV integration scaffolding remains (no direct CV/photo changes in this commit). X-Lovable-Edit-ID: edt-908ef291-0258-4d39-8c4d-68c8021e040d
Edited UI in Lovable
Migrate emails to obfuscated dutch2005@xtremeweb.xyz, update LinkedIn URL, adjust certifications to only include Microsoft 365 Certified and 3CX V20, and adapt sign-in placeholder. Also tweak UI for email obfuscation and tighten certifications grid layout. X-Lovable-Edit-ID: edt-d792fa60-c724-479a-bdc8-f94d34ea1be9
Migrate to a new external Supabase client by adding a dedicated client module using VITE_EXTERNAL_SUPABASE_URL and VITE_EXTERNAL_SUPABASE_ANON_KEY, and replace all imports of the old auto-generated client with the new db client. Added centralized db client and updated components/pages to use it. X-Lovable-Edit-ID: edt-d15dd87d-4892-4f0f-8208-2a7b30d6e14f
- Navbar: replace <a href="#..."> with React Router <Link to="/#..."> so nav works from /blog/:slug pages - Navbar: swap Terminal icon for /logo.svg img - BlogPost: add linkify() helper — auto-links bare URLs and markdown [text](url) in post content - index.html: add GA4 tag (G-0E07DMNCSG), update favicon to logo.svg - index.html: add commented Skimlinks monetization script (ready to activate) - public/logo.svg: new MM logo (dark bg, cyan border/text) for favicon + navbar Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- index.html: implement Google Consent Mode v2 defaults before gtag.js loads
- all signals denied by default (ad_storage, analytics_storage,
ad_user_data, ad_personalization)
- wait_for_update: 500ms on first visit so React banner can fire update
- restores previously stored consent from localStorage on repeat visits
- CookieConsent.tsx: bilingual (NL/EN) GDPR banner fixed at bottom
- "Alles accepteren" → grants all 4 consent signals + saves to localStorage
- "Alleen functioneel" / X → denies all signals + saves to localStorage
- expandable "Meer info" section explaining what each cookie type does
- matches site dark theme with cyan primary accent
- App.tsx: mount <CookieConsent /> inside LanguageProvider so NL/EN works
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Navbar: replace <Link to="/#..."> with scrollToSection() click handler
- If already on /: calls scrollIntoView() or scrollTo(top) directly
- If on /blog/:slug or any other page: navigate('/', { state: { scrollTo } })
- Converted nav items and logo to <button> elements
- Index.tsx: add useEffect on location.key to consume state.scrollTo and
scroll to the right section after arriving from another page
- BlogSection, AboutSection, ContactSection: add scroll-mt-16 so the 64px
fixed navbar doesn't overlap the section heading on scroll target
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
React/deps:
- react + react-dom: 18.3 → 19.2.4
- @types/react + @types/react-dom: 18.x → 19.2.x
- @types/node: 22.x → 24.x
- react-day-picker: 8.10 → 9.13.2 (v9 API)
- Add engines: { node: ">=24.0.0", npm: ">=10.0.0" }
calendar.tsx: rewrite for react-day-picker v9 API
- Rename classNames keys (caption→month_caption, nav_button_*→button_*,
head_row→weekdays, head_cell→weekday, row→week, cell→day, day→day_button,
day_*→* for selected/today/outside/disabled/range_*)
- Replace IconLeft/IconRight components with single Chevron component
README: full rewrite with tech stack table, versions, project structure,
setup instructions, deployment notes and React 19 compat notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Edited UI in Lovable
Refactored admin into a sidebar-driven dashboard with multiple panels: - Added AdminSidebar with navigation and logout - Implemented Dashboard, BlogPosts, Messages, Subscribers, SocialShare, Security, and Settings panels - Replaced Admin.tsx with sidebar-based routing and authentication guard - Introduced admin_audit_log table and related policies - Updated components to use new external Supabase client and expanded admin features (export, social sharing, security, activity logs) X-Lovable-Edit-ID: edt-a4db129b-9f58-42e9-9635-0b07b3bfbbfc
Edited UI in Lovable
Add ReadingProgress and RelatedPosts integration; implement SEOHead usage, TableOfContents, and open-graph JSON-LD scaffolding across BlogPost. Update App.tsx to use HelmetProvider; refine BlogPost to include TOC, headings, and improved navigation. X-Lovable-Edit-ID: edt-b635e78a-e7a6-4593-bed1-1f7cf6ff6c9c
Add DELETE policies for contact_messages and newsletter_subscribers, add email format constraints, replace 404 console log, and update NewsletterSection to use Zod-based email validation. X-Lovable-Edit-ID: edt-2ea8cf92-c753-4829-9678-091ce7db965f
Edited UI in Lovable
* 🧹 [Code Health] Unify Supabase client usage Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> * 🧹 [Code Health] Unify Supabase client usage Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com>
🎯 What: The vulnerability fixed A Stored Cross-Site Scripting (XSS) vulnerability existed in src/pages/BlogPost.tsx where user-supplied content (through the linkify function) was being rendered directly via dangerouslySetInnerHTML without proper sanitization.⚠️ Risk: The potential impact if left unfixed Malicious actors could inject arbitrary JavaScript into blog posts or list items. When a user views the compromised post, the script would execute in their browser context. This could lead to session hijacking, unauthorized actions on behalf of the user, or sensitive data theft. The blast radius could be high since any visitor reading the infected blog post would be affected. 🛡️ Solution: How the fix addresses the vulnerability The output of linkify(para) and linkify(item.slice(2)) is now passed through DOMPurify.sanitize() before being injected using dangerouslySetInnerHTML. DOMPurify safely strips out any malicious script tags and event handlers while preserving safe HTML, ensuring that the content is rendered securely. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com>
💡 **What:** Memoize the creation and stringification of the \`structuredData\` object using \`useMemo\`. 🎯 **Why:** Previously, the \`structuredData\` object was allocated and \`JSON.stringify\` was called on every render of the \`SEOHead\` component. While \`JSON.stringify\` on a small object is relatively fast, doing so on every render introduces unnecessary CPU overhead and generates garbage that needs to be collected. 📊 **Measured Improvement:** In a 1,000,000 iteration synthetic benchmark, allocating and stringifying the object repeatedly took ~1075ms. Memoizing the pre-stringified value took ~3ms for the same number of accesses. This eliminates redundant operations on each component render, making the component functionally lighter. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com>
* feat: implement remaining TODOs for mikemaze.nl Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> * fix: resolve review feedback Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> * fix: correctly capture insertedData Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> * chore: acknowledge PR comments Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com>
* 🧪 Add tests for cn utility function Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> * 🧪 Add tests for cn utility function Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> * 🧪 Add tests for cn utility function Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> * chore: remove bun.lockb from tracking (project uses npm) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add error test for useLanguage hook Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> * Fix PR comments - merge conflicts Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: dutch2005 <3473864+dutch2005@users.noreply.github.com>
supabaseClient.ts exports 'db', not 'supabase'. Use alias import. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Convert Admin, AdminLogin, Unsubscribe to React.lazy() + Suspense - Main bundle: 932KB -> 473KB gzip (289KB -> 148KB) - Admin chunk loads only when visiting /admin - Update docs/todo.md with full completed/pending state Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…qyzfbpui) Both Supabase clients now consistently prefer VITE_EXTERNAL_SUPABASE_URL so all code targets the active Mike Maze IT Adventures project. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Live table was missing unsubscribe_token (created before this column was added to the schema). Applied via Management API and committed migration for future reference. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Duolingo-style re-engagement at 1w/1m/3m/6m/1y with escalating personal tone. Pixel + URL token tracking, pg_cron daily trigger, single send-reminders edge function. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8 tasks: schema migration, track-open/track-visit/send-reminders edge functions, frontend beacon, subscribe update, pg_cron schedule. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents: deployment status, re-engagement system design, PR #21 two blockers (pg_cron placeholder, BlogPost.tsx missing hook). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ders, pg_cron) Implements Duolingo-style re-engagement emails at 1w/1m/3m/6m/1y intervals with pixel + URL token tracking and GDPR-aware consent handling.
Supabase auto-injects SUPABASE_SERVICE_ROLE_KEY in a different format than the legacy JWT stored locally. Switch to a dedicated CRON_SECRET env var for pg_cron authentication, which is simpler and more explicit. Deploy: npx supabase secrets set CRON_SECRET=<value> pg_cron job updated to use Bearer <CRON_SECRET> in Authorization header. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All re-engagement tasks done. Two manual items remain: publish content drafts and verify OG image live. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Upload og-image.jpg to public Supabase Storage bucket (site-assets) - Add SEOHead to Index.tsx with the stable Storage CDN URL - Avoids Lovable deployment 404 for /og-image.jpg Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s' to 'Parameters'
…, and full Pester v5 test suite Core module changes: - Bump module version to 1.1.0 and raise PowerShellVersion to 7.4; remove ThreadJob from RequiredModules (inbox in PS 7.4+) to fix Import-Module failure on PS 7.6 - ApplicationState: add CimSessions synchronized cache, CloudConnected flag, EvictCimSession method, and proper RunspacePool.Close() in Dispose() - Start-LazyWinAdmin: remove -RunspacePool from Start-ThreadJob (PS 7 inbox stub lacks the param); wrap job dispatch in try/catch to prevent ShowDialog crash on job-start failure; add RequireCloudSession and RequireComputerName pre-flight guards so unavailable features show a friendly status message instead of crashing - Private functions: fix .NET 7+ RegexParseException caused by backslash-underscore in character classes (Get-EntraIdentity, Get-IntuneDevice, Get-ComputerADInfo); replace Win32_Product with StdRegProv registry enumeration in Get-ComputerSoftware; split RDP registry and firewall steps in Set-ComputerRDP; migrate Azure queries to Search-AzGraph Test suite (Pester v5, 176 tests, 0 failures): - Integrity.Tests.ps1: file structure, module manifest, XAML named-control validation, ApplicationState class lifecycle - Functions.Tests.ps1: all 16 private functions covered; WinRM probe at script top-level for discovery-phase -Skip; fake CimInstance::new pattern to satisfy Invoke-CimMethod proxy type constraint without real WMI access; AD command stubs for RSAT-free machines - Run-Tests.ps1: runner with Pester auto-install, -Suite and -Output params, summary table Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-feature access hints - XAML: add lblAdminStatus + btnRestartAdmin to status bar; add tooltips to hardware, RDP, and registry write/delete buttons explaining which operations need admin rights - Start-LazyWinAdmin: detect elevation at startup via WindowsPrincipal.IsInRole; show green 'Administrator' or amber '(!) Standard User' label in status bar; hide Restart button when already elevated; wire button to relaunch pwsh elevated via Start-Process -Verb RunAs then close the current window - Add $AdminHint helper: when a hardware/RDP/registry operation returns null or an error AND the process is not elevated AND the target is the local machine, append a clear message pointing the user to 'Restart as Admin' instead of silently showing empty results - Integrity.Tests.ps1: add lblAdminStatus and btnRestartAdmin to XAML control coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- .claude/launch.json: dev launch configurations for the GUI and Pester test runner (pwsh-based; no web server port since this is a WPF app) - lazywinadmin.speq: project specification/contract file - Remove .lovable/plan.md — project is no longer hosted on Lovable.dev Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
$AppendOutput and $SetBusy now use Dispatcher.CheckAccess() to execute directly when already on the UI thread, avoiding re-entrant DispatcherFrame pushes. The Register-ObjectEvent action now uses Dispatcher.InvokeAsync so the event thread is non-blocking and OnCompleted callbacks never nest inside a synchronous Invoke call. The try/catch in Invoke-AsyncAction also drops an unnecessary Dispatcher.Invoke since it runs on the UI thread directly. Also adds CLAUDE.md with project conventions and updates README.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LazyWinAdmin GUI - Modernized (2026 Standard)
LazyWinAdmin is a comprehensive PowerShell-based management tool for Windows administrators. Originally released in 2012, this project has been completely modernized to 2026 standards, transforming from a monolithic WinForms script into a modular, thread-safe, and high-performance application.
🚀 2026 Modernization Highlights
The project has undergone a complete architectural overhaul to meet modern enterprise standards:
LazyWinAdminModule).Get-WmiObjectcalls to the modern, faster, and more secureGet-CimInstance(WinRM/WSMan).🛠️ Requirements
📁 Project Structure
LazyWinAdminModule/: The core PowerShell module.Public/: User-facing functions (e.g.,Start-LazyWinAdmin).Private/: Internal helper functions and modernized business logic.UI/: WPF/XAML definitions for the modern interface.Tests/: Pester unit tests.Media/: Original and updated project assets.docs/: Modernization plans and migration guides.🔧 Getting Started
To launch the modernized GUI:
✨ Key Features
📜 Contributions
Contributions are welcome! Please ensure all new logic includes Pester tests and adheres to the modular module structure.
Modernized by the LazyWinAdmin Community.