From 873adf58e797f048dd7cdfa99ff7ff44b5575213 Mon Sep 17 00:00:00 2001 From: pkong-ds Date: Mon, 26 Aug 2024 15:55:26 +0800 Subject: [PATCH] Suffix project name of company name with 6 alpha numeric characters --- .../graphql/portal/CreateProjectScreen.tsx | 13 ++---------- portal/src/util/projectname.test.ts | 20 ++++++++----------- portal/src/util/projectname.ts | 17 +++++++--------- 3 files changed, 17 insertions(+), 33 deletions(-) diff --git a/portal/src/graphql/portal/CreateProjectScreen.tsx b/portal/src/graphql/portal/CreateProjectScreen.tsx index c1addb326f..37efd7fd6e 100644 --- a/portal/src/graphql/portal/CreateProjectScreen.tsx +++ b/portal/src/graphql/portal/CreateProjectScreen.tsx @@ -15,8 +15,7 @@ import { ErrorParseRule, makeReasonErrorParseRule } from "../../error/parse"; import { useSimpleForm } from "../../hook/useSimpleForm"; import { randomProjectName, - getRandom32BitsNumber, - maskNumber, + projectNameWithCompanyName, } from "../../util/projectname"; import PrimaryButton from "../../PrimaryButton"; @@ -75,14 +74,6 @@ function processCompanyName(companyName: string): string { .toLowerCase(); } -function addRandomNumberSuffix(intermediateProjectName: string): string { - return ( - intermediateProjectName + - "-" + - maskNumber(getRandom32BitsNumber(), 0, 10).toString() - ); -} - function CreateProjectScreenContent(props: CreateProjectScreenContentProps) { const { numberOfApps } = props; const navigate = useNavigate(); @@ -104,7 +95,7 @@ function CreateProjectScreenContent(props: CreateProjectScreenContentProps) { if (typedState) { const intermediateName = processCompanyName(typedState.company_name); if (intermediateName !== "") - defaultState.appID = addRandomNumberSuffix(intermediateName); + defaultState.appID = projectNameWithCompanyName(intermediateName); } return defaultState; }, [state]); diff --git a/portal/src/util/projectname.test.ts b/portal/src/util/projectname.test.ts index 6a8ecbdac5..cd69316d6e 100644 --- a/portal/src/util/projectname.test.ts +++ b/portal/src/util/projectname.test.ts @@ -2,19 +2,9 @@ import { describe, it, expect } from "@jest/globals"; import { deterministicProjectName, extractBits, - maskNumber, + projectNameWithCompanyName, } from "./projectname"; -describe("maskNumber", () => { - it("should mask the number starting from 0 bit and get 11 bits after it", () => { - expect(maskNumber(12345678, 0, 11)).toEqual(334); - }); - - it("should mask the number starting from 20 bit and get 5 bits after it", () => { - expect(maskNumber(12345678, 20, 5)).toEqual(11); - }); -}); - describe("extractBits", () => { it("should handle bytes that look like signed bits", () => { expect( @@ -61,7 +51,6 @@ describe("deterministicProjectName", () => { }); it("deterministicProjectName([87, 87, 87, 87, 87, 87]) is 'firm-pwldul' ", () => { - ("1011101010111010101110101011101010111"); // [87, 87, 87, 87, 87, 87] is 0b01010111010_1011101010111010101110101011101_010111 // 0b0b01010111010 is 'firm' // 1011101010111010101110101011101 is 'pwldul' @@ -71,3 +60,10 @@ describe("deterministicProjectName", () => { expect(deterministicProjectName(fortyEightBits)).toEqual("firm-pwldul"); }); }); + +describe("projectNameWithCompanyName", () => { + it("projectNameWithCompanyName('authgear') starts with 'authgear-` and ends with 6 lowercase-alphanumeric characters", () => { + const authgearProjectName = projectNameWithCompanyName("authgear"); + expect(authgearProjectName).toMatch(/^authgear-[a-z0-9]{6}$/); + }); +}); diff --git a/portal/src/util/projectname.ts b/portal/src/util/projectname.ts index 40474178b0..6c540c9b21 100644 --- a/portal/src/util/projectname.ts +++ b/portal/src/util/projectname.ts @@ -11,16 +11,6 @@ export function getRandom48Bits(): Uint8Array { return randomBuffer; } -export function getRandom32BitsNumber(): number { - const randomBuffer = new Uint32Array(1); - window.crypto.getRandomValues(randomBuffer); - return randomBuffer[0]; -} - -export function maskNumber(num: number, startAt: number, bits: number): number { - return (num >> startAt) & ((1 << bits) - 1); -} - /** * This function take 48 bits, and split into 2 numbers, bit_0_10 and bit_11_41, dropping the last 6 bits * @@ -91,3 +81,10 @@ export function deterministicProjectName(fortyEightBits: Uint8Array): string { export function randomProjectName(): string { return deterministicProjectName(getRandom48Bits()); } + +export function projectNameWithCompanyName(companyName: string): string { + const randomBits = getRandom48Bits(); + const [_, thirtyOneBits] = extractBits(randomBits); + const alphaNumericString = deterministicAlphanumericString(thirtyOneBits); + return `${companyName}-${alphaNumericString}`; +}