external resource loading, window.location, tab icon fix

This commit is contained in:
Face
2025-08-16 13:57:14 +03:00
parent 98b25820bb
commit ae8954c52c
22 changed files with 413 additions and 247 deletions

4
dns/Cargo.lock generated
View File

@@ -1560,9 +1560,9 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "macros-rs"
version = "1.2.1"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb8136cf4bdbfd10cdf683dab195f53892cb3b6433397ef48b211556b9c49dcb"
checksum = "9cfca1250b52a785fbe49de29612471f59592b6b659159dcfcb976af08c803b4"
dependencies = [
"termcolor",
]

View File

@@ -0,0 +1,10 @@
<head>
<title>Login</title>
<icon src="https://cdn-icons-png.flaticon.com/512/295/295128.png">
<meta name="theme-color" content="#1b1b1b">
<meta name="description" content="Login to your account">
</head>
<body>
<h1>todo</h1>
</body>

View File

@@ -38,56 +38,7 @@
#log-output { text-white p-4 rounded-md mt-4 font-mono max-h-40 }
</style>
<script>
local submitBtn = gurt.select('#submit')
local username_input = gurt.select('#username')
local password_input = gurt.select('#password')
local log_output = gurt.select('#log-output')
function addLog(message)
gurt.log(message)
log_output.text = log_output.text .. message .. '\\n'
end
submitBtn:on('submit', function(event)
local username = event.data.username
local password = event.data.password
local request_body = JSON.stringify({
username = username,
password = password
})
print(request_body)
local url = 'http://localhost:8080/auth/login'
local headers = {
['Content-Type'] = 'application/json'
}
addLog('Attempting to log in with username: ' .. username)
log_output.text = ''
local response = fetch(url, {
method = 'POST',
headers = headers,
body = request_body
})
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
if response:ok() then
addLog('Login successful!')
local jsonData = response:json()
if jsonData then
addLog('Logged in as user: ' .. jsonData.user.username)
addLog('Token: ' .. jsonData.token:sub(1, 20) .. '...')
end
else
addLog('Request failed with status: ' .. response.status)
local error_data = response:text()
addLog('Error response: ' .. error_data)
end
end)
</script>
<script src="script.lua" />
</head>
<body>

52
dns/frontend/script.lua Normal file
View File

@@ -0,0 +1,52 @@
local submitBtn = gurt.select('#submit')
local username_input = gurt.select('#username')
local password_input = gurt.select('#password')
local log_output = gurt.select('#log-output')
function addLog(message)
gurt.log(message)
log_output.text = log_output.text .. message .. '\\n'
end
print(gurt.location.href)
submitBtn:on('submit', function(event)
local username = event.data.username
local password = event.data.password
local request_body = JSON.stringify({
username = username,
password = password
})
print(request_body)
local url = 'http://localhost:8080/auth/login'
local headers = {
['Content-Type'] = 'application/json'
}
addLog('Attempting to log in with username: ' .. username)
log_output.text = ''
local response = fetch(url, {
method = 'POST',
headers = headers,
body = request_body
})
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
if response:ok() then
addLog('Login successful!')
local jsonData = response:json()
if jsonData then
addLog('Logged in as user: ' .. jsonData.user.username)
addLog('Token: ' .. jsonData.token:sub(1, 20) .. '...')
-- TODO: store as cookie
gurt.location.goto("/dashboard.html")
end
else
addLog('Request failed with status: ' .. response.status)
local error_data = response:text()
addLog('Error response: ' .. error_data)
end
end)

View File

View File

@@ -1,21 +1,38 @@
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
registrations_remaining INTEGER DEFAULT 3,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
domain_invite_codes INTEGER DEFAULT 3,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
CREATE TABLE IF NOT EXISTS invite_codes (
id SERIAL PRIMARY KEY,
code VARCHAR(32) UNIQUE NOT NULL,
created_by INTEGER REFERENCES users(id),
used_by INTEGER REFERENCES users(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
used_at TIMESTAMP
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
used_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_invite_codes_code ON invite_codes(code);
CREATE TABLE IF NOT EXISTS domain_invite_codes (
id SERIAL PRIMARY KEY,
code VARCHAR(32) UNIQUE NOT NULL,
created_by INTEGER REFERENCES users(id),
used_by INTEGER REFERENCES users(id),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
used_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_code ON domain_invite_codes(code);
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_created_by ON domain_invite_codes(created_by);
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_used_by ON domain_invite_codes(used_by);
CREATE TABLE IF NOT EXISTS domains (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
@@ -24,13 +41,24 @@ CREATE TABLE IF NOT EXISTS domains (
user_id INTEGER REFERENCES users(id),
status VARCHAR(20) DEFAULT 'pending',
denial_reason TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
UNIQUE(name, tld)
);
CREATE INDEX IF NOT EXISTS idx_domains_name_tld ON domains(name, tld);
CREATE INDEX IF NOT EXISTS idx_domains_user_id ON domains(user_id);
CREATE INDEX IF NOT EXISTS idx_domains_status ON domains(status);
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_invite_codes_code ON invite_codes(code);
CREATE TABLE IF NOT EXISTS dns_records (
id SERIAL PRIMARY KEY,
domain_id INTEGER NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
record_type VARCHAR(10) NOT NULL CHECK (record_type IN ('A', 'AAAA', 'CNAME', 'TXT', 'MX', 'NS', 'SRV')),
name VARCHAR(255) NOT NULL DEFAULT '@', -- @ for root, or subdomain name
value VARCHAR(1000) NOT NULL,
ttl INTEGER DEFAULT 3600,
priority INTEGER, -- For MX records
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_dns_records_domain_type ON dns_records(domain_id, record_type);
CREATE INDEX IF NOT EXISTS idx_dns_records_name ON dns_records(name);

View File

@@ -1,3 +0,0 @@
ALTER TABLE users DROP COLUMN IF EXISTS email;
DROP INDEX IF EXISTS idx_users_email;

View File

@@ -1,4 +0,0 @@
ALTER TABLE users ALTER COLUMN created_at TYPE TIMESTAMPTZ;
ALTER TABLE invite_codes ALTER COLUMN created_at TYPE TIMESTAMPTZ;
ALTER TABLE invite_codes ALTER COLUMN used_at TYPE TIMESTAMPTZ;
ALTER TABLE domains ALTER COLUMN created_at TYPE TIMESTAMPTZ;

View File

@@ -1,14 +0,0 @@
ALTER TABLE users ADD COLUMN domain_invite_codes INTEGER DEFAULT 3;
CREATE TABLE IF NOT EXISTS domain_invite_codes (
id SERIAL PRIMARY KEY,
code VARCHAR(32) UNIQUE NOT NULL,
created_by INTEGER REFERENCES users(id),
used_by INTEGER REFERENCES users(id),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
used_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_code ON domain_invite_codes(code);
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_created_by ON domain_invite_codes(created_by);
CREATE INDEX IF NOT EXISTS idx_domain_invite_codes_used_by ON domain_invite_codes(used_by);

View File

@@ -1,23 +0,0 @@
CREATE TABLE dns_records (
id SERIAL PRIMARY KEY,
domain_id INTEGER NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
record_type VARCHAR(10) NOT NULL CHECK (record_type IN ('A', 'AAAA', 'CNAME', 'TXT', 'MX', 'NS', 'SRV')),
name VARCHAR(255) NOT NULL DEFAULT '@', -- @ for root, or subdomain name
value VARCHAR(1000) NOT NULL,
ttl INTEGER DEFAULT 3600,
priority INTEGER, -- For MX records
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_dns_records_domain_type ON dns_records(domain_id, record_type);
CREATE INDEX idx_dns_records_name ON dns_records(name);
INSERT INTO dns_records (domain_id, record_type, name, value, ttl)
SELECT id, 'A', '@', ip, 3600
FROM domains
WHERE status = 'approved';
INSERT INTO dns_records (domain_id, record_type, name, value, ttl, priority)
SELECT id, 'SRV', '_gurt._tcp', '0 5 4878 @', 3600, 0
FROM domains
WHERE status = 'approved';

View File

@@ -1,6 +1,5 @@
use serenity::async_trait;
use serenity::all::*;
use serenity::prelude::*;
use sqlx::PgPool;
pub struct DiscordBot {

View File

@@ -6,9 +6,8 @@ mod routes;
use crate::{auth::jwt_middleware, config::Config, discord_bot};
use actix_governor::{Governor, GovernorConfigBuilder};
use actix_web::{http::Method, web, web::Data, App, HttpRequest, HttpServer};
use actix_web::{http::Method, web, web::Data, App, HttpServer};
use actix_web_httpauth::middleware::HttpAuthentication;
use anyhow::{anyhow, Error};
use colored::Colorize;
use macros_rs::fmt::{crashln, string};
use ratelimit::RealIpKeyExtractor;

View File

@@ -1,7 +1,6 @@
use super::helpers::deserialize_lowercase;
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, types::chrono::{DateTime, Utc}};
use chrono;
#[derive(Clone, Debug, Deserialize, Serialize, FromRow)]
pub struct Domain {

View File

@@ -242,6 +242,7 @@ pub(crate) async fn get_domain(path: web::Path<(String, String)>, app: Data<AppS
tld: domain.tld,
name: domain.name,
ip: domain.ip,
records: None,
}),
Ok(None) => HttpResponse::NotFound().finish(),
Err(_) => HttpResponse::InternalServerError().finish(),
@@ -378,6 +379,7 @@ pub(crate) async fn get_domains(query: web::Query<PaginationParams>, app: Data<A
tld: domain.tld,
name: domain.name,
ip: domain.ip,
records: None,
})
.collect();