Remove salt

This commit is contained in:
Shreerang Kale 2025-07-21 11:37:52 +05:30
parent 75989d9f34
commit e57c4b24ad
3 changed files with 29 additions and 35 deletions

View File

@ -224,17 +224,9 @@ export async function POST(request: NextRequest) {
// Sanitize the app name to ensure it's DNS-compatible (only alphanumeric and dashes) // Sanitize the app name to ensure it's DNS-compatible (only alphanumeric and dashes)
const sanitizedAppName = appName.replace(/[^a-zA-Z0-9-]/g, '-').toLowerCase(); const sanitizedAppName = appName.replace(/[^a-zA-Z0-9-]/g, '-').toLowerCase();
// Generate a random salt (6 alphanumeric characters) to prevent name collisions // Create DNS name in format: app_name-shortcommithash
const generateSalt = (): string => { const dnsName = `${sanitizedAppName}-${shortHash}`;
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; console.log(`DNS name: ${dnsName} (sanitized from: ${appName})`);
return Array.from({ length: 6 }, () => chars.charAt(Math.floor(Math.random() * chars.length))).join('');
};
const salt = generateSalt();
console.log(`Generated salt: ${salt}`);
// Create DNS name in format: app_name-shortcommithash-salt
const dnsName = `${sanitizedAppName}-${shortHash}-${salt}`;
console.log(`DNS name with salt: ${dnsName} (sanitized from: ${appName})`);
// Ensure the DNS name doesn't have consecutive dashes or start/end with a dash // Ensure the DNS name doesn't have consecutive dashes or start/end with a dash
let cleanDnsName = dnsName let cleanDnsName = dnsName
@ -243,10 +235,9 @@ export async function POST(request: NextRequest) {
// Ensure DNS name is valid (63 chars max per label, all lowercase, starts with a letter) // Ensure DNS name is valid (63 chars max per label, all lowercase, starts with a letter)
if (cleanDnsName.length > 63) { if (cleanDnsName.length > 63) {
// If too long, truncate but preserve both the commit hash and salt parts // If too long, truncate but preserve both the commit hash
const suffixPart = `-${shortHash}-${salt}`; const maxAppNameLength = 63 - shortHash.length;
const maxAppNameLength = 63 - suffixPart.length; cleanDnsName = sanitizedAppName.substring(0, maxAppNameLength) + shortHash;
cleanDnsName = sanitizedAppName.substring(0, maxAppNameLength) + suffixPart;
} }
// If the DNS name ended up empty (unlikely) or doesn't start with a letter (possible), // If the DNS name ended up empty (unlikely) or doesn't start with a letter (possible),
@ -255,7 +246,7 @@ export async function POST(request: NextRequest) {
cleanDnsName = `app-${cleanDnsName}`; cleanDnsName = `app-${cleanDnsName}`;
} }
console.log(`Final DNS name with salt: ${cleanDnsName}`); console.log(`Final DNS name: ${cleanDnsName}`);
// Set up Registry config // Set up Registry config
const config = getRegistryConfig() const config = getRegistryConfig()
@ -273,9 +264,8 @@ export async function POST(request: NextRequest) {
const registry = getRegistry() const registry = getRegistry()
// Create LRN for the application with commit hash and salt // Create LRN for the application with commit hash
// We already have the salt from earlier, so we use it directly const lrn = `lrn://${config.authority}/applications/${appName}-${shortHash}`;
const lrn = `lrn://${config.authority}/applications/${appName}-${shortHash}-${salt}`;
// Get current timestamp for the meta note // Get current timestamp for the meta note
const timestamp = new Date().toUTCString(); const timestamp = new Date().toUTCString();
@ -284,7 +274,7 @@ export async function POST(request: NextRequest) {
console.log('Step 1: Publishing ApplicationRecord...'); console.log('Step 1: Publishing ApplicationRecord...');
const applicationRecord = { const applicationRecord = {
type: 'ApplicationRecord', type: 'ApplicationRecord',
name: `${appName}-${shortHash}-${salt}`, // Include commit hash and salt in the record name name: `${appName}-${shortHash}`, // Include commit hash in the record name
version: '1.0.0', version: '1.0.0',
app_type: 'webapp', app_type: 'webapp',
repository: [repoUrl], repository: [repoUrl],
@ -365,8 +355,8 @@ export async function POST(request: NextRequest) {
const deploymentRequestData = { const deploymentRequestData = {
type: 'ApplicationDeploymentRequest', type: 'ApplicationDeploymentRequest',
version: '1.0.0', version: '1.0.0',
name: `${appName}-${shortHash}-${salt}`, // Update name to match application record name: `${appName}-${shortHash}`, // Update name to match application record
application: lrn, // LRN already includes commit hash and salt application: lrn, // LRN already includes commit hash
deployer: deployerLrn, deployer: deployerLrn,
dns: cleanDnsName, dns: cleanDnsName,
config: { config: {

View File

@ -28,7 +28,7 @@ export default function StatusDisplay({
error, error,
}: StatusDisplayProps) { }: StatusDisplayProps) {
// Get domain suffix from environment variable // Get domain suffix from environment variable
const domainSuffix = process.env.NEXT_PUBLIC_DOMAIN_SUFFIX || ''; const domainSuffix = process.env.NEXT_PUBLIC_DOMAIN_SUFFIX;
if (status === 'idle') return null; if (status === 'idle') return null;
const StatusBadge = ({ type }: { type: 'creating' | 'success' | 'error' }) => { const StatusBadge = ({ type }: { type: 'creating' | 'success' | 'error' }) => {
@ -129,7 +129,11 @@ export default function StatusDisplay({
{appRecordId && <InfoItem label="Laconic Application Record ID" value={appRecordId} />} {appRecordId && <InfoItem label="Laconic Application Record ID" value={appRecordId} />}
{recordId && <InfoItem label="Laconic Deployment Request Record ID" value={recordId} />} {recordId && <InfoItem label="Laconic Deployment Request Record ID" value={recordId} />}
{lrn && <InfoItem label="Laconic Resource Name (LRN)" value={lrn} />} {lrn && <InfoItem label="Laconic Resource Name (LRN)" value={lrn} />}
{dns && <InfoItem label="Deployment URL (ready in 2-3 minutes)" value={domainSuffix ? `https://${dns}${domainSuffix}` : `http://${dns}`} />} {dns && (
domainSuffix
? <InfoItem label="Deployment URL (ready in 2-3 minutes)" value={`https://${dns}${domainSuffix}`} />
: <InfoItem label="Please set domain suffix" value="" />
)}
</div> </div>
)} )}

View File

@ -15,37 +15,37 @@ export default function URLForm({ onSubmit, disabled }: URLFormProps) {
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
// Trim the URL to remove any whitespace // Trim the URL to remove any whitespace
const trimmedUrl = url.trim(); const trimmedUrl = url.trim();
if (!trimmedUrl) { if (!trimmedUrl) {
setError('Please enter a URL'); setError('Please enter a URL');
return; return;
} }
// Validate URL format // Validate URL format
try { try {
const parsedUrl = new URL(trimmedUrl); const parsedUrl = new URL(trimmedUrl);
// Check for protocol // Check for protocol
if (!parsedUrl.protocol.startsWith('http')) { if (!parsedUrl.protocol.startsWith('http')) {
setError('URL must use HTTP or HTTPS protocol'); setError('URL must use HTTP or HTTPS protocol');
return; return;
} }
// Check for hostname // Check for hostname
if (!parsedUrl.hostname || parsedUrl.hostname.length < 3) { if (!parsedUrl.hostname || parsedUrl.hostname.length < 3) {
setError('URL must contain a valid hostname'); setError('URL must contain a valid hostname');
return; return;
} }
// Basic sanity check for common invalid URLs // Basic sanity check for common invalid URLs
if (parsedUrl.href === 'http://localhost' || parsedUrl.href === 'https://localhost') { if (parsedUrl.href === 'http://localhost' || parsedUrl.href === 'https://localhost') {
setError('Please enter a valid public URL, not localhost'); setError('Please enter a valid public URL, not localhost');
return; return;
} }
// All validations passed // All validations passed
setError(''); setError('');
onSubmit(trimmedUrl); onSubmit(trimmedUrl);
@ -68,7 +68,7 @@ export default function URLForm({ onSubmit, disabled }: URLFormProps) {
onChange={(e) => setUrl(e.target.value)} onChange={(e) => setUrl(e.target.value)}
placeholder={exampleUrl} placeholder={exampleUrl}
className="w-full p-3 rounded-md transition-colors" className="w-full p-3 rounded-md transition-colors"
style={{ style={{
background: 'var(--card-bg)', background: 'var(--card-bg)',
border: '1px solid var(--input-border)', border: '1px solid var(--input-border)',
color: 'var(--foreground)', color: 'var(--foreground)',
@ -91,12 +91,12 @@ export default function URLForm({ onSubmit, disabled }: URLFormProps) {
</p> </p>
)} )}
</div> </div>
<button <button
type="submit" type="submit"
disabled={disabled || !url} disabled={disabled || !url}
className="w-full px-6 py-3 rounded-md transition-colors" className="w-full px-6 py-3 rounded-md transition-colors"
style={{ style={{
backgroundColor: (disabled || !url) ? 'var(--muted)' : 'var(--primary)', backgroundColor: (disabled || !url) ? 'var(--muted)' : 'var(--primary)',
color: 'var(--primary-foreground)', color: 'var(--primary-foreground)',
opacity: (disabled || !url) ? '0.7' : '1', opacity: (disabled || !url) ? '0.7' : '1',
@ -106,4 +106,4 @@ export default function URLForm({ onSubmit, disabled }: URLFormProps) {
</button> </button>
</form> </form>
); );
} }