From 99f17dc42cae8a93d076de224eed5e1047aec861 Mon Sep 17 00:00:00 2001 From: Face <69168154+face-hh@users.noreply.github.com> Date: Tue, 19 Aug 2025 18:27:25 +0300 Subject: [PATCH] user domains API, .value on input, fix flex sizing --- README.md | 1 - dns/README.md | 54 ++++- dns/frontend/dashboard.html | 52 +---- dns/frontend/dashboard.lua | 197 ++--------------- dns/frontend/index.html | 1 + dns/frontend/register.html | 136 ++++++++++++ dns/frontend/register.lua | 257 +++++++++++++++++++++++ dns/src/gurt_server.rs | 3 + dns/src/gurt_server/models.rs | 16 ++ dns/src/gurt_server/routes.rs | 52 ++++- flumi/Scenes/Tags/input.tscn | 46 +--- flumi/Scripts/AutoSizingFlexContainer.gd | 2 +- flumi/Scripts/B9/HTMLParser.gd | 2 +- flumi/Scripts/B9/Lua.gd | 10 +- flumi/Scripts/StyleManager.gd | 59 ++---- flumi/Scripts/Utils/FlexUtils.gd | 3 +- flumi/Scripts/Utils/Lua/DOM.gd | 119 ++++++++++- flumi/Scripts/main.gd | 51 +++-- 18 files changed, 705 insertions(+), 356 deletions(-) create mode 100644 dns/frontend/register.html create mode 100644 dns/frontend/register.lua diff --git a/README.md b/README.md index 2826b27..eb9a709 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ Issues: 3. Certain properties like `scale` and `rotate` don't apply to the `active` pseudo-class because they rely on mouse_enter and mouse_exit events 4. `
Box
` something like this has the "Box" text (presumably the PanelContainer) as the target of the hover, not the div itself (which has the w/h size) 5. font in button doesn't comply with CSS, its the projects default -6. Flex containers, ironically enough, make the page unresponsive. This happens because of our custom `AutoSizingFlexContainer.gd` script, which aims to set a Godot UI size to the flex containers based on their content. However, they don't get resized when the window is resized, leading to unresponsiveness. The fact that we're setting the `custom_minimum_size` is not the root cause, but rather the fact that the script doesn't update the size when the window is resized - or, more likely, I just don't understand how flexbox works. Notes: - **< input />** is sort-of inline in normal web. We render it as a block element (new-line). diff --git a/dns/README.md b/dns/README.md index b52773d..eb9494e 100644 --- a/dns/README.md +++ b/dns/README.md @@ -19,6 +19,7 @@ This is a Domain Management API built with Rust (Actix Web) and PostgreSQL. It p - [GET /auth/me](#get-authme) - [POST /auth/invite](#post-authinvite) - [POST /auth/redeem-invite](#post-authredeem-invite) + - [GET /auth/domains](#get-authdomains) 🔒 - [Domain Endpoints](#domain-endpoints) - [GET /](#get-) - [POST /domain](#post-domain) 🔒 @@ -127,6 +128,50 @@ Redeem an invite code to get 3 additional domain registrations. Requires authent } ``` +### GET /auth/domains 🔒 + +Get all domains owned by the authenticated user, including their status. Requires `Authorization: Bearer ` header. + +**Query Parameters:** +- `page` - Page number (default: 1) +- `limit` - Items per page (default: 100, max: 1000) + +**Response:** +```json +{ + "domains": [ + { + "name": "myawesome", + "tld": "dev", + "ip": "192.168.1.100", + "status": "approved", + "denial_reason": null + }, + { + "name": "pending", + "tld": "fr", + "ip": "10.0.0.1", + "status": "pending", + "denial_reason": null + }, + { + "name": "rejected", + "tld": "mf", + "ip": "172.16.0.1", + "status": "denied", + "denial_reason": "Invalid IP address" + } + ], + "page": 1, + "limit": 100 +} +``` + +**Status Values:** +- `pending` - Domain is awaiting approval +- `approved` - Domain has been approved and is active +- `denied` - Domain was rejected (see `denial_reason` for details) + ## Domain Endpoints ### GET / @@ -159,15 +204,6 @@ Submit a domain for approval. Requires authentication and consumes one registrat } ``` -**Response:** -```json -{ - "message": "Domain registration submitted for approval", - "domain": "myawesome.dev", - "status": "pending" -} -``` - **Error Responses:** - `401 Unauthorized` - Missing or invalid JWT token - `400 Bad Request` - No registrations remaining, invalid domain, or offensive name diff --git a/dns/frontend/dashboard.html b/dns/frontend/dashboard.html index 4e683c1..a1b31a4 100644 --- a/dns/frontend/dashboard.html +++ b/dns/frontend/dashboard.html @@ -26,15 +26,15 @@ } .primary-btn { - p-3 rounded-lg font-medium cursor-pointer transition-colors bg-[#dc2626] text-white + p-3 rounded-lg font-medium cursor-pointer transition-colors bg-[#dc2626] text-white w-32 h-12 } .success-btn { - p-3 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white + p-3 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white w-32 h-12 } .danger-btn { - p-3 rounded-lg font-medium cursor-pointer transition-colors bg-[#b91c1c] text-white + p-3 rounded-lg font-medium cursor-pointer transition-colors bg-[#b91c1c] text-white w-32 h-12 } .secondary-btn { @@ -42,7 +42,7 @@ } .warning-btn { - p-3 rounded-lg font-medium cursor-pointer transition-colors bg-[#dc2626] text-white + p-3 rounded-lg font-medium cursor-pointer transition-colors bg-[#dc2626] text-white w-32 h-12 } .form-group { @@ -58,7 +58,7 @@ } .stats-card { - bg-[#1f1f1f] p-4 rounded-lg border border-[#dc2626] + p-4 rounded-lg border border-[#dc2626] } .domain-item { @@ -98,48 +98,10 @@

Loading...

- -
-
- -
-

Register New Domain

-
-

Domain Name:

- -
-
-

Select TLD:

-
-

Loading TLDs...

-
-
-
-

IP Address:

- -
-
- -
- -
-

Invite System

-

Create invite codes to share with friends, or redeem codes to get more domain - registrations.

- -

Placeholder

- -
-

Create Invite

- -
-
-

Redeem Invite

- - + +
-
diff --git a/dns/frontend/dashboard.lua b/dns/frontend/dashboard.lua index 41f0931..92734ea 100644 --- a/dns/frontend/dashboard.lua +++ b/dns/frontend/dashboard.lua @@ -1,16 +1,12 @@ local user = nil local domains = {} -local tlds = {} local authToken = nil local userInfo = gurt.select('#user-info') local domainsList = gurt.select('#domains-list') -local tldSelector = gurt.select('#tld-selector') local loadingElement = gurt.select('#tld-loading') -local displayElement = gurt.select('#invite-code-display') -local options -displayElement:hide() +local options local function showError(elementId, message) local element = gurt.select('#' .. elementId) @@ -29,57 +25,17 @@ local function updateUserInfo() userInfo.text = 'Welcome, ' .. user.username .. '!' end -local function renderTLDSelector() - loadingElement:remove() - - tldSelector.text = '' - local i = 1 - local total = #tlds - local intervalId - - intervalId = gurt.setInterval(function() - if i > total then - gurt.clearInterval(intervalId) - return - end - - local tld = tlds[i] - local option = gurt.create('button', { - text = '.' .. tld, - style = 'tld-option', - ['data-tld'] = tld - }) - - tldSelector:append(option) - - option:on('click', function() - -- Clear previous selection - if not options then - options = gurt.selectAll('.tld-option') - end - - for j = 1, #options do - if options[j].classList:contains('tld-selected') then - options[j].classList:remove('tld-selected') - end - end - - -- Select this option - option.classList:add('tld-selected') - end) - i = i + 1 - end, 16) -end - local function renderDomains() local loadingElement = gurt.select('#domains-loading') - loadingElement:remove() + if loadingElement then + loadingElement:remove() + end domainsList.text = '' if #domains == 0 then local emptyMessage = gurt.create('div', { - text = 'No domains registered yet. Submit your first domain below!', + text = 'No domains registered yet. Click "New" to register your first domain!', style = 'text-center text-[#6b7280] py-8' }) domainsList:append(emptyMessage) @@ -91,7 +47,7 @@ local function renderDomains() style = 'domain-item' }) - local domainInfo = gurt.create('div', {}) + local domainInfo = gurt.create('div', { style = 'w-full' }) local domainName = gurt.create('div', { text = domain.name .. '.' .. domain.tld, @@ -103,8 +59,14 @@ local function renderDomains() style = 'text-[#6b7280]' }) + local domainStatus = gurt.create('div', { + text = 'Status: ' .. (domain.status or 'Unknown'), + style = 'text-[#6b7280]' + }) + domainInfo:append(domainName) domainInfo:append(domainIP) + domainInfo:append(domainStatus) local actions = gurt.create('div', { style = 'flex gap-2' @@ -143,7 +105,7 @@ end local function loadDomains() print('Loading domains...') - local response = fetch('gurt://localhost:8877/domains?page=1&size=100', { + local response = fetch('gurt://localhost:8877/auth/domains?page=1&size=100', { headers = { Authorization = 'Bearer ' .. authToken } @@ -159,19 +121,6 @@ local function loadDomains() end end -local function loadTLDs() - print('Loading available TLDs...') - local response = fetch('gurt://localhost:8877/tlds') - - if response:ok() then - tlds = response:json() - print('Loaded ' .. #tlds .. ' TLDs') - renderTLDSelector() - else - print('Failed to load TLDs: ' .. response:text()) - end -end - local function checkAuth() authToken = gurt.crumbs.get("auth_token") @@ -188,7 +137,6 @@ local function checkAuth() print('Authentication successful for user: ' .. user.username) updateUserInfo() loadDomains() - loadTLDs() else print('Token invalid, redirecting to login...') gurt.crumbs.delete('auth_token') @@ -206,126 +154,13 @@ local function logout() gurt.location.goto("../") end -local function submitDomain(name, tld, ip) - hideError('domain-error') - print('Submitting domain: ' .. name .. '.' .. tld) - - local response = fetch('gurt://localhost:8877/domain', { - method = 'POST', - headers = { - ['Content-Type'] = 'application/json', - Authorization = 'Bearer ' .. authToken - }, - body = JSON.stringify({ name = name, tld = tld, ip = ip }) - }) - - if response:ok() then - local data = response:json() - print('Domain submitted successfully: ' .. data.domain) - - -- Update user registrations remaining - user.registrations_remaining = user.registrations_remaining - 1 - updateUserInfo() - - -- Clear form - gurt.select('#domain-name').text = '' - gurt.select('#domain-ip').text = '' - - -- Refresh domains list - loadDomains() - else - local error = response:text() - showError('domain-error', 'Domain submission failed: ' .. error) - print('Domain submission failed: ' .. error) - end -end - -local function createInvite() - print('Creating invite code...') - local response = fetch('gurt://localhost:8877/auth/invite', { - method = 'POST', - headers = { - Authorization = 'Bearer ' .. authToken - } - }) - - if response:ok() then - local data = response:json() - local inviteCode = data.invite_code - displayElement.text = 'Invite code: ' .. inviteCode .. ' (copied to clipboard)' - displayElement:show() - Clipboard.write(inviteCode) - print('Invite code created and copied to clipboard: ' .. inviteCode) - else - print('Failed to create invite: ' .. response:text()) - end -end - -local function redeemInvite(code) - hideError('redeem-error') - print('Redeeming invite code: ' .. code) - - local response = fetch('gurt://localhost:8877/auth/redeem-invite', { - method = 'POST', - headers = { - ['Content-Type'] = 'application/json', - Authorization = 'Bearer ' .. authToken - }, - body = JSON.stringify({ invite_code = code }) - }) - - if response:ok() then - local data = response:json() - print('Invite redeemed: +' .. data.registrations_added .. ' registrations') - - -- Update user info - user.registrations_remaining = user.registrations_remaining + data.registrations_added - updateUserInfo() - - -- Clear form - gurt.select('#invite-code-input').text = '' - else - local error = response:text() - showError('redeem-error', 'Failed to redeem invite: ' .. error) - print('Failed to redeem invite: ' .. error) - end +local function goToRegister() + gurt.location.goto("/register.html") end -- Event handlers gurt.select('#logout-btn'):on('click', logout) - -gurt.select('#submit-domain-btn'):on('click', function() - local name = gurt.select('#domain-name').text - local ip = gurt.select('#domain-ip').text - local selectedTLD = gurt.select('.tld-selected') - - if not name or name == '' then - showError('domain-error', 'Domain name is required') - return - end - - if not ip or ip == '' then - showError('domain-error', 'IP address is required') - return - end - - if not selectedTLD then - showError('domain-error', 'Please select a TLD') - return - end - - local tld = selectedTLD:getAttribute('data-tld') - submitDomain(name, tld, ip) -end) - -gurt.select('#create-invite-btn'):on('click', createInvite) - -gurt.select('#redeem-invite-btn'):on('click', function() - local code = gurt.select('#invite-code-input').text - if code and code ~= '' then - redeemInvite(code) - end -end) +gurt.select('#new-btn'):on('click', goToRegister) -- Initialize print('Dashboard initialized') diff --git a/dns/frontend/index.html b/dns/frontend/index.html index a323f49..161e15e 100644 --- a/dns/frontend/index.html +++ b/dns/frontend/index.html @@ -38,6 +38,7 @@ #log-output { text-white p-4 rounded-md mt-4 font-mono max-h-40 } +