Skip to content

Commit

Permalink
feat(apple): declare entitlements in app manifest (#2010)
Browse files Browse the repository at this point in the history
  • Loading branch information
tido64 committed May 3, 2024
1 parent 2f6784b commit 019cb93
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 65 deletions.
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

0 comments on commit 019cb93

Please sign in to comment.