You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
10 KiB
238 lines
10 KiB
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.ProvisioningProfileAdhocManager = void 0;
|
|
function _appleUtils() {
|
|
const data = require("@expo/apple-utils");
|
|
_appleUtils = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _CommandError() {
|
|
const data = _interopRequireDefault(require("../CommandError"));
|
|
_CommandError = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _ora() {
|
|
const data = require("../utils/ora");
|
|
_ora = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _authenticate() {
|
|
const data = require("./authenticate");
|
|
_authenticate = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _bundleId() {
|
|
const data = require("./bundleId");
|
|
_bundleId = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _distributionCert() {
|
|
const data = require("./distributionCert");
|
|
_distributionCert = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
function uniqueItems(items) {
|
|
const set = new Set(items);
|
|
return [...set];
|
|
}
|
|
async function registerMissingDevicesAsync(context, udids) {
|
|
const allIosProfileDevices = await _appleUtils().Device.getAllIOSProfileDevicesAsync(context);
|
|
const alreadyAdded = allIosProfileDevices.filter(device => udids.includes(device.attributes.udid));
|
|
const alreadyAddedUdids = alreadyAdded.map(i => i.attributes.udid);
|
|
await Promise.all(udids.map(async udid => {
|
|
if (!alreadyAddedUdids.includes(udid)) {
|
|
const device = await _appleUtils().Device.createAsync(context, {
|
|
name: 'iOS Device (added by Expo)',
|
|
udid
|
|
});
|
|
alreadyAdded.push(device);
|
|
}
|
|
}));
|
|
return alreadyAdded;
|
|
}
|
|
async function findProfileByBundleIdAsync(context, bundleId, certSerialNumber) {
|
|
const expoProfiles = (await (0, _bundleId().getProfilesForBundleIdAsync)(context, bundleId)).filter(profile => {
|
|
return profile.attributes.profileType === _appleUtils().ProfileType.IOS_APP_ADHOC && profile.attributes.name.startsWith('*[expo]') && profile.attributes.profileState !== _appleUtils().ProfileState.EXPIRED;
|
|
});
|
|
const expoProfilesWithCertificate = [];
|
|
// find profiles associated with our development cert
|
|
for (const profile of expoProfiles) {
|
|
const certificates = await profile.getCertificatesAsync();
|
|
if (certificates.some(cert => cert.attributes.serialNumber === certSerialNumber)) {
|
|
expoProfilesWithCertificate.push(profile);
|
|
}
|
|
}
|
|
if (expoProfilesWithCertificate) {
|
|
// there is an expo managed profile with our desired certificate
|
|
// return the profile that will be valid for the longest duration
|
|
return {
|
|
profile: expoProfilesWithCertificate.sort(sortByExpiration)[expoProfilesWithCertificate.length - 1],
|
|
didUpdate: false
|
|
};
|
|
} else if (expoProfiles) {
|
|
// there is an expo managed profile, but it doesn't have our desired certificate
|
|
// append the certificate and update the profile
|
|
const distributionCertificate = await (0, _distributionCert().getDistributionCertificateAync)(context, certSerialNumber);
|
|
if (!distributionCertificate) {
|
|
throw new (_CommandError().default)(`Certificate for serial number "${certSerialNumber}" does not exist`);
|
|
}
|
|
const profile = expoProfiles.sort(sortByExpiration)[expoProfiles.length - 1];
|
|
profile.attributes.certificates = [distributionCertificate];
|
|
return {
|
|
profile: await profile.regenerateAsync(),
|
|
didUpdate: true
|
|
};
|
|
}
|
|
|
|
// there is no valid provisioning profile available
|
|
return {
|
|
profile: null,
|
|
didUpdate: false
|
|
};
|
|
}
|
|
function sortByExpiration(a, b) {
|
|
return new Date(a.attributes.expirationDate).getTime() - new Date(b.attributes.expirationDate).getTime();
|
|
}
|
|
async function findProfileByIdAsync(context, profileId, bundleId) {
|
|
var _profiles$find;
|
|
let profiles = await (0, _bundleId().getProfilesForBundleIdAsync)(context, bundleId);
|
|
profiles = profiles.filter(profile => profile.attributes.profileType === _appleUtils().ProfileType.IOS_APP_ADHOC);
|
|
return (_profiles$find = profiles.find(profile => profile.id === profileId)) !== null && _profiles$find !== void 0 ? _profiles$find : null;
|
|
}
|
|
async function manageAdHocProfilesAsync(context, {
|
|
udids,
|
|
bundleId,
|
|
certSerialNumber,
|
|
profileId
|
|
}) {
|
|
// We register all missing devices on the Apple Developer Portal. They are identified by UDIDs.
|
|
const devices = await registerMissingDevicesAsync(context, udids);
|
|
let existingProfile;
|
|
let didUpdate = false;
|
|
if (profileId) {
|
|
existingProfile = await findProfileByIdAsync(context, profileId, bundleId);
|
|
// Fail if we cannot find the profile that was specifically requested
|
|
if (!existingProfile) throw new (_CommandError().default)(`Could not find profile with profile id "${profileId}" for bundle id "${bundleId}"`);
|
|
} else {
|
|
// If no profile id is passed, try to find a suitable provisioning profile for the App ID.
|
|
const results = await findProfileByBundleIdAsync(context, bundleId, certSerialNumber);
|
|
existingProfile = results.profile;
|
|
didUpdate = results.didUpdate;
|
|
}
|
|
if (existingProfile) {
|
|
var _existingProfile$attr, _existingProfile, _existingProfile$attr2, _existingProfile$attr3, _existingProfile$attr4;
|
|
// We need to verify whether the existing profile includes all user's devices.
|
|
let deviceUdidsInProfile = (_existingProfile$attr = (_existingProfile = existingProfile) === null || _existingProfile === void 0 ? void 0 : (_existingProfile$attr2 = _existingProfile.attributes) === null || _existingProfile$attr2 === void 0 ? void 0 : (_existingProfile$attr3 = _existingProfile$attr2.devices) === null || _existingProfile$attr3 === void 0 ? void 0 : (_existingProfile$attr4 = _existingProfile$attr3.map) === null || _existingProfile$attr4 === void 0 ? void 0 : _existingProfile$attr4.call(_existingProfile$attr3, i => i.attributes.udid)) !== null && _existingProfile$attr !== void 0 ? _existingProfile$attr : [];
|
|
deviceUdidsInProfile = uniqueItems(deviceUdidsInProfile.filter(Boolean));
|
|
const allDeviceUdids = uniqueItems(udids);
|
|
const hasEqualUdids = deviceUdidsInProfile.length === allDeviceUdids.length && deviceUdidsInProfile.every(udid => allDeviceUdids.includes(udid));
|
|
if (hasEqualUdids && existingProfile.isValid()) {
|
|
var _existingProfile2, _existingProfile2$att, _existingProfile3, _existingProfile4;
|
|
const result = {
|
|
profileName: (_existingProfile2 = existingProfile) === null || _existingProfile2 === void 0 ? void 0 : (_existingProfile2$att = _existingProfile2.attributes) === null || _existingProfile2$att === void 0 ? void 0 : _existingProfile2$att.name,
|
|
provisioningProfileId: (_existingProfile3 = existingProfile) === null || _existingProfile3 === void 0 ? void 0 : _existingProfile3.id,
|
|
provisioningProfile: (_existingProfile4 = existingProfile) === null || _existingProfile4 === void 0 ? void 0 : _existingProfile4.attributes.profileContent
|
|
};
|
|
if (didUpdate) {
|
|
result.didUpdate = true;
|
|
}
|
|
return result;
|
|
}
|
|
// We need to add new devices to the list and create a new provisioning profile.
|
|
existingProfile.attributes.devices = devices;
|
|
await existingProfile.regenerateAsync();
|
|
const updatedProfile = (await findProfileByBundleIdAsync(context, bundleId, certSerialNumber)).profile;
|
|
if (!updatedProfile) {
|
|
throw new (_CommandError().default)(`Failed to locate updated profile for bundle identifier "${bundleId}" and serial number "${certSerialNumber}"`);
|
|
}
|
|
return {
|
|
didUpdate: true,
|
|
profileName: updatedProfile.attributes.name,
|
|
provisioningProfileId: updatedProfile.id,
|
|
provisioningProfile: updatedProfile.attributes.profileContent
|
|
};
|
|
}
|
|
|
|
// No existing profile...
|
|
|
|
// We need to find user's distribution certificate to make a provisioning profile for it.
|
|
const distributionCertificate = await (0, _distributionCert().getDistributionCertificateAync)(context, certSerialNumber);
|
|
if (!distributionCertificate) {
|
|
// If the distribution certificate doesn't exist, the user must have deleted it, we can't do anything here :(
|
|
throw new (_CommandError().default)(`No distribution certificate for serial number "${certSerialNumber}" is available to make a provisioning profile against`);
|
|
}
|
|
const bundleIdItem = await (0, _bundleId().getBundleIdForIdentifierAsync)(context, bundleId);
|
|
// If the provisioning profile for the App ID doesn't exist, we just need to create a new one!
|
|
const newProfile = await _appleUtils().Profile.createAsync(context, {
|
|
bundleId: bundleIdItem.id,
|
|
// apple drops [ if its the first char (!!),
|
|
name: `*[expo] ${bundleId} AdHoc ${Date.now()}`,
|
|
certificates: [distributionCertificate.id],
|
|
devices: devices.map(device => device.id),
|
|
profileType: _appleUtils().ProfileType.IOS_APP_ADHOC
|
|
});
|
|
return {
|
|
didUpdate: true,
|
|
didCreate: true,
|
|
profileName: newProfile.attributes.name,
|
|
provisioningProfileId: newProfile.id,
|
|
provisioningProfile: newProfile.attributes.profileContent
|
|
};
|
|
}
|
|
async function createOrReuseAdhocProvisioningProfileAsync(authCtx, udids, bundleIdentifier, distCertSerialNumber) {
|
|
const spinner = (0, _ora().ora)(`Handling Apple ad hoc provisioning profiles`).start();
|
|
try {
|
|
const context = (0, _authenticate().getRequestContext)(authCtx);
|
|
const {
|
|
didUpdate,
|
|
didCreate,
|
|
profileName,
|
|
...adhocProvisioningProfile
|
|
} = await manageAdHocProfilesAsync(context, {
|
|
udids,
|
|
bundleId: bundleIdentifier,
|
|
certSerialNumber: distCertSerialNumber
|
|
});
|
|
if (didCreate) {
|
|
spinner.succeed(`Created new profile: ${profileName}`);
|
|
} else if (didUpdate) {
|
|
spinner.succeed(`Updated existing profile: ${profileName}`);
|
|
} else {
|
|
spinner.succeed(`Used existing profile: ${profileName}`);
|
|
}
|
|
return {
|
|
...adhocProvisioningProfile,
|
|
teamId: authCtx.team.id,
|
|
teamName: authCtx.team.name
|
|
};
|
|
} catch (error) {
|
|
spinner.fail(`Failed to handle Apple profiles`);
|
|
throw error;
|
|
}
|
|
}
|
|
class ProvisioningProfileAdhocManager {
|
|
constructor(ctx) {
|
|
this.ctx = ctx;
|
|
}
|
|
async createOrReuse(udids, bundleIdentifier, distCertSerialNumber) {
|
|
return createOrReuseAdhocProvisioningProfileAsync(this.ctx, udids, bundleIdentifier, distCertSerialNumber);
|
|
}
|
|
}
|
|
exports.ProvisioningProfileAdhocManager = ProvisioningProfileAdhocManager;
|
|
//# sourceMappingURL=provisioningProfileAdhoc.js.map
|