set app folder permissions to root on mac

This commit is contained in:
antelle 2017-06-05 11:31:50 +02:00
parent e5bfa59c50
commit 857593232c
12 changed files with 357 additions and 18 deletions

View File

@ -208,6 +208,14 @@ module.exports = function(grunt) {
nonull: true,
options: { mode: '0755' }
},
'desktop-darwin-installer': {
cwd: 'package/osx/KeeWeb Installer.app',
dest: 'tmp/desktop/KeeWeb-darwin-x64/KeeWeb.app/Contents/Helpers/KeeWeb Installer.app',
src: '**',
expand: true,
nonull: true,
options: { mode: true }
},
'desktop-win32-dist-x64': {
src: 'tmp/desktop/KeeWeb.win.x64.exe',
dest: `dist/desktop/KeeWeb-${pkg.version}.win.x64.exe`,
@ -687,6 +695,7 @@ module.exports = function(grunt) {
'sign-exe:win32-build-x64',
'sign-exe:win32-build-ia32',
'copy:desktop-darwin-helper-x64',
'copy:desktop-darwin-installer',
'copy:desktop-windows-helper-ia32',
'copy:desktop-windows-helper-x64',
'codesign:app'

View File

@ -8,6 +8,7 @@ const KeyHandler = require('./comp/key-handler');
const IdleTracker = require('./comp/idle-tracker');
const PopupNotifier = require('./comp/popup-notifier');
const SingleInstanceChecker = require('./comp/single-instance-checker');
const AppRightsChecker = require('./comp/app-rights-checker');
const Alerts = require('./comp/alerts');
const Updater = require('./comp/updater');
const AuthReceiver = require('./comp/auth-receiver');
@ -36,7 +37,7 @@ ready(() => {
.then(loadRemoteConfig)
.then(ensureCanRun)
.then(showApp)
.then(autoUpdatePlugins)
.then(postInit)
.catch(e => {
appModel.appLogger.error('Error starting app', e);
});
@ -105,31 +106,44 @@ ready(() => {
}
function showApp() {
const skipHttpsWarning = localStorage.skipHttpsWarning || appModel.settings.get('skipHttpsWarning');
const protocolIsInsecure = ['https:', 'file:', 'app:'].indexOf(location.protocol) < 0;
const hostIsInsecure = location.hostname !== 'localhost';
if (protocolIsInsecure && hostIsInsecure && !skipHttpsWarning) {
Alerts.error({ header: Locale.appSecWarn, icon: 'user-secret', esc: false, enter: false, click: false,
body: Locale.appSecWarnBody1 + '<br/><br/>' + Locale.appSecWarnBody2,
buttons: [
{ result: '', title: Locale.appSecWarnBtn, error: true }
],
complete: showView
});
} else {
showView();
}
return Promise.resolve().then(() => {
const skipHttpsWarning = localStorage.skipHttpsWarning || appModel.settings.get('skipHttpsWarning');
const protocolIsInsecure = ['https:', 'file:', 'app:'].indexOf(location.protocol) < 0;
const hostIsInsecure = location.hostname !== 'localhost';
if (protocolIsInsecure && hostIsInsecure && !skipHttpsWarning) {
return new Promise(resolve => {
Alerts.error({
header: Locale.appSecWarn, icon: 'user-secret', esc: false, enter: false, click: false,
body: Locale.appSecWarnBody1 + '<br/><br/>' + Locale.appSecWarnBody2,
buttons: [
{result: '', title: Locale.appSecWarnBtn, error: true}
],
complete: () => {
showView();
resolve();
}
});
});
} else {
showView();
}
});
}
function autoUpdatePlugins() {
function postInit() {
Updater.init();
SingleInstanceChecker.init();
AppRightsChecker.init();
setTimeout(() => PluginManager.runAutoUpdate(), Timeouts.AutoUpdatePluginsAfterStart);
}
function showView() {
appModel.prepare();
new AppView({ model: appModel }).render();
Updater.init();
SingleInstanceChecker.init();
logStartupTime();
}
function logStartupTime() {
const time = Math.round(performance.now());
appModel.appLogger.info(`Started in ${time}ms ¯\\_(ツ)_/¯`);
}

View File

@ -0,0 +1,77 @@
const FeatureDetector = require('../util/feature-detector');
const Alerts = require('../comp/alerts');
const AppSettingsModel = require('../models/app-settings-model');
const Launcher = require('./launcher');
const Locale = require('../util/locale');
const AppRightsChecker = {
AppPath: '/Applications/KeeWeb.app',
init() {
if (!FeatureDetector.isDesktop || !FeatureDetector.isMac) {
return;
}
if (AppSettingsModel.instance.get('skipFolderRightsWarning')) {
return;
}
if (!Launcher.getAppPath().startsWith(this.AppPath)) {
return;
}
this.needRunInstaller(needRun => {
if (needRun) {
this.showAlert();
this.runInstaller();
}
});
},
needRunInstaller(callback) {
Launcher.statFile(this.AppPath, stat => {
const folderIsRoot = stat && stat.uid === 0;
callback(!folderIsRoot);
});
},
showAlert() {
const command = 'sudo shown -R root ' + this.AppPath;
this.alert = Alerts.alert({
icon: 'lock',
header: Locale.appRightsAlert,
body: Locale.appRightsAlertBody1.replace('{}', `<code>${this.AppPath}</code>`) +
'<br/>' + Locale.appRightsAlertBody2 + `: <pre>${command}</pre>`,
buttons: [
{result: 'skip', title: Locale.alertDoNotAsk, error: true},
Alerts.buttons.ok
],
success: (result) => {
if (result === 'skip') {
this.dontAskAnymore();
}
this.alert = null;
}
});
},
runInstaller() {
Launcher.spawn({
cmd: this.AppPath + '/Contents/Helpers/KeeWeb\ Installer.app/Contents/MacOS/applet',
complete: () => {
this.needRunInstaller(needRun => {
if (this.alert && !needRun) {
this.alert.closeWithResult('cancel');
}
});
}
});
},
dontAskAnymore() {
this.needRunInstaller(needRun => {
if (needRun) {
AppSettingsModel.instance.set('skipFolderRightsWarning', true);
}
});
}
};
module.exports = AppRightsChecker;

View File

@ -54,6 +54,7 @@
"alertSignIn": "Sign In",
"alertCopy": "Copy",
"alertClose": "Close",
"alertDoNotAsk": "Don't ask me anymore",
"appBeta": "WARNING: beta version, only for preview",
@ -290,6 +291,9 @@
"appNotSupportedError": "Your browser is not supported.",
"appTabWarn": "Too many tabs",
"appTabWarnBody": "KeeWeb cannot be used in two browser tabs simultaneously, please close this tab.",
"appRightsAlert": "Locking app folder",
"appRightsAlertBody1": "Your {} folder is writable. We're asking you for administrator permissions, to make it writable only for administrators.",
"appRightsAlertBody2": "Don't want to give administrator permission? You can do it yourself in Terminal",
"setGenTitle": "General Settings",
"setGenUpdate": "Update",

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>applet</string>
<key>CFBundleIconFile</key>
<string>applet</string>
<key>CFBundleIdentifier</key>
<string>com.apple.ScriptEditor.id.KeeWeb-Installer</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>KeeWeb Installer</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>aplt</string>
<key>LSMinimumSystemVersionByArchitecture</key>
<dict>
<key>x86_64</key>
<string>10.6</string>
</dict>
<key>LSRequiresCarbon</key>
<true/>
<key>WindowState</key>
<dict>
<key>bundleDividerCollapsed</key>
<true/>
<key>bundlePositionOfDivider</key>
<real>0.0</real>
<key>dividerCollapsed</key>
<false/>
<key>eventLogLevel</key>
<integer>2</integer>
<key>name</key>
<string>ScriptWindowState</string>
<key>positionOfDivider</key>
<real>421</real>
<key>savedFrame</key>
<string>20 90 700 672 0 0 1280 777 </string>
<key>selectedTab</key>
<string>description</string>
</dict>
</dict>
</plist>

Binary file not shown.

View File

@ -0,0 +1 @@
APPLaplt

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

View File

@ -0,0 +1,5 @@
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
{\fonttbl}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
}

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Resources/Scripts/main.scpt</key>
<data>
hsRwl39Q/JbFKwwQ/MLvOD3Mf4Q=
</data>
<key>Resources/applet.icns</key>
<data>
VcgFWegZDTv+w0YHNMzLzFhTAZc=
</data>
<key>Resources/applet.rsrc</key>
<data>
8fN/GtxUP559toTqTl+V3wCZeoU=
</data>
<key>Resources/description.rtfd/TXT.rtf</key>
<data>
U1/ikutWmrJdAXLoU25d4KUS06c=
</data>
</dict>
<key>files2</key>
<dict>
<key>Resources/Scripts/main.scpt</key>
<dict>
<key>hash</key>
<data>
hsRwl39Q/JbFKwwQ/MLvOD3Mf4Q=
</data>
<key>hash2</key>
<data>
t7kR7hl6N/mOn8SxdBAqRDqpnWm/sWW4XJ4jYDK4U5I=
</data>
</dict>
<key>Resources/applet.icns</key>
<dict>
<key>hash</key>
<data>
VcgFWegZDTv+w0YHNMzLzFhTAZc=
</data>
<key>hash2</key>
<data>
b6dMOucVxf4qMeaTlZp/Sd18BqVBvyKlqZ4xJRQ2Gws=
</data>
</dict>
<key>Resources/applet.rsrc</key>
<dict>
<key>hash</key>
<data>
8fN/GtxUP559toTqTl+V3wCZeoU=
</data>
<key>hash2</key>
<data>
eBEutqxEKm3EiJlpx6YIakFWJU2RKjnLue7r2J/WmJo=
</data>
</dict>
<key>Resources/description.rtfd/TXT.rtf</key>
<dict>
<key>hash</key>
<data>
U1/ikutWmrJdAXLoU25d4KUS06c=
</data>
<key>hash2</key>
<data>
vGT9c0omY5YveJ9Gjv3lLYFVn64gjtcT7Nc6UAWGXh4=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^Resources/</key>
<true/>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^.*</key>
<true/>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^[^/]+$</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>