1
0
Fork 0

Merge branch 'devel' of https://github.com/arangodb/arangodb into devel

This commit is contained in:
Jan Steemann 2016-10-12 17:00:25 +02:00
commit ed132992ea
29 changed files with 377 additions and 52 deletions

View File

@ -8,7 +8,7 @@ For a full example of sessions with authentication and registration see the exam
!SECTION Creating an authenticator
`auth([options]): Authenticator`
`createAuth([options]): Authenticator`
Creates an authenticator.

View File

@ -0,0 +1,264 @@
!CHAPTER OAuth 2.0
`const createOAuth2Client = require('@arangodb/foxx/oauth2');`
The OAuth2 module provides abstractions over OAuth2 providers like Facebook, GitHub and Google.
**Examples**
The following extends the [user management example](Users.md):
```js
const crypto = require('@arangodb/crypto');
const router = createRouter();
const oauth2 = createOAuth2Client({
// We'll use Facebook for this example
authEndpoint: 'https://www.facebook.com/dialog/oauth',
tokenEndpoint: 'https://graph.facebook.com/oauth/access_token',
activeUserEndpoint: 'https://graph.facebook.com/v2.0/me',
clientId: 'keyboardcat',
clientSecret: 'keyboardcat'
});
module.context.use('/oauth2', router);
// See the user management example for setting up the
// sessions and users objects used in this example
router.use(sessions);
router.post('/auth', function (req, res) {
const csrfToken = crypto.genRandomAlphaNumbers(32);
const url = req.reverse('oauth2_callback', {csrfToken});
const redirect_uri = req.makeAbsolute(url);
// Set CSRF cookie for five minutes
res.cookie('oauth2_csrf_token', csrfToken, {ttl: 60 * 5});
// Redirect to the provider's authorization URL
res.redirect(303, oauth2.getAuthUrl(url));
});
router.get('/auth', function (req, res) {
// Some providers pass errors as query parameter
if (req.queryParams.error) {
res.throw(500, `Provider error: ${req.queryParams.error}`)
}
// Make sure CSRF cookie matches the URL
const expectedToken = req.cookie('oauth2_csrf_token');
if (!expectedToken || req.queryParams.csrfToken !== expectedToken) {
res.throw(400, 'CSRF mismatch.');
}
// Make sure the URL contains a grant token
if (!req.queryParams.code) {
res.throw(400, 'Provider did not pass grant token.');
}
// Reconstruct the redirect_uri used for the grant token
const url = req.reverse('oauth2_callback');
const redirect_uri = req.makeAbsolute(url);
// Fetch an access token from the provider
const authData = oauth2.exchangeGrantToken(
req.queryParams.code,
redirect_uri
);
const facebookToken = authData.access_token;
// Fetch the active user's profile info
const profile = oauth2.fetchActiveUser(facebookToken);
const facebookId = profile.id;
// Try to find an existing user with the user ID
// (this requires the users collection)
let user = users.firstExample({facebookId});
if (user) {
// Update the access_token if it has changed
if (user.facebookToken !== facebookToken) {
users.update(user, {facebookToken});
}
} else {
// Create a new user document
user = {
username: `fb:${facebookId}`,
facebookId,
access_token
}
const meta = users.save(user);
Object.assign(user, meta);
}
// Log the user in (this requires the session middleware)
req.session.uid = user._key;
req.session.access_token = authData.access_token;
req.sessionStorage.save(req.session);
// Redirect to the default route
res.redirect(303, req.makeAbsolute('/'));
}, 'oauth2_callback')
.queryParam('error', joi.string().optional())
.queryParam('csrfToken', joi.string().optional())
.queryParam('code', joi.string().optional());
```
!SECTION Creating an OAuth2 client
`createOAuth2Client(options): OAuth2Client`
Creates an OAuth2 client.
**Arguments**
* **options**: `Object`
An object with the following properties:
* **authEndpoint**: `string`
The fully-qualified URL of the provider's [authorization endpoint](http://tools.ietf.org/html/rfc6749#section-3.1).
* **tokenEndpoint**: `string`
The fully-qualified URL of the provider's [token endpoint](http://tools.ietf.org/html/rfc6749#section-3.2).
* **refreshEndpoint**: `string` (optional)
The fully-qualified URL of the provider's [refresh token endpoint](http://tools.ietf.org/html/rfc6749#section-6).
* **activeUserEndpoint**: `string` (optional)
The fully-qualified URL of the provider's endpoint for fetching details about the current user.
* **clientId**: `string`
The application's *Client ID* (or *App ID*) for the provider.
* **clientSecret**: `string`
The application's *Client Secret* (or *App Secret*) for the provider.
Returns an OAuth2 client for the given provider.
!SUBSECTION Setting up OAuth2 for Facebook
If you want to use Facebook as the OAuth2 provider, use the following options:
* *authEndpoint*: `https://www.facebook.com/dialog/oauth`
* *tokenEndpoint*: `https://graph.facebook.com/oauth/access_token`
* *activeUserEndpoint*: `https://graph.facebook.com/v2.0/me`
You also need to obtain a client ID and client secret from Facebook:
1. Create a regular account at [Facebook](https://www.facebook.com) or use an existing account you own.
2. Visit the [Facebook Developers](https://developers.facebook.com) page.
3. Click on *Apps* in the menu, then select *Register as a Developer* (the only option) and follow the instructions provided. You may need to verify your account by phone.
4. Click on *Apps* in the menu, then select *Create a New App* and follow the instructions provided.
5. Open the app dashboard, then note down the *App ID* and *App Secret*. The secret may be hidden by default.
6. Click on *Settings*, then *Advanced* and enter one or more *Valid OAuth redirect URIs*. At least one of them must match your *redirect_uri* later. Don't forget to save your changes.
7. Set the option *clientId* to the *App ID* and the option *clientSecret* to the *App Secret*.
!SUBSECTION Setting up OAuth2 for GitHub
If you want to use GitHub as the OAuth2 provider, use the following options:
* *authEndpoint*: `https://github.com/login/oauth/authorize?scope=user`
* *tokenEndpoint*: `https://github.com/login/oauth/access_token`
* *activeUserEndpoint*: `https://api.github.com/user`
You also need to obtain a client ID and client secret from GitHub:
1. Create a regular account at [GitHub](https://github.com) or use an existing account you own.
2. Go to [Account Settings > Applications > Register new application](https://github.com/settings/applications/new).
3. Provide an *authorization callback URL*. This must match your *redirect_uri* later.
4. Fill in the other required details and follow the instructions provided.
5. Open the application page, then note down the *Client ID* and *Client Secret*.
6. Set the option *clientId* to the *Client ID* and the option *clientSecret* to the *Client Secret*.
!SUBSECTION Setting up OAuth2 for Google
If you want to use Google as the OAuth2 provider, use the following options:
* *authEndpoint*: `https://accounts.google.com/o/oauth2/auth?access_type=offline&scope=profile`
* *tokenEndpoint*: `https://accounts.google.com/o/oauth2/token`
* *activeUserEndpoint*: `https://www.googleapis.com/plus/v1/people/me`
You also need to obtain a client ID and client secret from Google:
1. Create a regular account at [Google](https://www.google.com) or use an existing account you own.
2. Visit the [Google Developers Console](https://console.developers.google.com).
3. Click on *Create Project*, then follow the instructions provided.
4. When your project is ready, open the project dashboard, then click on *Enable an API*.
5. Enable the *Google+ API* to allow your app to distinguish between different users.
6. Open the *Credentials* page and click *Create new Client ID*, then follow the instructions provided. At least one *Authorized Redirect URI* must match your *redirect_uri* later. At least one *Authorized JavaScript Origin* must match your app's fully-qualified domain.
7. When the Client ID is ready, note down the *Client ID* and *Client secret*.
8. Set the option *clientId* to the *Client ID* and the option *clientSecret* to the *Client secret*.
!SECTION Get the authorization URL
`oauth2.getAuthUrl(redirect_uri, args): string`
Generates the authorization URL for the authorization endpoint.
**Arguments**
* **redirect_uri**: `string`
The fully-qualified URL of your application's OAuth2 callback.
* **args**: (optional)
An object with any of the following properties:
* **response_type**: `string` (Default: `"code"`)
See [RFC 6749](http://tools.ietf.org/html/rfc6749).
Returns a fully-qualified URL for the authorization endpoint of the provider by appending the client ID and any additional arguments from *args* to the *authEndpoint*.
!SECTION Exchange a grant code for an access token
`oauth2.exchangeGrantToken(code, redirect_uri)`
Exchanges a grant code for an access token.
Performs a *POST* response to the *tokenEndpoint*.
Throws an exception if the remote server responds with an empty response body.
**Arguments**
* **code**: `string`
A grant code returned by the provider's authorization endpoint.
* **redirect_uri**: `string`
The original callback URL with which the code was requested.
* **args**: `Object` (optional)
An object with any of the following properties:
* **grant_type**: `string` (Default: `"authorization_code"`)
See [RFC 6749](http://tools.ietf.org/html/rfc6749).
Returns the parsed response object.
!SECTION Fetch the active user
`oauth2.fetchActiveUser(access_token): Object`
Fetches details of the active user.
Performs a *GET* response to the *activeUserEndpoint*.
Throws an exception if the remote server responds with an empty response body.
Also throws an exception if the *activeUserEndpoint* is not configured.
**Arguments**
* **access_token**: `string`
An OAuth2 access token as returned by *exchangeGrantToken*.
Returns the parsed response object.
**Examples**
```js
const authData = oauth2.exchangeGrantToken(code, redirect_uri);
const userData = oauth2.fetchActiveUser(authData.access_token);
```

View File

@ -106,7 +106,7 @@
* [User management](Foxx/Users.md)
* [Related modules](Foxx/Modules.md)
* [Authentication](Foxx/Auth.md)
# * [OAuth 2.0](Foxx/OAuth2.md)
* [OAuth 2.0](Foxx/OAuth2.md)
* [Transactions](Transactions/README.md)
* [Transaction invocation](Transactions/TransactionInvocation.md)
* [Passing parameters](Transactions/Passing.md)

View File

@ -1,4 +0,0 @@
!CHAPTER The OAuth2 module
TODO

View File

@ -778,15 +778,15 @@ Section "-Core installation"
;Create shortcuts
CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Arango Shell.lnk" "$INSTDIR\bin\arangosh.exe" '' '$INSTDIR\resources\Icons\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Arango Server.lnk" "$INSTDIR\bin\arangod.exe" '' '$INSTDIR\resources\Icons\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Arango Shell.lnk" "$INSTDIR\usr\bin\arangosh.exe" '' '$INSTDIR\resources\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Arango Server.lnk" "$INSTDIR\usr\sbin\arangod.exe" '' '$INSTDIR\resources\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
;Read a value from an InstallOptions INI file
StrCmp "0" "$INSTALL_DESKTOP" noDesktopIcon
CreateShortCut "$DESKTOP\Arango Shell.lnk" "$INSTDIR\bin\arangosh.exe" '' '$INSTDIR\resources\Icons\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$DESKTOP\Arango Management Interface.lnk" "http://127.0.0.1:8529" '' '$INSTDIR\resources\Icons\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$DESKTOP\Arango Shell.lnk" "$INSTDIR\bin\arangosh.exe" '' '$INSTDIR\resources\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$DESKTOP\Arango Management Interface.lnk" "http://127.0.0.1:8529" '' '$INSTDIR\resources\arangodb.ico' '0' SW_SHOWMAXIMIZED
noDesktopIcon:
; Write special uninstall registry entries
@ -810,7 +810,7 @@ Section "-Core installation"
System::Call 'Kernel32::SetEnvironmentVariable(t, t)i ("ARANGODB_DEFAULT_ROOT_PASSWORD", "$PASSWORD").r0'
StrCmp $0 0 error
ExecWait "$INSTDIR\bin\arangod.exe --database.init-database"
ExecWait "$INSTDIR\usr\sbin\arangod.exe --database.init-database"
Goto done
error:
MessageBox MB_OK "Failed to initialize database password."
@ -819,7 +819,7 @@ Section "-Core installation"
StrCmp $TRI_INSTALL_TYPE 'Service' 0 nothing
SimpleSC::StopService '${TRI_SVC_NAME}' 0 30
SimpleSC::RemoveService '${TRI_SVC_NAME}'
SimpleSC::InstallService '${TRI_SVC_NAME}' '${TRI_SVC_NAME}' '16' '2' '"$INSTDIR\bin\arangod.exe" --start-service' '' '' ''
SimpleSC::InstallService '${TRI_SVC_NAME}' '${TRI_SVC_NAME}' '16' '2' '"$INSTDIR\usr\sbin\arangod.exe" --start-service' '' '' ''
SimpleSC::SetServiceDescription '${TRI_SVC_NAME}' '${TRI_FRIENDLY_SVC_NAME}'
SimpleSC::StartService '${TRI_SVC_NAME}' '' 30
Call WaitForServiceUp
@ -833,7 +833,7 @@ Function .onInstSuccess
FunctionEnd
Section "-Add to path"
Push $INSTDIR\bin
Push $INSTDIR\usr\bin
StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath
StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0
Call AddToPath
@ -1182,9 +1182,9 @@ Section "Uninstall"
SimpleSC::GetServiceBinaryPath '${TRI_SVC_NAME}'
Pop $0 ; returns an errorcode (<>0) otherwise success (0)
Pop $1 ; returns the binary path of the service
; $1 should contain '"$INSTDIR\bin\arangod.exe" --start-service' - if $INSTDIR is equal
; $1 should contain '"$INSTDIR\usr\sbin\arangod.exe" --start-service' - if $INSTDIR is equal
; to our $INSTDIR uninstall the service - else its another installation and we jump to Done instead.
StrCmp $1 '"$INSTDIR\bin\arangod.exe" --start-service' '' Done
StrCmp $1 '"$INSTDIR\usr\sbin\arangod.exe" --start-service' '' Done
DetailPrint 'Shutting down Service'
SimpleSC::StopService '${TRI_SVC_NAME}' 0 30
SimpleSC::RemoveService '${TRI_SVC_NAME}'
@ -1275,7 +1275,7 @@ Section "Uninstall"
${EndIf}
DeleteRegKey HKLM "${TRI_UNINSTALL_REG_PATH}"
Push $INSTDIR\bin
Push $INSTDIR\usr\bin
StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0
Call un.RemoveFromPath
doNotRemoveFromPath:

View File

@ -638,15 +638,14 @@ Section "-Core installation"
;Create shortcuts
CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Arango Shell.lnk" "$INSTDIR\bin\arangosh.exe" '' '$INSTDIR\resources\Icons\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Arango Server.lnk" "$INSTDIR\bin\arangod.exe" '' '$INSTDIR\resources\Icons\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Arango Shell.lnk" "$INSTDIR\usr\bin\arangosh.exe" '' '$INSTDIR\resources\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
;Read a value from an InstallOptions INI file
StrCmp "0" "$INSTALL_DESKTOP" noDesktopIcon
CreateShortCut "$DESKTOP\Arango Shell.lnk" "$INSTDIR\bin\arangosh.exe" '' '$INSTDIR\resources\Icons\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$DESKTOP\Arango Management Interface.lnk" "http://127.0.0.1:8529" '' '$INSTDIR\resources\Icons\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$DESKTOP\Arango Shell.lnk" "$INSTDIR\usr\bin\arangosh.exe" '' '$INSTDIR\resources\arangodb.ico' '0' SW_SHOWMAXIMIZED
CreateShortCut "$DESKTOP\Arango Management Interface.lnk" "http://127.0.0.1:8529" '' '$INSTDIR\resources\arangodb.ico' '0' SW_SHOWMAXIMIZED
noDesktopIcon:
; Write special uninstall registry entries
@ -668,13 +667,6 @@ Section "-Core installation"
!insertmacro MUI_STARTMENU_WRITE_END
System::Call 'Kernel32::SetEnvironmentVariable(t, t)i ("ARANGODB_DEFAULT_ROOT_PASSWORD", "$PASSWORD").r0'
StrCmp $0 0 error
ExecWait "$INSTDIR\bin\arangod.exe --database.init-database"
Goto done
error:
MessageBox MB_OK "Failed to initialize database password."
done:
@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@
SectionEnd
@ -682,7 +674,7 @@ Function .onInstSuccess
FunctionEnd
Section "-Add to path"
Push $INSTDIR\bin
Push $INSTDIR\usr\bin
StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath
StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0
Call AddToPath
@ -989,7 +981,7 @@ Section "Uninstall"
DeleteRegKey HKCU "Software\@CPACK_NSIS_PACKAGE_NAME@"
DeleteRegKey HKLM "${TRI_UNINSTALL_REG_PATH}"
Push $INSTDIR\bin
Push $INSTDIR\usr\bin
StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0
Call un.RemoveFromPath
doNotRemoveFromPath:

View File

@ -38,7 +38,7 @@
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(BIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif

View File

@ -36,7 +36,7 @@
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(SBIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif

View File

@ -37,7 +37,7 @@
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(SBIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif

View File

@ -36,7 +36,7 @@
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(SBIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif

View File

@ -37,7 +37,7 @@
#if _WIN32
#include "Basics/win-utils.h"
#define FIX_ICU_ENV TRI_FixIcuDataEnv()
#define FIX_ICU_ENV TRI_FixIcuDataEnv(SBIN_DIRECTORY)
#else
#define FIX_ICU_ENV
#endif

View File

@ -1166,6 +1166,13 @@ int ClusterInfo::createCollectionCoordinator(std::string const& databaseName,
}
if (TRI_microtime() > endTime) {
LOG_TOPIC(ERR, Logger::CLUSTER) << "Timeout in _create collection"
<< ": database: " << databaseName << ", collId:" << collectionID
<< "\njson: " << json.toString()
<< "\ntransaction sent to agency: " << transaction.toJson();
AgencyCommResult ag = ac.getValues("");
LOG_TOPIC(ERR, Logger::CLUSTER) << "Agency dump:\n"
<< ag.slice().toJson();
events::CreateCollection(name, TRI_ERROR_CLUSTER_TIMEOUT);
return setErrormsg(TRI_ERROR_CLUSTER_TIMEOUT, errorMsg);
}
@ -1270,6 +1277,12 @@ int ClusterInfo::dropCollectionCoordinator(std::string const& databaseName,
}
if (TRI_microtime() > endTime) {
LOG_TOPIC(ERR, Logger::CLUSTER) << "Timeout in _drop collection"
<< ": database: " << databaseName << ", collId:" << collectionID
<< "\ntransaction sent to agency: " << trans.toJson();
AgencyCommResult ag = ac.getValues("");
LOG_TOPIC(ERR, Logger::CLUSTER) << "Agency dump:\n"
<< ag.slice().toJson();
events::DropCollection(collectionID, TRI_ERROR_CLUSTER_TIMEOUT);
return setErrormsg(TRI_ERROR_CLUSTER_TIMEOUT, errorMsg);
}

View File

@ -103,7 +103,7 @@ static int runServer(int argc, char** argv) {
std::string name = context.binaryName();
auto options = std::make_shared<options::ProgramOptions>(
argv[0], "Usage: " + name + " [<options>]", "For more information use:");
argv[0], "Usage: " + name + " [<options>]", "For more information use:", SBIN_DIRECTORY);
application_features::ApplicationServer server(options, SBIN_DIRECTORY);

View File

@ -47,7 +47,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangobench [<options>]", "For more information use:"));
argv[0], "Usage: arangobench [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -44,7 +44,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangodump [<options>]", "For more information use:"));
argv[0], "Usage: arangodump [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -45,7 +45,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangoimp [<options>]", "For more information use:"));
argv[0], "Usage: arangoimp [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -45,7 +45,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangorestore [<options>]", "For more information use:"));
argv[0], "Usage: arangorestore [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -51,7 +51,7 @@ int main(int argc, char* argv[]) {
std::string name = context.binaryName();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: " + name + " [<options>]", "For more information use:"));
argv[0], "Usage: " + name + " [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -42,7 +42,7 @@ int main(int argc, char* argv[]) {
context.installHup();
std::shared_ptr<options::ProgramOptions> options(new options::ProgramOptions(
argv[0], "Usage: arangovpack [<options>]", "For more information use:"));
argv[0], "Usage: arangovpack [<options>]", "For more information use:", BIN_DIRECTORY));
ApplicationServer server(options, BIN_DIRECTORY);

View File

@ -12,7 +12,7 @@ endif()
# Global macros ----------------------------------------------------------------
macro (generate_root_config name)
FILE(READ ${PROJECT_SOURCE_DIR}/etc/arangodb3/${name}.conf.in FileContent)
STRING(REPLACE "@PKGDATADIR@" "@ROOTDIR@/share/arangodb3"
STRING(REPLACE "@PKGDATADIR@" "@ROOTDIR@/${CMAKE_INSTALL_DATAROOTDIR_ARANGO}"
FileContent "${FileContent}")
STRING(REPLACE "@LOCALSTATEDIR@" "@ROOTDIR@/var"
FileContent "${FileContent}")

View File

@ -47,7 +47,7 @@ install (FILES "${SSL_EAY_RELEASE_DLL}" DESTINATION "${CMAKE_INSTALL_BINDIR}/" C
set (ICON_PATH "${W_INSTALL_FILES}/Icons/")
install(DIRECTORY "${ICON_PATH}" DESTINATION "resources")
file(TO_NATIVE_PATH "resources/Icons/arangodb.ico" RELATIVE_ARANGO_ICON)
file(TO_NATIVE_PATH "resources/arangodb.ico" RELATIVE_ARANGO_ICON)
file(TO_NATIVE_PATH "${ICON_PATH}arangodb.bmp" ARANGO_IMG)
file(TO_NATIVE_PATH "${ICON_PATH}/arangodb.ico" ARANGO_ICON)

View File

@ -37,6 +37,7 @@
<% } %>
<% if (scaleProperties.coordsPending && scaling === true) { %>
<span class="warning"><span> <%= scaleProperties.coordsPending %> </span><i class="fa fa-circle-o-notch fa-spin"></i></span>
<button class="abortClusterPlan button-navbar button-default">Abort</button>
<% } %>
</div>
</div>
@ -112,6 +113,7 @@
<% } %>
<% if (scaleProperties.dbsPending && scaling === true) { %>
<span class="warning"><span> <%= scaleProperties.dbsPending %> </span><i class="fa fa-circle-o-notch fa-spin"></i></span>
<button class="abortClusterPlan button-navbar button-default">Abort</button>
<% } %>
</div>

View File

@ -16,6 +16,7 @@
'click #removeCoord': 'removeCoord',
'click #addDBs': 'addDBs',
'click #removeDBs': 'removeDBs',
'click .abortClusterPlan': 'abortClusterPlanModal',
'keyup #plannedCoords': 'checkKey',
'keyup #plannedDBs': 'checkKey'
},
@ -225,13 +226,45 @@
});
},
abortClusterPlanModal: function () {
var buttons = []; var tableContent = [];
tableContent.push(
window.modalView.createReadOnlyEntry(
'plan-abort-button',
'Caution',
'You are aborting the planned cluster plan. All pending servers are going to be removed. Continue?',
undefined,
undefined,
false,
/[<>&'"]/
)
);
buttons.push(
window.modalView.createSuccessButton('Yes', this.abortClusterPlan.bind(this))
);
window.modalView.show('modalTable.ejs', 'Modify Cluster Size', buttons, tableContent);
},
abortClusterPlan: function () {
window.modalView.hide();
try {
var coords = JSON.parse($('#infoCoords > .positive > span').text());
var dbs = JSON.parse($('#infoDBs > .positive > span').text());
this.setCoordSize(coords);
this.setDBsSize(dbs);
} catch (ignore) {
console.log(ignore);
arangoHelper.arangoError('Plan', 'Could not abort Cluster Plan');
}
},
renderCounts: function (scale, callback) {
var self = this;
var renderFunc = function (id, ok, pending, error) {
var string = '<span class="positive"><span>' + ok + '</span><i class="fa fa-check-circle"></i></span>';
if (pending && scale === true) {
string = string + '<span class="warning"><span>' + pending + '</span><i class="fa fa-circle-o-notch fa-spin"></i></span>';
string = string + '<span class="warning"><span>' + pending +
'</span><i class="fa fa-circle-o-notch fa-spin"></i></span><button class="abortClusterPlan button-navbar button-default">Abort</button>';
}
if (error) {
string = string + '<span class="negative"><span>' + error + '</span><i class="fa fa-exclamation-circle"></i></span>';

View File

@ -195,6 +195,16 @@
}
}
%default {
background-color: $c-white;
&:hover,
&:focus {
background-color: $c-neutral;
color: $c-white;
}
}
%icon-neutral {
color: $c-neutral;

View File

@ -58,6 +58,10 @@
@extend %info;
}
.button-navbar {
margin-top: -5px;
}
[class^='button-']:disabled,
button.disabled,
[class*=' button-']:disabled {
@ -86,6 +90,12 @@ button.disabled,
@extend %neutral;
}
.button-default {
@extend %btn;
@extend %default;
color: $c-black;
}
.addButton {
@extend %clickable;
@extend %icon-positive;

View File

@ -1464,6 +1464,7 @@ function startInstanceAgency (instanceInfo, protocol, options,
for (let i = 0; i < N; i++) {
let instanceArgs = _.clone(addArgs);
instanceArgs['log.file'] = fs.join(rootDir, 'log' + String(i));
instanceArgs['agency.activate'] = 'true';
instanceArgs['agency.size'] = String(N);
instanceArgs['agency.pool-size'] = String(N);

View File

@ -102,6 +102,7 @@ class ProgramOptions {
ProgramOptions(char const* progname, std::string const& usage,
std::string const& more,
const char *binaryPath,
TerminalWidthFuncType const& terminalWidth = TRI_ColumnsWidth,
SimilarityFuncType const& similarity = TRI_Levenshtein)
: _progname(progname),
@ -111,7 +112,8 @@ class ProgramOptions {
_similarity(similarity),
_processingResult(),
_sealed(false),
_overrideOptions(false) {
_overrideOptions(false),
_binaryPath(binaryPath){
// find progname wildcard in string
size_t const pos = _usage.find(ARANGODB_PROGRAM_OPTIONS_PROGNAME);
@ -126,7 +128,7 @@ class ProgramOptions {
// sets a value translator
void setTranslator(
std::function<std::string(std::string const&)> translator) {
std::function<std::string(std::string const&, char const*)> translator) {
_translator = translator;
}
@ -357,7 +359,7 @@ class ProgramOptions {
return true;
}
std::string result = option.parameter->set(_translator(value));
std::string result = option.parameter->set(_translator(value, _binaryPath));
if (!result.empty()) {
// parameter validation failed
@ -621,7 +623,9 @@ class ProgramOptions {
// allow or disallow overriding already set options
bool _overrideOptions;
// translate input values
std::function<std::string(std::string const&)> _translator;
std::function<std::string(std::string const&, char const*)> _translator;
// directory of this binary
char const* _binaryPath;
};
}
}

View File

@ -23,7 +23,7 @@
#include "Translator.h"
#include "Basics/tri-strings.h"
#include "Basics/files.h"
std::string arangodb::options::EnvironmentTranslator(std::string const& value) {
std::string arangodb::options::EnvironmentTranslator(std::string const& value, const char *binaryPath) {
if (value.empty()) {
return value;
}
@ -57,7 +57,7 @@ std::string arangodb::options::EnvironmentTranslator(std::string const& value) {
if (v == nullptr) {
#if _WIN32
if (TRI_EqualString(k.c_str(), "ROOTDIR")) {
vv = TRI_LocateInstallDirectory();
vv = TRI_LocateInstallDirectory(binaryPath);
if (! vv.empty()) {
char c = *(vv.rbegin());

View File

@ -27,7 +27,7 @@
namespace arangodb {
namespace options {
std::string EnvironmentTranslator(std::string const& value);
std::string EnvironmentTranslator(std::string const& value, const char* binaryPath);
}
}