Skip to content

Commit

Permalink
Implement install ipa
Browse files Browse the repository at this point in the history
  • Loading branch information
yunusefendi52 committed May 1, 2024
1 parent 5f13b63 commit f6e3340
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 46 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"scripts": {
"build": "nuxt build",
"dev": "HOST=localhost nuxt dev",
"dev": "HOST=localhost HOST=0.0.0.0 nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
Expand Down
9 changes: 7 additions & 2 deletions pages/install/[publicId]/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,13 @@ useSeoMeta({
})
const download = (releaseId: number) => {
const url = `/api/install/download?publicId=${publicId}&releaseId=${releaseId}`
window.open(url, '_blank')
if (isIosDevice()) {
const url = generateManifestLink('', '', releaseId.toString(), publicId.toString())
document.location = url
} else {
const url = `/api/install/download?publicId=${publicId}&releaseId=${releaseId}`
window.open(url, '_blank')
}
}
</script>

Expand Down
9 changes: 7 additions & 2 deletions pages/orgs/[orgName]/apps/[appId]/[detailArtifact].vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,13 @@ const { data: detailArtifact, refresh, status: status2 } = useFetch('/api/artifa
})
const download = () => {
const url = `/api/artifacts/download-artifact?appName=${appName}&orgName=${orgName}&releaseId=${releaseId}`
window.open(url, '_blank')
if (isIosDevice()) {
const url = generateManifestLink(appName, orgName, releaseId, undefined)
document.location = url
} else {
const url = `/api/artifacts/download-artifact?appName=${appName}&orgName=${orgName}&releaseId=${releaseId}`
window.open(url, '_blank')
}
}
const { data: appGroups } = useFetch('/api/groups/list-groups', {
Expand Down
30 changes: 25 additions & 5 deletions server/api/artifacts/detail-artifact.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import { generateRandomPassword, getStorageKeys } from "~/server/utils/utils"
import { takeUniqueOrThrow } from "../detail-app.get"
import { GetObjectAttributesCommand, GetObjectTaggingCommand, HeadObjectCommand, ObjectAttributes } from "@aws-sdk/client-s3"
import { S3AppClient, type AppHeadObjectCommandOutput } from "~/server/services/S3AppClient"
import { readPackageFile } from "~/server/utils/package-reader"
import type { EventHandlerRequest, H3Event } from "h3"

export default defineEventHandler(async (event) => {
export const getDetailArtifact = async (
event: H3Event<EventHandlerRequest>,
userId: string,
orgName: string,
appName: string,
releaseId: number | string) => {
const db = event.context.drizzle
const userId = event.context.auth.userId
const { appName, orgName, releaseId } = getQuery(event)
const userOrg = await db.select({
organizationsId: organizations.id,
})
Expand All @@ -22,7 +25,6 @@ export default defineEventHandler(async (event) => {
return operators.and(operators.eq(fields.organizationsId, userOrg.organizationsId!), operators.eq(fields.name, appName!.toString()))
},
}).then(takeUniqueOrThrow)
console.log('ffffff', releaseId)
const releaseIdInt = parseInt(releaseId!.toString())
const detailArtifact = await db.query.artifacts.findMany({
where(fields, operators) {
Expand All @@ -32,6 +34,24 @@ export default defineEventHandler(async (event) => {
)
},
}).then(takeUniqueOrThrow)
return {
userOrg,
detailArtifact,
app,
}
}

export default defineEventHandler(async (event) => {
const db = event.context.drizzle
const userId = event.context.auth.userId
const { appName, orgName, releaseId } = getQuery(event)
const { userOrg, app, detailArtifact } = await getDetailArtifact(
event,
userId,
orgName!.toString(),
appName!.toString(),
parseInt(releaseId!.toString()),
)
const s3 = new S3AppClient()
const { assets } = getStorageKeys(userOrg.organizationsId!, app.id, detailArtifact.fileObjectKey)
const [headObject, groups] = await Promise.all([
Expand Down
24 changes: 22 additions & 2 deletions server/api/artifacts/download-artifact.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ import { organizations, organizationsPeople } from "~/server/db/schema"
import { and, eq } from "drizzle-orm"
import { takeUniqueOrThrow } from "../detail-app.get"
import { S3AppClient } from "~/server/services/S3AppClient"
import type { EventHandlerRequest, H3Event } from "h3"

export default defineEventHandler(async (event) => {
const { appName, orgName, releaseId } = getQuery(event)
export const getArtifactFromInternal = async (
event: H3Event<EventHandlerRequest>,
orgName: string,
appName: string,
releaseId: string,
) => {
const db = event.context.drizzle
const userId = event.context.auth.userId
const userOrg = await db.select({
Expand Down Expand Up @@ -38,5 +43,20 @@ export default defineEventHandler(async (event) => {
Key: assets,
ResponseContentDisposition: `attachment; filename ="${app.name}${detailArtifact.extension ? `.${detailArtifact.extension}` : ''}"`,
}), 1800)
return {
signedUrl,
userOrg,
app,
detailArtifact,
}
}

export default defineEventHandler(async (event) => {
const { appName, orgName, releaseId } = getQuery(event)
const { signedUrl } = await getArtifactFromInternal(
event,
orgName!.toString(),
appName!.toString(),
releaseId!.toString())
await sendRedirect(event, signedUrl)
})
52 changes: 27 additions & 25 deletions server/api/install/download.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,16 @@ import { organizations, organizationsPeople } from "~/server/db/schema"
import { and, eq } from "drizzle-orm"
import { takeUniqueOrThrow } from "../detail-app.get"
import { S3AppClient } from "~/server/services/S3AppClient"
import { getArtifactFromPublicId } from './get-data.get'
import type { EventHandlerRequest, H3Event } from "h3"

export default defineEventHandler(async (event) => {
const query = getQuery(event)
const publicId = query.publicId?.toString()
const releaseIdStr = query.releaseId?.toString()
if (!publicId || !releaseIdStr) {
setResponseStatus(event, 401)
return
}
const releaseId = parseInt(releaseIdStr!)

export const getArtifactLinkFromPublicIdAndReleaseId = async (
event: H3Event<EventHandlerRequest>,
publicId: string,
releaseId: number,
) => {
const db = event.context.drizzle
const artifactGroup = await db.query.artifactsGroups.findMany({
where(fields, operators) {
return operators.eq(fields.publicId, publicId)
},
}).then(takeUniqueOrThrow)
const app = await db.query.apps.findMany({
where(fields, operators) {
return operators.eq(fields.id, artifactGroup.appsId!)
},
}).then(takeUniqueOrThrow)
const org = await db.query.organizations.findMany({
where(fields, operators) {
return operators.eq(fields.id, app.organizationsId!)
},
}).then(takeUniqueOrThrow)
const { app, artifactGroup, org } = await getArtifactFromPublicId(event, publicId)
const detailArtifact = await db.query.artifacts.findMany({
where(fields, operators) {
return operators.and(
Expand All @@ -47,5 +30,24 @@ export default defineEventHandler(async (event) => {
Key: assets,
ResponseContentDisposition: `attachment; filename ="${app.name}${detailArtifact.extension ? `.${detailArtifact.extension}` : ''}"`,
}), 1800)
return {
signedUrl,
app,
org,
artifactGroup,
detailArtifact,
}
}

export default defineEventHandler(async (event) => {
const query = getQuery(event)
const publicId = query.publicId?.toString()
const releaseIdStr = query.releaseId?.toString()
if (!publicId || !releaseIdStr) {
setResponseStatus(event, 401)
return
}
const releaseId = parseInt(releaseIdStr!)
const { signedUrl } = await getArtifactLinkFromPublicIdAndReleaseId(event, publicId, releaseId)
await sendRedirect(event, signedUrl)
})
27 changes: 19 additions & 8 deletions server/api/install/get-data.get.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import { and, desc, eq } from "drizzle-orm"
import { artifacts, artifactsGroupsManager, organizations, organizationsPeople } from "~/server/db/schema"
import { takeUniqueOrThrow } from "../detail-app.get"
import type { EventHandlerRequest, H3Event, H3EventContext } from "h3"

export default defineEventHandler(async (event) => {
const query = getQuery(event)
const publicId = query.publicId?.toString()
if (!publicId) {
setResponseStatus(event, 401)
return
}

export const getArtifactFromPublicId = async (event: H3Event<EventHandlerRequest>, publicId: string) => {
const db = event.context.drizzle
const artifactGroup = await db.query.artifactsGroups.findMany({
where(fields, operators) {
Expand All @@ -26,6 +20,23 @@ export default defineEventHandler(async (event) => {
return operators.eq(fields.id, app.organizationsId!)
},
}).then(takeUniqueOrThrow)
return {
app,
org,
artifactGroup,
}
}

export default defineEventHandler(async (event) => {
const query = getQuery(event)
const publicId = query.publicId?.toString()
if (!publicId) {
setResponseStatus(event, 401)
return
}

const db = event.context.drizzle
const { app, artifactGroup, org } = await getArtifactFromPublicId(event, publicId)
const artifactList = await db.select()
.from(artifactsGroupsManager)
.leftJoin(artifacts, eq(artifacts.id, artifactsGroupsManager.artifactsId))
Expand Down
58 changes: 58 additions & 0 deletions server/api/manifest.plist.get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import _ from 'lodash'
import { takeUniqueOrThrow } from './detail-app.get'
import { getArtifactLinkFromPublicIdAndReleaseId } from './install/download.get'
import { getArtifactFromInternal } from './artifacts/download-artifact.get'

export default defineEventHandler(async (event) => {
const query = getQuery(event)
const data = JSON.parse(atob(query.data!.toString()))
const publicId = data.publicLink
const releaseId = data.releaseId

// Param from logged in user (without public id)
const orgName = data.orgName
const appName = data.appName

const { signedUrl, app, detailArtifact: artifact } = publicId ?
await getArtifactLinkFromPublicIdAndReleaseId(event, publicId, releaseId)
: await getArtifactFromInternal(
event,
orgName!.toString(),
appName!.toString(),
releaseId!.toString())
const plist = `
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>${_.escape(signedUrl)}</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>${artifact.packageName}</string>
<key>bundle-version</key>
<string>${artifact.versionName2}</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>${app.displayName}</string>
</dict>
</dict>
</array>
</dict>
</plist>
`
setResponseHeader(event, 'Content-Type', "text/xml plist")
return plist
})
2 changes: 1 addition & 1 deletion server/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ export const generateRandomPassword = (length = 60) => {
}


export const s3BucketName = 'distapp'
export const s3BucketName = 'distapp'
14 changes: 14 additions & 0 deletions utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,17 @@ export function formatBytes(bytes: number, decimals = 2, isBinary = false) {
export const formatDate = (value?: string | null) => {
return moment(value).format('LLL')
}

export const isIosDevice = () => /(iPad|iPhone|iPod)/g.test(navigator.userAgent) || (/(Mac OS)/g.test(navigator.userAgent) && "ontouchend" in document)

export const generateManifestLink = (appName: string, orgName: string, releaseId: string, publicLink: string | undefined) => {
const data = {
appName,
orgName,
releaseId,
publicLink,
}
const dataStr = btoa(JSON.stringify(data))
const dd = encodeURIComponent(`?data=${dataStr}`)
return `itms-services://?action=download-manifest&url=${window.location.origin}/api/manifest.plist${dd}`
}

0 comments on commit f6e3340

Please sign in to comment.