Skip to content
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 61 additions & 5 deletions src/init/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
let globalPlatform: 'ios' | 'android' = 'ios'
let globalDelta = false
let globalCurrentVersion: string | undefined
let globalAppId: string | undefined

function readTmpObj() {
tmpObject ??= readdirSync(tmp.tmpdir)
Expand Down Expand Up @@ -391,10 +392,16 @@
}
}

let globalOrgId: string | undefined
let globalOrgName: string | undefined

function markStepDone(step: number, pathToPackageJson?: string, channelName?: string) {
try {
writeFileSync(getTmpObjectPath(), JSON.stringify({
step_done: step,
orgId: globalOrgId,
orgName: globalOrgName,
appId: globalAppId,
pathToPackageJson: pathToPackageJson ?? globalPathToPackageJson,
channelName: channelName ?? globalChannelName,
platform: globalPlatform,
Expand All @@ -414,14 +421,30 @@
}
}

async function readStepsDone(orgId: string, apikey: string): Promise<number | undefined> {
interface ResumeResult {
stepDone: number
orgId: string
orgName: string
appId?: string
}

async function tryResumeOnboarding(apikey: string): Promise<ResumeResult | undefined> {

Check failure on line 431 in src/init/command.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 18 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=Cap-go_capgo-cli&issues=AZ0bj-Ea_I2f9sMfM0ro&open=AZ0bj-Ea_I2f9sMfM0ro&pullRequest=569
try {
const rawData = readFileSync(getTmpObjectPath(), 'utf-8')
if (!rawData || rawData.length === 0)
return undefined

const { step_done, pathToPackageJson, channelName, platform, delta, currentVersion } = JSON.parse(rawData)
const { step_done, orgId, orgName, appId: savedAppId, pathToPackageJson, channelName, platform, delta, currentVersion } = JSON.parse(rawData)
if (!orgId || !step_done) {
pLog.warn('⚠️ Found previous onboarding progress, but it was saved in an older format.')
pLog.info(' Starting fresh. Your previous progress cannot be resumed.')
return undefined
}

pLog.info(formatInitResumeMessage(step_done, initOnboardingSteps.length))
if (orgName) {
pLog.info(` Organization: ${orgName}`)
}
const resumeChoice = await pSelect({
message: 'Would you like to continue from where you left off?',
options: [
Expand All @@ -446,7 +469,10 @@
if (typeof currentVersion === 'string' && currentVersion.length > 0) {
globalCurrentVersion = currentVersion
}
return step_done
if (savedAppId) {
globalAppId = savedAppId
}
return { stepDone: step_done, orgId, orgName, appId: savedAppId }
}

return undefined
Expand Down Expand Up @@ -2318,13 +2344,42 @@
const supabase = await createSupabaseClient(options.apikey, options.supaHost, options.supaAnon)
await verifyUser(supabase, options.apikey, ['upload', 'all', 'read', 'write'])

const organization = await selectOrganizationForInit(supabase, ['admin', 'super_admin'])
// Try to resume from saved state before asking for org selection
const resumed = await tryResumeOnboarding(options.apikey)
let stepToSkip = resumed?.stepDone ?? 0

let organization: Organization
if (resumed) {
// Fetch orgs to find the saved one (we need the full Organization object)
const { data: allOrganizations } = await supabase.rpc('get_orgs_v7')
const savedOrg = allOrganizations?.find(org => org.gid === resumed.orgId)
if (savedOrg) {
organization = savedOrg
pLog.info(`Using organization "${savedOrg.name}"`)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reapply org access checks before auto-resuming org

This branch accepts savedOrg from get_orgs_v7 and assigns it directly, which skips the admin-role and 2FA checks enforced in selectOrganizationForInit (normalizeRole filtering and enforcing_2fa guard). If a user’s permissions changed since the saved state (e.g., no longer admin, or 2FA required but not enabled), resume will continue with an org they can’t onboard and fail later instead of falling back to org selection as intended.

Useful? React with 👍 / 👎.

}
else {
pLog.warn(`Previously used organization "${resumed.orgName}" is no longer available. Please select a new one.`)
organization = await selectOrganizationForInit(supabase, ['admin', 'super_admin'])
stepToSkip = 0
}
}
else {
organization = await selectOrganizationForInit(supabase, ['admin', 'super_admin'])
}

const orgId = organization.gid
globalOrgId = orgId
globalOrgName = organization.name

if (resumed?.appId) {
appId = resumed.appId
globalAppId = appId
}

const pendingOnboardingSelection = await maybeReusePendingOnboardingApp(organization, options.apikey, appId, supabase)
appId = pendingOnboardingSelection.appId ?? appId
await ensureCapacitorProjectReady(orgId, options.apikey, appId, pendingOnboardingSelection.pendingApp)

let stepToSkip = await readStepsDone(orgId, options.apikey) ?? 0
if (pendingOnboardingSelection.reusedPendingApp) {
stepToSkip = Math.max(stepToSkip, 1)
}
Expand All @@ -2351,6 +2406,7 @@
renderCurrentStep(1)
await checkPrerequisitesStep(orgId, options.apikey)
appId = await addAppStep(organization, options.apikey, appId, options)
globalAppId = appId
markStepDone(1)
}

Expand Down
Loading