Skip to content

Commit

Permalink
Merge pull request #558 from macadmins/development
Browse files Browse the repository at this point in the history
Move core pre/postinstall logic to Nudge.app, fix calendar issue, new essentials package
  • Loading branch information
erikng authored Mar 7, 2024
2 parents 2defb16 + bedf0a5 commit ca0df33
Show file tree
Hide file tree
Showing 13 changed files with 278 additions and 111 deletions.
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.15] - 2024-03-07
This will be the **final Nudge release** for macOS 11 and potentially other versions of macOS.

Due to several bugs found in the v1.1.14 release, including many subsequent v1.1.14.x builds, this release is being created to address them.

There are currently no known regressions from v1.1.13.

### Added
- `Essentials` Package
- This signed and notarized package contains the Nudge application and LaunchAgent
- Additional shortcut keys to ignore list when Nudge is in the forefront
- `Security.md` file added for pentesters to send potential security issues within the project

### Changed
- macOS upgrade logic now uses `/System/Library/CoreServices/Software Update.app` as the default path for unknown installer versions
- The LaunchAgent and Logger packages are now signed and notarized
- The Zsh package scripts are now embedded into the Nudge application
- Please note that if you install the LaunchAgent or Logger packages, you will need to install them **after** the Nudge application package. Failure to do this will result in the `postinstall` scripts not triggering.
- The `postinstall` script is now in Bash, but calls Zsh without global/user environment variables
- Moved the `preinstall` script logic to `postinstall`
- This materially changes the Nudge application package and the Suite package

### Fixed
- All known regressions in v1.1.14
- Some ignored shortcut keys were improperly designed and not working
- `userSessionDeferrals` were not being accurately calculated
- When using `calendarDeferralUnit`, the upper bounds of the calendar may return a negative integer, causing Nudge to crash.
- The behavior will now return `0`

## [1.1.14] - 2024-01-30
This will be the **final Nudge release** for macOS 11 and potentially other versions of macOS.

Expand Down
20 changes: 20 additions & 0 deletions Nudge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
63D7D0F625C9E9A500236281 /* NudgeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63D7D0F525C9E9A500236281 /* NudgeTests.swift */; };
63D7D10125C9E9A500236281 /* NudgeUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63D7D10025C9E9A500236281 /* NudgeUITests.swift */; };
63D7D12725C9F1EE00236281 /* StandardMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63D7D12625C9F1EE00236281 /* StandardMode.swift */; };
63FD280F2B96846A004E0108 /* postinstall-launchagent in Resources */ = {isa = PBXBuildFile; fileRef = 63FD280B2B9682CD004E0108 /* postinstall-launchagent */; };
63FD28102B96846E004E0108 /* postinstall-logger in Resources */ = {isa = PBXBuildFile; fileRef = 63FD280C2B9682F9004E0108 /* postinstall-logger */; };
63FD28122B968475004E0108 /* postinstall-nudge in Resources */ = {isa = PBXBuildFile; fileRef = 63FD280E2B96831F004E0108 /* postinstall-nudge */; };
73CC1D7829B81EE500FBF8E2 /* com.github.macadmins.Nudge.SMAppService.plist in Resources */ = {isa = PBXBuildFile; fileRef = 73CC1D7729B81EE500FBF8E2 /* com.github.macadmins.Nudge.SMAppService.plist */; };
73CC1D7A29B81F0600FBF8E2 /* com.github.macadmins.Nudge.SMAppService.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 73CC1D7729B81EE500FBF8E2 /* com.github.macadmins.Nudge.SMAppService.plist */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -118,6 +121,9 @@
63D7D10025C9E9A500236281 /* NudgeUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NudgeUITests.swift; sourceTree = "<group>"; };
63D7D10225C9E9A500236281 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
63D7D12625C9F1EE00236281 /* StandardMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardMode.swift; sourceTree = "<group>"; };
63FD280B2B9682CD004E0108 /* postinstall-launchagent */ = {isa = PBXFileReference; lastKnownFileType = text; path = "postinstall-launchagent"; sourceTree = "<group>"; };
63FD280C2B9682F9004E0108 /* postinstall-logger */ = {isa = PBXFileReference; lastKnownFileType = text; path = "postinstall-logger"; sourceTree = "<group>"; };
63FD280E2B96831F004E0108 /* postinstall-nudge */ = {isa = PBXFileReference; lastKnownFileType = text; path = "postinstall-nudge"; sourceTree = "<group>"; };
73CC1D7729B81EE500FBF8E2 /* com.github.macadmins.Nudge.SMAppService.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.github.macadmins.Nudge.SMAppService.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -255,6 +261,7 @@
639B6B5425DF374600E38EC1 /* UI */,
639B6B3925DF1FEB00E38EC1 /* Preferences */,
639B6B4725DF218900E38EC1 /* Utilities */,
63FD280A2B968290004E0108 /* Scripts */,
63D7D0E625C9E9A500236281 /* Assets.xcassets */,
63D7D0EB25C9E9A500236281 /* Info.plist */,
63D7D0EC25C9E9A500236281 /* Nudge.entitlements */,
Expand Down Expand Up @@ -291,6 +298,16 @@
path = NudgeUITests;
sourceTree = "<group>";
};
63FD280A2B968290004E0108 /* Scripts */ = {
isa = PBXGroup;
children = (
63FD280B2B9682CD004E0108 /* postinstall-launchagent */,
63FD280C2B9682F9004E0108 /* postinstall-logger */,
63FD280E2B96831F004E0108 /* postinstall-nudge */,
);
path = Scripts;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -412,13 +429,16 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
63FD280F2B96846A004E0108 /* postinstall-launchagent in Resources */,
63D7D0EA25C9E9A500236281 /* Preview Assets.xcassets in Resources */,
63FD28122B968475004E0108 /* postinstall-nudge in Resources */,
63D7D0E725C9E9A500236281 /* Assets.xcassets in Resources */,
639B6B0F25DC9ED300E38EC1 /* com.github.macadmins.Nudge.mobileconfig in Resources */,
73CC1D7829B81EE500FBF8E2 /* com.github.macadmins.Nudge.SMAppService.plist in Resources */,
63C6A08E2833FB6500D5264A /* com.github.macadmins.Nudge.tester.json in Resources */,
035C2AEC25D8ABC400429458 /* com.github.macadmins.Nudge.json in Resources */,
6316F0E72832CA0700E1354D /* Schema in Resources */,
63FD28102B96846E004E0108 /* postinstall-logger in Resources */,
637CEBC12A30C9E700EFA3E9 /* Localizable.xcstrings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
4 changes: 2 additions & 2 deletions Nudge/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.1.14</string>
<string>1.1.15</string>
<key>CFBundleVersion</key>
<string>1.1.14</string>
<string>1.1.15</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
Expand Down
51 changes: 51 additions & 0 deletions Nudge/Scripts/postinstall-launchagent
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#
# Copyright 2021-Present Erik Gomez.
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# If you change your agent file name, update the following line
launch_agent_plist_name='com.github.macadmins.Nudge.plist'

# Base paths
launch_agent_base_path='Library/LaunchAgents/'

# Load agent if installing to a running system
if [[ $3 == "/" ]] ; then
# Fail the install if the admin forgets to change their paths and they don't exist.
if [ ! -e "$3/${launch_agent_base_path}${launch_agent_plist_name}" ]; then
echo "LaunchAgent missing, exiting"
exit 1
fi

# Current console user information
console_user=$(/usr/bin/stat -f "%Su" /dev/console)
console_user_uid=$(/usr/bin/id -u "$console_user")

# Only enable the LaunchAgent if there is a user logged in, otherwise rely on built in LaunchAgent behavior
if [[ -z "$console_user" ]]; then
echo "Did not detect user"
elif [[ "$console_user" == "loginwindow" ]]; then
echo "Detected Loginwindow Environment"
elif [[ "$console_user" == "_mbsetupuser" ]]; then
echo "Detect SetupAssistant Environment"
elif [[ "$console_user" == "root" ]]; then
echo "Detect root as currently logged-in user"
else
# Unload the agent so it can be triggered on re-install
/bin/launchctl asuser "${console_user_uid}" /bin/launchctl unload -w "$3${launch_agent_base_path}${launch_agent_plist_name}"
# Kill Nudge just in case (say someone manually opens it and not launched via launchagent
/usr/bin/killall Nudge
# Load the launch agent
/bin/launchctl asuser "${console_user_uid}" /bin/launchctl load -w "$3${launch_agent_base_path}${launch_agent_plist_name}"
fi
fi
34 changes: 34 additions & 0 deletions Nudge/Scripts/postinstall-logger
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#
# Copyright 2021-Present Erik Gomez.
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# If you change your agent file name, update the following line
launch_daemon_plist_name='com.github.macadmins.Nudge.logger.plist'

# Base paths
launch_daemon_base_path='Library/LaunchDaemons/'

# Load agent if installing to a running system
if [[ $3 == "/" ]] ; then
# Fail the install if the admin forgets to change their paths and they don't exist.
if [ ! -e "$3/${launch_daemon_base_path}${launch_daemon_plist_name}" ]; then
echo "LaunchDaemon missing, exiting"
exit 1
fi

# Unload the agent so it can be triggered on re-install
/bin/launchctl unload -w "$3${launch_daemon_base_path}${launch_daemon_plist_name}"
# Load the launch agent
/bin/launchctl load -w "$3${launch_daemon_base_path}${launch_daemon_plist_name}"
fi
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/bin/zsh
#
# Copyright 2021-Present Erik Gomez.
#
Expand Down
31 changes: 25 additions & 6 deletions Nudge/UI/Common/DeferView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,32 @@ struct DeferView: View {
LoggerUtilities().logUserDeferrals()
UIUtilities().userInitiatedExit()
}

private var limitRange: ClosedRange<Date> {
let windowTime = [ "approachingWindowTime": UserExperienceVariables.approachingWindowTime,
"imminentWindowTime": UserExperienceVariables.imminentWindowTime ]
let daysToAdd = appState.daysRemaining > 0 ? appState.daysRemaining - (windowTime[UserExperienceVariables.calendarDeferralUnit] ?? UserExperienceVariables.imminentWindowTime / 24) : 0
// Do not let the user defer past the point of the windowTime
return DateManager().getCurrentDate()...Calendar.current.date(byAdding: .day, value: daysToAdd, to: DateManager().getCurrentDate())!
// Ensure the current date is consistently used throughout the calculation.
let currentDate = DateManager().getCurrentDate()

// Calculate the window time in days based on the UserExperienceVariables.calendarDeferralUnit.
let windowTimeInDays: Int
switch UserExperienceVariables.calendarDeferralUnit {
case "approachingWindowTime":
windowTimeInDays = UserExperienceVariables.approachingWindowTime / 24
case "imminentWindowTime":
windowTimeInDays = UserExperienceVariables.imminentWindowTime / 24
default:
windowTimeInDays = UserExperienceVariables.imminentWindowTime / 24 // Default or fallback case
}

// Calculate daysToAdd ensuring it's not negative.
// It subtracts the windowTimeInDays from appState.daysRemaining, falling back to 0 if daysRemaining is negative.
let daysToAdd = max(appState.daysRemaining - windowTimeInDays, 0)

// Safely calculate the upper bound date by adding daysToAdd to the current date.
guard let upperBoundDate = Calendar.current.date(byAdding: .day, value: daysToAdd, to: currentDate) else {
fatalError("Could not calculate the upper bound date.") // Consider handling this more gracefully in production code.
}

return currentDate...upperBoundDate
}
}

Expand Down
21 changes: 21 additions & 0 deletions build_assets/postinstall-essentials
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh
#
# Copyright 2021-Present Erik Gomez.
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Only run if on a running system
if [[ $3 == "/" ]] ; then
/bin/zsh --no-rcs -c '/Applications/Utilities/Nudge.app/Contents/Resources/postinstall-nudge'
/bin/zsh --no-rcs -c '/Applications/Utilities/Nudge.app/Contents/Resources/postinstall-launchagent'
fi
38 changes: 5 additions & 33 deletions build_assets/postinstall-launchagent
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/zsh
#!/bin/sh
#
# Copyright 2021-Present Erik Gomez.
#
Expand All @@ -14,39 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# If you change your agent file name, update the following line
launch_agent_plist_name='com.github.macadmins.Nudge.plist'

# Base paths
launch_agent_base_path='Library/LaunchAgents/'

# Load agent if installing to a running system
# Only run if on a running system
if [[ $3 == "/" ]] ; then
# Fail the install if the admin forgets to change their paths and they don't exist.
if [ ! -e "$3/${launch_agent_base_path}${launch_agent_plist_name}" ]; then
echo "LaunchAgent missing, exiting"
exit 1
fi

# Current console user information
console_user=$(/usr/bin/stat -f "%Su" /dev/console)
console_user_uid=$(/usr/bin/id -u "$console_user")

# Only enable the LaunchAgent if there is a user logged in, otherwise rely on built in LaunchAgent behavior
if [[ -z "$console_user" ]]; then
echo "Did not detect user"
elif [[ "$console_user" == "loginwindow" ]]; then
echo "Detected Loginwindow Environment"
elif [[ "$console_user" == "_mbsetupuser" ]]; then
echo "Detect SetupAssistant Environment"
elif [[ "$console_user" == "root" ]]; then
echo "Detect root as currently logged-in user"
if [ -f '/Applications/Utilities/Nudge.app/Contents/Resources/postinstall-launchagent' ]; then
/bin/zsh --no-rcs -c '/Applications/Utilities/Nudge.app/Contents/Resources/postinstall-launchagent'
else
# Unload the agent so it can be triggered on re-install
/bin/launchctl asuser "${console_user_uid}" /bin/launchctl unload -w "$3${launch_agent_base_path}${launch_agent_plist_name}"
# Kill Nudge just in case (say someone manually opens it and not launched via launchagent
/usr/bin/killall Nudge
# Load the launch agent
/bin/launchctl asuser "${console_user_uid}" /bin/launchctl load -w "$3${launch_agent_base_path}${launch_agent_plist_name}"
echo "File does not exist: Please ensure Nudge is installed prior to installation of these packages"
fi
fi
23 changes: 6 additions & 17 deletions build_assets/postinstall-logger
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/zsh
#!/bin/sh
#
# Copyright 2021-Present Erik Gomez.
#
Expand All @@ -14,22 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# If you change your agent file name, update the following line
launch_daemon_plist_name='com.github.macadmins.Nudge.logger.plist'

# Base paths
launch_daemon_base_path='Library/LaunchDaemons/'

# Load agent if installing to a running system
# Only run if on a running system
if [[ $3 == "/" ]] ; then
# Fail the install if the admin forgets to change their paths and they don't exist.
if [ ! -e "$3/${launch_daemon_base_path}${launch_daemon_plist_name}" ]; then
echo "LaunchDaemon missing, exiting"
exit 1
if [ -f '/Applications/Utilities/Nudge.app/Contents/Resources/postinstall-logger' ]; then
/bin/zsh --no-rcs -c '/Applications/Utilities/Nudge.app/Contents/Resources/postinstall-logger'
else
echo "File does not exist: Please ensure Nudge is installed prior to installation of these packages"
fi

# Unload the agent so it can be triggered on re-install
/bin/launchctl unload -w "$3${launch_daemon_base_path}${launch_daemon_plist_name}"
# Load the launch agent
/bin/launchctl load -w "$3${launch_daemon_base_path}${launch_daemon_plist_name}"
fi
20 changes: 20 additions & 0 deletions build_assets/postinstall-nudge
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh
#
# Copyright 2021-Present Erik Gomez.
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Only run if on a running system
if [[ $3 == "/" ]] ; then
/bin/zsh --no-rcs -c '/Applications/Utilities/Nudge.app/Contents/Resources/postinstall-nudge'
fi
Loading

0 comments on commit ca0df33

Please sign in to comment.