Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(apple): declare entitlements in app manifest #2010

Merged
merged 2 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions ios/ReactTestApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
196C22612490CB7600449D3C /* React+Compatibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "React+Compatibility.h"; sourceTree = "<group>"; };
196C7207232EF5DC006556ED /* ReactTestApp-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReactTestApp-Bridging-Header.h"; sourceTree = "<group>"; };
196C7214232F1788006556ED /* ReactInstance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactInstance.swift; sourceTree = "<group>"; };
196C7216232F6CD9006556ED /* ReactTestApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ReactTestApp.entitlements; sourceTree = "<group>"; };
196C7216232F6CD9006556ED /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = SOURCE_ROOT; };
196C724023319A85006556ED /* QRCodeScannerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScannerViewController.swift; sourceTree = "<group>"; };
197827F927710D3400AEC655 /* Manifest+Embedded.g.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Manifest+Embedded.g.swift"; sourceTree = SOURCE_ROOT; };
1988282224105BCC005057FF /* UIViewController+ReactTestApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+ReactTestApp.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -131,10 +131,10 @@
196C22602490CB7600449D3C /* React+Compatibility.m */,
1988282224105BCC005057FF /* UIViewController+ReactTestApp.h */,
1988284424105BEC005057FF /* UIViewController+ReactTestApp.m */,
196C7216232F6CD9006556ED /* App.entitlements */,
19ECD0DB232ED427003D8557 /* Assets.xcassets */,
19ECD0E3232ED427003D8557 /* Info.plist */,
191A67832BDFCD5C0094F246 /* PrivacyInfo.xcprivacy */,
196C7216232F6CD9006556ED /* ReactTestApp.entitlements */,
192F052724AD3CC500A48456 /* ReactTestApp.common.xcconfig */,
192F052824AD3CC500A48456 /* ReactTestApp.debug.xcconfig */,
192F052624AD3CC500A48456 /* ReactTestApp.release.xcconfig */,
Expand Down Expand Up @@ -400,7 +400,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ReactTestApp/ReactTestApp.entitlements;
CODE_SIGN_ENTITLEMENTS = App.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = UBF8T346G9;
Expand All @@ -424,7 +424,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ReactTestApp/ReactTestApp.entitlements;
CODE_SIGN_ENTITLEMENTS = App.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = UBF8T346G9;
Expand Down
10 changes: 0 additions & 10 deletions ios/ReactTestApp/ReactTestApp.entitlements

This file was deleted.

29 changes: 29 additions & 0 deletions ios/entitlements.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require('cfpropertylist')

require_relative('pod_helpers')

DEFAULT_IOS_ENTITLEMENTS = {
'keychain-access-groups' => [
'$(AppIdentifierPrefix)com.microsoft.adalcache',
],
}.freeze

DEFAULT_MACOS_ENTITLEMENTS = {
'com.apple.security.app-sandbox' => true,
'com.apple.security.files.user-selected.read-only' => true,
'com.apple.security.network.client' => true,
}.freeze

def generate_entitlements!(project_root, target_platform, destination)
user_entitlements = platform_config('codeSignEntitlements', project_root, target_platform)
# If `codeSignEntitlements` is a string, set `CODE_SIGN_ENTITLEMENTS` instead
return if user_entitlements.is_a? String

entitlements = target_platform == :macos ? DEFAULT_MACOS_ENTITLEMENTS : DEFAULT_IOS_ENTITLEMENTS

plist = CFPropertyList::List.new
plist.value = CFPropertyList.guess(entitlements.merge(user_entitlements || {}))
plist.save(File.join(destination, 'App.entitlements'),
CFPropertyList::List::FORMAT_XML,
{ :formatted => true })
end
2 changes: 2 additions & 0 deletions ios/test_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require('pathname')

require_relative('assets_catalog')
require_relative('entitlements')
require_relative('info_plist')
require_relative('pod_helpers')
require_relative('privacy_manifest')
Expand Down Expand Up @@ -190,6 +191,7 @@ def make_project!(xcodeproj, project_root, target_platform, options)
end

generate_assets_catalog!(project_root, target_platform, destination)
generate_entitlements!(project_root, target_platform, destination)
generate_info_plist!(project_root, target_platform, destination)
generate_privacy_manifest!(project_root, target_platform, destination)

Expand Down
8 changes: 4 additions & 4 deletions macos/ReactTestApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
193EF066247A736300BE8C79 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = SOURCE_ROOT; };
193EF069247A736300BE8C79 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
193EF06B247A736300BE8C79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
193EF06C247A736300BE8C79 /* ReactTestApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ReactTestApp.entitlements; sourceTree = "<group>"; };
193EF06C247A736300BE8C79 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = SOURCE_ROOT; };
193EF071247A736300BE8C79 /* ReactTestAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactTestAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
193EF077247A736300BE8C79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
193EF07C247A736300BE8C79 /* ReactTestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactTestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -128,11 +128,11 @@
196C22632490CBAB00449D3C /* React+Compatibility.m */,
193EF092247A830200BE8C79 /* UIViewController+ReactTestApp.h */,
193EF091247A830200BE8C79 /* UIViewController+ReactTestApp.m */,
193EF06C247A736300BE8C79 /* App.entitlements */,
193EF066247A736300BE8C79 /* Assets.xcassets */,
193EF068247A736300BE8C79 /* Main.storyboard */,
193EF06B247A736300BE8C79 /* Info.plist */,
191A67872BDFD9E90094F246 /* PrivacyInfo.xcprivacy */,
193EF06C247A736300BE8C79 /* ReactTestApp.entitlements */,
19B368BC24B12C24002CCEFF /* ReactTestApp.common.xcconfig */,
19B368BD24B12C24002CCEFF /* ReactTestApp.debug.xcconfig */,
19B368BE24B12C24002CCEFF /* ReactTestApp.release.xcconfig */,
Expand Down Expand Up @@ -391,7 +391,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ReactTestApp/ReactTestApp.entitlements;
CODE_SIGN_ENTITLEMENTS = App.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
Expand All @@ -412,7 +412,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = ReactTestApp/ReactTestApp.entitlements;
CODE_SIGN_ENTITLEMENTS = App.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
Expand Down
12 changes: 0 additions & 12 deletions macos/ReactTestApp/ReactTestApp.entitlements

This file was deleted.

15 changes: 11 additions & 4 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,16 @@
]
},
"codeSignEntitlements": {
"description": "Specifies the path to a custom [Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements) file. The path should be relative to `app.json`.",
"markdownDescription": "Specifies the path to a custom\n[Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements)\nfile. The path should be relative to `app.json`.\n\nThis is the same as setting `CODE_SIGN_ENTITLEMENTS` in Xcode.\n\nIntroduced in\n[0.9.7](https://github.com/microsoft/react-native-test-app/releases/tag/0.9.7).",
"type": "string"
"description": "Declare entitlements for capabilities used by the app.",
"markdownDescription": "Declare entitlements for capabilities used by the app.\n\nExample:\n\n```json\n{\n \"ios\": {\n \"codeSignEntitlements\": {\n \"com.apple.developer.game-center\": true\n }\n }\n}\n```\n\nFor more details, read Apple's documentation on\n[Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements).\n\nAlternatively, specify a path to a custom `.entitlements` file. The path should\nbe relative to `app.json`. This is equivalent to setting\n`CODE_SIGN_ENTITLEMENTS` in Xcode.",
"oneOf": [
{
"type": "string"
},
{
"type": "object"
}
]
},
"codeSignIdentity": {
"description": "Sets the <a href='https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html#//apple_ref/doc/uid/TP40005929-CH4-SW1'>code signing identity</a> to use when signing code.",
Expand All @@ -78,7 +85,7 @@
},
"privacyManifest": {
"description": "The privacy manifest is a property list that records the information regarding the types of data collected and the required reasons APIs your app or third-party SDK use.",
"markdownDescription": "The privacy manifest is a property list that records the information regarding\nthe types of data collected and the required reasons APIs your app or\nthird-party SDK use.\n\n- The types of data collected by your app or third-party SDK must be provided on\n all platforms.\n- The required reasons APIs your app or third-party SDK uses must be provided on\n iOS, iPadOS, tvOS, visionOS, and watchOS.\n\nBy default, a `PrivacyInfo.xcprivacy` is always generated with the following\nvalues:\n\n```json\n{\n \"NSPrivacyTracking\": false,\n \"NSPrivacyTrackingDomains\": [],\n \"NSPrivacyCollectedDataTypes\": [],\n \"NSPrivacyAccessedAPITypes\": [\n {\n \"NSPrivacyAccessedAPIType\": \"NSPrivacyAccessedAPICategoryFileTimestamp\",\n \"NSPrivacyAccessedAPITypeReasons\": [\"C617.1\"]\n },\n {\n \"NSPrivacyAccessedAPIType\": \"NSPrivacyAccessedAPICategorySystemBootTime\",\n \"NSPrivacyAccessedAPITypeReasons\": [\"35F9.1\"]\n },\n {\n \"NSPrivacyAccessedAPIType\": \"NSPrivacyAccessedAPICategoryUserDefaults\",\n \"NSPrivacyAccessedAPITypeReasons\": [\"CA92.1\"]\n }\n ]\n}\n```\n\nFor more details, read Apple's documentation on\n[Privacy manifest files](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files).",
"markdownDescription": "The privacy manifest is a property list that records the information regarding\nthe types of data collected and the required reasons APIs your app or\nthird-party SDK use.\n\n- The types of data collected by your app or third-party SDK must be provided on\n all platforms.\n- The required reasons APIs your app or third-party SDK uses must be provided on\n iOS, iPadOS, tvOS, visionOS, and watchOS.\n\nBy default, a `PrivacyInfo.xcprivacy` is always generated with the following\nvalues:\n\n<!-- prettier-ignore-start -->\n```json\n{\n \"NSPrivacyTracking\": false,\n \"NSPrivacyTrackingDomains\": [],\n \"NSPrivacyCollectedDataTypes\": [],\n \"NSPrivacyAccessedAPITypes\": [\n {\n \"NSPrivacyAccessedAPIType\":\n \"NSPrivacyAccessedAPICategoryFileTimestamp\",\n \"NSPrivacyAccessedAPITypeReasons\": [\"C617.1\"]\n },\n {\n \"NSPrivacyAccessedAPIType\":\n \"NSPrivacyAccessedAPICategorySystemBootTime\",\n \"NSPrivacyAccessedAPITypeReasons\": [\"35F9.1\"]\n },\n {\n \"NSPrivacyAccessedAPIType\":\n \"NSPrivacyAccessedAPICategoryUserDefaults\",\n \"NSPrivacyAccessedAPITypeReasons\": [\"CA92.1\"]\n }\n ]\n}\n```\n<!-- prettier-ignore-end -->\n\nFor more details, read Apple's documentation on\n[Privacy manifest files](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files).",
"type": "object"
}
}
Expand Down
5 changes: 1 addition & 4 deletions scripts/config-plugins/plugins/withIosBaseMods.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ const defaultProviders = {
"ReactTestApp.xcodeproj/project.pbxproj"
),
infoPlist: modifyFilePath(expoProviders.infoPlist, "Info.plist"),
entitlements: modifyFilePath(
expoProviders.entitlements,
"ReactTestApp/ReactTestApp.entitlements"
),
entitlements: nullProvider,
podfileProperties: nullProvider,
};

Expand Down
24 changes: 18 additions & 6 deletions scripts/docs/ios.codeSignEntitlements.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
Specifies the path to a custom
[Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements)
file. The path should be relative to `app.json`.
Declare entitlements for capabilities used by the app.

This is the same as setting `CODE_SIGN_ENTITLEMENTS` in Xcode.
Example:

Introduced in
[0.9.7](https://github.com/microsoft/react-native-test-app/releases/tag/0.9.7).
```json
{
"ios": {
"codeSignEntitlements": {
"com.apple.developer.game-center": true
}
}
}
```

For more details, read Apple's documentation on
[Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements).

Alternatively, specify a path to a custom `.entitlements` file. The path should
be relative to `app.json`. This is equivalent to setting
`CODE_SIGN_ENTITLEMENTS` in Xcode.
11 changes: 8 additions & 3 deletions scripts/docs/ios.privacyManifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,32 @@ third-party SDK use.
By default, a `PrivacyInfo.xcprivacy` is always generated with the following
values:

<!-- prettier-ignore-start -->
```json
{
"NSPrivacyTracking": false,
"NSPrivacyTrackingDomains": [],
"NSPrivacyCollectedDataTypes": [],
"NSPrivacyAccessedAPITypes": [
{
"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategoryFileTimestamp",
"NSPrivacyAccessedAPIType":
"NSPrivacyAccessedAPICategoryFileTimestamp",
"NSPrivacyAccessedAPITypeReasons": ["C617.1"]
},
{
"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategorySystemBootTime",
"NSPrivacyAccessedAPIType":
"NSPrivacyAccessedAPICategorySystemBootTime",
"NSPrivacyAccessedAPITypeReasons": ["35F9.1"]
},
{
"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategoryUserDefaults",
"NSPrivacyAccessedAPIType":
"NSPrivacyAccessedAPICategoryUserDefaults",
"NSPrivacyAccessedAPITypeReasons": ["CA92.1"]
}
]
}
```
<!-- prettier-ignore-end -->

For more details, read Apple's documentation on
[Privacy manifest files](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files).
2 changes: 1 addition & 1 deletion scripts/schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function generateSchema(docs = {}) {
codeSignEntitlements: {
description: extractBrief(docs["ios.codeSignEntitlements"]),
markdownDescription: docs["ios.codeSignEntitlements"],
type: "string",
oneOf: [{ type: "string" }, { type: "object" }],
},
codeSignIdentity: {
description: extractBrief(docs["ios.codeSignIdentity"]),
Expand Down
4 changes: 1 addition & 3 deletions test/pack.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ describe("npm pack", () => {
"ios/ReactTestApp/ReactTestApp-DevSupport.m",
"ios/ReactTestApp/ReactTestApp.common.xcconfig",
"ios/ReactTestApp/ReactTestApp.debug.xcconfig",
"ios/ReactTestApp/ReactTestApp.entitlements",
"ios/ReactTestApp/ReactTestApp.release.xcconfig",
"ios/ReactTestApp/SceneDelegate.swift",
"ios/ReactTestApp/Session.swift",
Expand All @@ -145,6 +144,7 @@ describe("npm pack", () => {
"ios/ReactTestAppUITests/Info.plist",
"ios/ReactTestAppUITests/ReactTestAppUITests.swift",
"ios/assets_catalog.rb",
"ios/entitlements.rb",
"ios/info_plist.rb",
"ios/pod_helpers.rb",
"ios/privacy_manifest.rb",
Expand All @@ -164,7 +164,6 @@ describe("npm pack", () => {
"macos/ReactTestApp/Info.plist",
"macos/ReactTestApp/ReactTestApp.common.xcconfig",
"macos/ReactTestApp/ReactTestApp.debug.xcconfig",
"macos/ReactTestApp/ReactTestApp.entitlements",
"macos/ReactTestApp/ReactTestApp.release.xcconfig",
"macos/ReactTestApp/ViewController.swift",
"macos/ReactTestAppTests/Info.plist",
Expand Down Expand Up @@ -217,7 +216,6 @@ describe("npm pack", () => {
"visionos/ReactTestApp/Info.plist",
"visionos/ReactTestApp/ReactTestApp.common.xcconfig",
"visionos/ReactTestApp/ReactTestApp.debug.xcconfig",
"visionos/ReactTestApp/ReactTestApp.entitlements",
"visionos/ReactTestApp/ReactTestApp.release.xcconfig",
"visionos/ReactTestAppTests/Info.plist",
"visionos/ReactTestAppTests/ReactTestAppTests.swift",
Expand Down
Loading
Loading