Skip to content

Commit

Permalink
Merge pull request #345 from stakwork/feat/validate-vanity-address
Browse files Browse the repository at this point in the history
Feat/validate vanity address
  • Loading branch information
Evanfeenstra authored Oct 11, 2024
2 parents 5341bb8 + 39c13a7 commit 6cd3e4a
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 19 deletions.
14 changes: 9 additions & 5 deletions app/src/api/cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,17 @@ export const userKey = "SPHINX_TOKEN";

export async function send_cmd(type: CmdType, data: CmdData, tag?: string) {
const txt = JSON.stringify({ type, data });
const encodedTxt = encodeURIComponent(txt);
let ret = "";
try {
const r = await fetch(`${root}/cmd?txt=${txt}&tag=${tag || "SWARM"}`, {
headers: {
"x-jwt": localStorage.getItem(userKey),
},
});
const r = await fetch(
`${root}/cmd?txt=${encodedTxt}&tag=${tag || "SWARM"}`,
{
headers: {
"x-jwt": localStorage.getItem(userKey),
},
}
);
ret = await r.text();
const jj = JSON.parse(ret);
if (jj && jj["stack_error"]) {
Expand Down
52 changes: 38 additions & 14 deletions src/bin/super/superapp/src/Remotes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
import { remotes, tribes } from "./store";
import { onMount } from "svelte";
import type { Remote } from "./types/types";
import { getSwarmNumber, splitHost } from "./utils/index";
import {
getSwarmNumber,
isValidVanityAddress,
splitHost,
} from "./utils/index";
import { selectedNode } from "./store";
import {
create_new_swarm_ec2,
Expand Down Expand Up @@ -60,6 +64,7 @@
let swarm_name_width = max_input_with;
let aws_instance_types = [];
let selected_instance = "";
let vanity_address_error = "";
let selectedRowIds = [];
Expand Down Expand Up @@ -494,7 +499,10 @@
}
function updateVanityAddressWidth(event) {
vanity_address_error = "";
vanity_address = event.target.value.replace(/\s+/g, "");
vanity_address_error = isValidVanityAddress(vanity_address);
const span = document.querySelector(".vanity_address_measure");
vanity_input_width = span.offsetWidth;
if (!vanity_input_width) {
Expand Down Expand Up @@ -671,7 +679,10 @@
<Modal
bind:open={open_create_ec2}
modalHeading="Create New Swarm Ec2 Instance"
primaryButtonDisabled={isSubmitting || !name || !selected_instance}
primaryButtonDisabled={isSubmitting ||
!name ||
!selected_instance ||
vanity_address_error.length > 0}
primaryButtonText={isSubmitting ? "Loading..." : "Create"}
secondaryButtonText="Cancel"
on:click:button--secondary={() => (open_create_ec2 = false)}
Expand Down Expand Up @@ -711,17 +722,19 @@
{/if}
</div>
</div>
<Select
on:change={(e) => (selected_instance = e.target.value)}
helperText="Select Ec2 Instance Size"
labelText="Ec2 Instance Size"
selected={selected_instance}
>
<SelectItem value={""} text={"Select Size"} />
{#each aws_instance_types as option}
<SelectItem value={option.value} text={option.name} />
{/each}
</Select>
<div class="select_instance_container">
<Select
on:change={(e) => (selected_instance = e.target.value)}
helperText="Select Ec2 Instance Size"
labelText="Ec2 Instance Size"
selected={selected_instance}
>
<SelectItem value={""} text={"Select Size"} />
{#each aws_instance_types as option}
<SelectItem value={option.value} text={option.name} />
{/each}
</Select>
</div>
<div class="custom_text_input_container">
<label class="customlabel" for="label">Vanity Address</label>
<div class="custom_input_container">
Expand All @@ -740,6 +753,7 @@
<span class="suffix">{domain}</span>
{/if}
</div>
<small class="error-message">{vanity_address_error}</small>
</div>
</Modal>
</main>
Expand Down Expand Up @@ -774,7 +788,6 @@
overflow: hidden;
border: solid 1px #494949;
border-radius: 0.5rem;
margin-bottom: 1rem;
}
.suffix {
Expand Down Expand Up @@ -818,4 +831,15 @@
border: none;
margin: 0;
}
.error-message {
color: #d32f2f;
margin-top: 0;
font-size: 0.7rem;
}
.select_instance_container {
margin-bottom: 1rem;
margin-top: 1rem;
}
</style>
19 changes: 19 additions & 0 deletions src/bin/super/superapp/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,22 @@ export function getSwarmNumber(default_host: string) {
return "";
}
}

export function isValidVanityAddress(vanity_address: string) {
const valid_chars = /^[a-zA-Z0-9-]+$/; // Only letters, numbers, and hyphens
const consecutive_hyphens = /--/; // Check for consecutive hyphens

if (vanity_address.startsWith("-") || vanity_address.endsWith("-")) {
return "Hyphen cannot be the first or last character.";
}

if (consecutive_hyphens.test(vanity_address)) {
return "Hyphens cannot appear consecutively.";
}

if (!valid_chars.test(vanity_address) && vanity_address) {
return "Vanity address can only contain letters, numbers, and hyphens.";
}

return "";
}
37 changes: 37 additions & 0 deletions src/bin/super/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,18 @@ async fn add_domain_name_to_route53(domain_name: &str, public_ip: &str) -> Resul

//Sample execution function
pub async fn create_swarm_ec2(info: &CreateEc2InstanceInfo) -> Result<(), Error> {
if let Some(vanity_address) = &info.vanity_address {
if !vanity_address.is_empty() {
if let Some(subdomain) = vanity_address.strip_suffix(".sphinx.chat") {
let domain_status = is_valid_domain(subdomain.to_string());
if !domain_status.is_empty() {
return Err(anyhow!(domain_status));
}
} else {
return Err(anyhow!("Vanity Address doesn't match the expected format."));
}
}
}
let ec2_intance_id = create_ec2_instance(
info.name.clone(),
info.vanity_address.clone(),
Expand All @@ -542,3 +554,28 @@ pub async fn create_swarm_ec2(info: &CreateEc2InstanceInfo) -> Result<(), Error>
log::info!("Public_IP: {}", ec2_ip_address);
Ok(())
}

fn is_valid_domain(domain: String) -> String {
let valid_chars = |c: char| c.is_ascii_alphanumeric() || c == '-';

if domain.starts_with('-') || domain.ends_with('-') {
return "Hyphen cannot be the first or last character.".to_string();
}

let mut previous_char: Option<char> = None;
for c in domain.chars() {
if !valid_chars(c) {
return "Domain can only contain letters, numbers, and hyphens.".to_string();
}

if let Some(prev) = previous_char {
if prev == '-' && c == '-' {
return "Hyphens cannot appear consecutively.".to_string();
}
}

previous_char = Some(c);
}

"".to_string()
}

0 comments on commit 6cd3e4a

Please sign in to comment.