mirror of https://github.com/keeweb/keeweb
set app folder permissions to root on mac
parent
e5bfa59c50
commit
857593232c
|
@ -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'
|
||||
|
|
|
@ -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 ¯\\_(ツ)_/¯`);
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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",
|
||||
|
|
|
@ -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.
|
@ -0,0 +1 @@
|
|||
APPLaplt
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 362 B |
|
@ -0,0 +1,5 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
|
||||
{\fonttbl}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
}
|
|
@ -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>
|
Loading…
Reference in New Issue