Skip to content

Fix buttons and improve handling of certificates when Safari is not the default browser #949

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

Merged
merged 19 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f43b0e4
Fix check on buttons returning the correct message
MatteoPologruto May 8, 2024
f69980a
Update certificates regardless of the default browser
MatteoPologruto May 8, 2024
f7bd6e3
Set installCerts when the certificate is installed from previous vers…
MatteoPologruto May 8, 2024
8006310
Do not set installCerts to false if the default browser is not Safari
MatteoPologruto May 8, 2024
aa02ed0
Do not ask again to update the certificate if the user refuses once
MatteoPologruto May 9, 2024
e46bfbf
Fix user script on macOS
MatteoPologruto May 9, 2024
7f4cdf6
Check for the presence of the certificate in the keychain to determin…
MatteoPologruto May 9, 2024
4285c04
Fix getExpirationDate breaking when the certificate is expired
MatteoPologruto May 9, 2024
4064541
Fix return value in case of error
MatteoPologruto May 9, 2024
cf31546
getExpirationDate rewritten to use the correct expiration field.
Xayton May 9, 2024
411d051
Separate osascript default button from the one to press
MatteoPologruto May 9, 2024
c11610b
Fix leftover buttons
MatteoPologruto May 9, 2024
9494f25
Small text fixes in the "manage certificate" dialog
Xayton May 10, 2024
d56f231
Simplify error management in getExpirationDate
Xayton May 10, 2024
8ec1efc
Fix compiler warnings and move obj-c code into a separate file.
Xayton May 10, 2024
34fae24
certInKeychain returns a bool
Xayton May 10, 2024
8854680
Fix building errors caused by objective-c files on Ubuntu and Windows
MatteoPologruto May 13, 2024
681a250
Build objective-c files only on Darwin
MatteoPologruto May 13, 2024
c461c40
Remove -ld_classic library because XCode is not up to date on the CI
MatteoPologruto May 13, 2024
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
Prev Previous commit
Next Next commit
Do not ask again to update the certificate if the user refuses once
  • Loading branch information
MatteoPologruto committed May 9, 2024
commit aa02ed0e11ed4920cda2f6eb84a9bcb840bfb8f5
30 changes: 2 additions & 28 deletions certificates/certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ import (
"math/big"
"net"
"os"
"strings"
"time"

"github.com/arduino/arduino-create-agent/utilities"
"github.com/arduino/go-paths-helper"
log "github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -270,8 +268,8 @@ func DeleteCertificates(certDir *paths.Path) {
certDir.Join("cert.cer").Remove()
}

// isExpired checks if a certificate is expired or about to expire (less than 1 month)
func isExpired() (bool, error) {
// IsExpired checks if a certificate is expired or about to expire (less than 1 month)
func IsExpired() (bool, error) {
bound := time.Now().AddDate(0, 1, 0)
dateS, err := GetExpirationDate()
if err != nil {
Expand All @@ -281,30 +279,6 @@ func isExpired() (bool, error) {
return date.Before(bound), nil
}

// PromptInstallCertsSafari prompts the user to install the HTTPS certificates if they are using Safari
func PromptInstallCertsSafari() bool {
buttonPressed := utilities.UserPrompt("display dialog \"The Arduino Agent needs a local HTTPS certificate to work correctly with Safari.\nIf you use Safari, you need to install it.\" buttons {\"Do not install\", \"Install the certificate for Safari\"} default button 2 with title \"Arduino Agent: Install certificate\"")
return strings.Contains(string(buttonPressed), "button returned:Install the certificate for Safari")
}

// PromptExpiredCerts prompts the user to update the HTTPS certificates if they are using Safari
func PromptExpiredCerts(certDir *paths.Path) {
if expired, err := isExpired(); err != nil {
log.Errorf("cannot check if certificates are expired something went wrong: %s", err)
} else if expired {
buttonPressed := utilities.UserPrompt("display dialog \"The Arduino Agent needs a local HTTPS certificate to work correctly with Safari.\nYour certificate is expired or close to expiration. Do you want to update it?\" buttons {\"Do not update\", \"Update the certificate for Safari\"} default button 2 with title \"Arduino Agent: Update certificate\"")
if strings.Contains(string(buttonPressed), "button returned:Update the certificate for Safari") {
err := UninstallCertificates()
if err != nil {
log.Errorf("cannot uninstall certificates something went wrong: %s", err)
} else {
DeleteCertificates(certDir)
GenerateAndInstallCertificates(certDir)
}
}
}
}

// GenerateAndInstallCertificates generates and installs the certificates
func GenerateAndInstallCertificates(certDir *paths.Path) {
GenerateCertificates(certDir)
Expand Down
31 changes: 27 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func loop() {
// If we are updating manually from 1.2.7 to 1.3.0 we have to uninstall the old agent manually first.
// This check will inform the user if he needs to run the uninstall first
if runtime.GOOS == "darwin" && oldInstallExists() {
utilities.UserPrompt("display dialog \"Old agent installation of the Arduino Create Agent found, please uninstall it before launching the new one\" buttons \"OK\" with title \"Error\"")
utilities.UserPrompt("Old agent installation of the Arduino Create Agent found, please uninstall it before launching the new one", "\"OK\"", "OK", "Error")
os.Exit(0)
}

Expand Down Expand Up @@ -233,7 +233,7 @@ func loop() {
log.Panicf("config.ini cannot be parsed: %s", err)
}
} else if cert.GetDefaultBrowserName() == "Safari" {
if cert.PromptInstallCertsSafari() {
if promptInstallCertsSafari() {
err = config.SetInstallCertsIni(configPath.String(), "true")
if err != nil {
log.Panicf("config.ini cannot be parsed: %s", err)
Expand Down Expand Up @@ -374,8 +374,27 @@ func loop() {
// check if the HTTPS certificates are expired or expiring and prompt the user to update them on macOS
if runtime.GOOS == "darwin" && *installCerts {
if config.CertsExist() {
cert.PromptExpiredCerts(config.GetCertificatesDir())
} else if cert.PromptInstallCertsSafari() {
certDir := config.GetCertificatesDir()
if expired, err := cert.IsExpired(); err != nil {
log.Errorf("cannot check if certificates are expired something went wrong: %s", err)
} else if expired {
buttonPressed := utilities.UserPrompt("The Arduino Agent needs a local HTTPS certificate to work correctly with Safari.\nYour certificate is expired or close to expiration. Do you want to update it?", "{\"Do not update\", \"Update the certificate for Safari\"}", "Update the certificate for Safari", "Arduino Agent: Update certificate")
if buttonPressed {
err := cert.UninstallCertificates()
if err != nil {
log.Errorf("cannot uninstall certificates something went wrong: %s", err)
} else {
cert.DeleteCertificates(certDir)
cert.GenerateAndInstallCertificates(certDir)
}
} else {
err = config.SetInstallCertsIni(configPath.String(), "false")
if err != nil {
log.Panicf("config.ini cannot be parsed: %s", err)
}
}
}
} else if promptInstallCertsSafari() {
// installing the certificates from scratch at this point should only happen if
// something went wrong during previous installation attempts
cert.GenerateAndInstallCertificates(config.GetCertificatesDir())
Expand Down Expand Up @@ -534,3 +553,7 @@ func installCertsKeyExists(filename string) (bool, error) {
}
return cfg.Section("").HasKey("installCerts"), nil
}

func promptInstallCertsSafari() bool {
return utilities.UserPrompt("The Arduino Agent needs a local HTTPS certificate to work correctly with Safari.\nIf you use Safari, you need to install it.", "{\"Do not install\", \"Install the certificate for Safari\"}", "Install the certificate for Safari", "Arduino Agent: Install certificate")
}
43 changes: 23 additions & 20 deletions systray/systray_real.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ package systray
import (
"os"
"runtime"
"strings"

"fyne.io/systray"
cert "github.com/arduino/arduino-create-agent/certificates"
Expand Down Expand Up @@ -95,38 +94,42 @@ func (s *Systray) start() {
s.updateMenuItem(mRmCrashes, config.LogsIsEmpty())
case <-mManageCerts.ClickedCh:
infoMsg := "The Arduino Agent needs a local HTTPS certificate to work correctly with Safari.\n\nYour HTTPS certificate status:\n"
buttons := "{\"Install the certificate for Safari\", \"OK\"} default button \"OK\""
buttons := "{\"OK\", \"Install the certificate for Safari\"}"
defaultButton := "Install the certificate for Safari"
certDir := config.GetCertificatesDir()
if config.CertsExist() {
expDate, err := cert.GetExpirationDate()
if err != nil {
log.Errorf("cannot get certificates expiration date, something went wrong: %s", err)
}
infoMsg = infoMsg + "- Certificate installed: Yes\n- Certificate trusted: Yes\n- Certificate expiration date: " + expDate
buttons = "{\"Uninstall the certificate for Safari\", \"OK\"} default button \"OK\""
buttons = "{\"OK\", \"Uninstall the certificate for Safari\"}"
defaultButton = "Uninstall the certificate for Safari"
pressedButton := utilities.UserPrompt(infoMsg, buttons, defaultButton, "Arduino Agent: Manage HTTPS certificate")
if pressedButton {
err := cert.UninstallCertificates()
if err != nil {
log.Errorf("cannot uninstall certificates something went wrong: %s", err)
} else {
cert.DeleteCertificates(certDir)
err = config.SetInstallCertsIni(s.currentConfigFilePath.String(), "false")
if err != nil {
log.Errorf("cannot set installCerts value in config.ini: %s", err)
}
}
s.Restart()
}
} else {
infoMsg = infoMsg + "- Certificate installed: No\n- Certificate trusted: N/A\n- Certificate expiration date: N/A"
}
pressedButton := utilities.UserPrompt("display dialog \"" + infoMsg + "\" buttons " + buttons + " with title \"Arduino Agent: Manage HTTPS certificate\"")
if strings.Contains(pressedButton, "Install the certificate for Safari") {
cert.GenerateAndInstallCertificates(certDir)
err := config.SetInstallCertsIni(s.currentConfigFilePath.String(), "true")
if err != nil {
log.Errorf("cannot set installCerts value in config.ini: %s", err)
}
s.Restart()
} else if strings.Contains(pressedButton, "Uninstall the certificate for Safari") {
err := cert.UninstallCertificates()
if err != nil {
log.Errorf("cannot uninstall certificates something went wrong: %s", err)
} else {
cert.DeleteCertificates(certDir)
err = config.SetInstallCertsIni(s.currentConfigFilePath.String(), "false")
pressedButton := utilities.UserPrompt(infoMsg, buttons, defaultButton, "Arduino Agent: Manage HTTPS certificate")
if pressedButton {
cert.GenerateAndInstallCertificates(certDir)
err := config.SetInstallCertsIni(s.currentConfigFilePath.String(), "true")
if err != nil {
log.Errorf("cannot set installCerts value in config.ini: %s", err)
}
s.Restart()
}
s.Restart()
}
case <-mPause.ClickedCh:
s.Pause()
Expand Down
6 changes: 3 additions & 3 deletions utilities/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ func VerifyInput(input string, signature string) error {
}

// UserPrompt executes an osascript and returns the pressed button
func UserPrompt(dialog string) string {
oscmd := exec.Command("osascript", "-e", dialog)
func UserPrompt(dialog string, buttons string, defaultButton string, title string) bool {
oscmd := exec.Command("osascript", "-e", "display dialog \""+dialog+"\" buttons "+buttons+" default button\""+defaultButton+"\" with title \""+title+"\"")
pressedButton, _ := oscmd.Output()
return string(pressedButton)
return strings.Contains(string(pressedButton), "button returned:"+defaultButton)
}
Loading