Merge pull request #589 from kasenvr/feature/oauth2-kalila

Feature/oauth2 kalila
This commit is contained in:
David Rowe 2020-08-05 20:18:35 +12:00 committed by GitHub
commit 1e0498aaa4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 133 additions and 37 deletions

View file

@ -414,6 +414,7 @@
"name": "group_permissions",
"type": "table",
"caption": "Permissions for Users in Groups",
"help": "For groups that are provided from WordPress you need to denote them by putting an \"@\" symbol in front of each item, e.g., \"@silver\"".
"categorize_by_key": "permissions_id",
"can_add_new_categories": true,
"can_add_new_rows": false,
@ -542,6 +543,7 @@
"name": "group_forbiddens",
"type": "table",
"caption": "Permissions Denied to Users in Groups",
"help": "For groups that are provided from WordPress you need to denote them by putting an \"@\" symbol in front of each item, e.g., \"@silver\"".
"categorize_by_key": "permissions_id",
"can_add_new_categories": true,
"can_add_new_rows": false,

View file

@ -45,6 +45,7 @@ Item {
property bool lostFocus: false
readonly property bool loginDialogPoppedUp: loginDialog.getLoginDialogPoppedUp()
// If not logging into domain, then we must be logging into the metaverse...
readonly property bool isLoggingInToDomain: loginDialog.getDomainLoginRequested()
readonly property string domainLoginDomain: loginDialog.getDomainLoginDomain()
@ -94,7 +95,7 @@ Item {
}
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam,
"withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam, "linkOculus": linkAccountBody.linkOculus,
"displayName":displayNameField.text, "isLoggingInToDomain": linkAccountBody.isLoggingInToDomain });
"displayName":displayNameField.text, "isLoggingInToDomain": linkAccountBody.isLoggingInToDomain, "domainLoginDomain": linkAccountBody.domainLoginDomain });
}
function init() {
@ -105,13 +106,15 @@ Item {
loginErrorMessage.wrapMode = Text.WordWrap;
errorContainer.height = (loginErrorMessageTextMetrics.width / displayNameField.width) * loginErrorMessageTextMetrics.height;
}
var domainLoginText = "Log In to Domain\n" + domainLoginDomain;
loginDialogText.text = (!isLoggingInToDomain) ? "Log In to Metaverse" : domainLoginText;
loginButton.text = (!linkAccountBody.linkSteam && !linkAccountBody.linkOculus) ? "Log In" : "Link Account";
loginButton.text = (!isLoggingInToDomain) ? "Log In" : "Log In to Domain";
loginButton.text = (!isLoggingInToDomain) ? "Log In to Metaverse" : "Log In to Domain";
loginButton.color = hifi.buttons.blue;
displayNameField.placeholderText = "Display Name (optional)";
var savedDisplayName = Settings.getValue("Avatar/displayName", "");
displayNameField.text = savedDisplayName;
emailField.placeholderText = "Username or Email";
emailField.placeholderText = (!isLoggingInToDomain) ? "Username or Email" : "Username";
if (!isLoggingInToDomain) {
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
emailField.text = keepMeLoggedInCheckbox.checked ? savedUsername === "Unknown user" ? "" : savedUsername : "";
@ -144,7 +147,7 @@ Item {
Item {
id: loginContainer
width: displayNameField.width
height: errorContainer.height + displayNameField.height + emailField.height + passwordField.height + 5.5 * hifi.dimensions.contentSpacing.y +
height: errorContainer.height + loginDialogTextContainer.height + displayNameField.height + emailField.height + passwordField.height + 5.5 * hifi.dimensions.contentSpacing.y +
keepMeLoggedInCheckbox.height + loginButton.height + cantAccessTextMetrics.height + continueButton.height
anchors {
top: parent.top
@ -158,9 +161,10 @@ Item {
width: parent.width
height: loginErrorMessageTextMetrics.height
anchors {
bottom: displayNameField.top;
bottomMargin: hifi.dimensions.contentSpacing.y;
left: displayNameField.left;
bottom: loginDialogTextContainer.top
bottomMargin: hifi.dimensions.contentSpacing.y
left: loginDialogTextContainer.left
right: loginDialogTextContainer.right
}
TextMetrics {
id: loginErrorMessageTextMetrics
@ -173,12 +177,45 @@ Item {
font.family: linkAccountBody.fontFamily
font.pixelSize: linkAccountBody.textFieldFontSize
font.bold: linkAccountBody.fontBold
anchors {
top: parent.top
left: parent.left
right: parent.right
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: ""
visible: false
}
}
Item {
id: loginDialogTextContainer
height: 56
anchors {
top: parent.top
left: parent.left
right: parent.right
topMargin: 1.5 * hifi.dimensions.contentSpacing.y
}
Text {
id: loginDialogText
text: qsTr("Log In")
lineHeight: 1
color: "white"
anchors {
top: parent.top
left: parent.left
right: parent.right
}
font.family: linkAccountBody.fontFamily
font.pixelSize: 24
font.bold: linkAccountBody.fontBold
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
HifiControlsUit.TextField {
id: displayNameField
@ -187,8 +224,8 @@ Item {
font.pixelSize: linkAccountBody.textFieldFontSize
styleRenderType: Text.QtRendering
anchors {
top: parent.top
topMargin: errorContainer.height
top: loginDialogTextContainer.bottom
topMargin: 1.5 * hifi.dimensions.contentSpacing.y
}
placeholderText: "Display Name (optional)"
activeFocusOnPress: true
@ -352,6 +389,7 @@ Item {
labelFontFamily: linkAccountBody.fontFamily
labelFontSize: 18;
color: hifi.colors.white;
visible: !isLoggingInToDomain
anchors {
top: passwordField.bottom;
topMargin: hifi.dimensions.contentSpacing.y;
@ -436,7 +474,7 @@ Item {
font.pixelSize: linkAccountBody.textFieldFontSize
font.bold: linkAccountBody.fontBold
text: "<a href='metaverse.vircadia.com/users/password/new'> Can't access your account?</a>"
text: "<a href='https://metaverse.vircadia.com/users/password/new'> Can't access your account?</a>"
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
@ -562,7 +600,7 @@ Item {
leftMargin: hifi.dimensions.contentSpacing.x
}
text: "<a href='metaverse.vircadia.com/users/register'>Sign Up</a>"
text: "<a href='https://metaverse.vircadia.com/users/register'>Sign Up</a>"
linkColor: hifi.colors.blueAccent
onLinkActivated: {

View file

@ -33,6 +33,7 @@ Item {
property bool linkOculus: linkOculus
property bool createOculus: createOculus
property bool isLoggingInToDomain: isLoggingInToDomain
property string domainLoginDomain: domainLoginDomain
property string displayName: ""
readonly property bool loginDialogPoppedUp: loginDialog.getLoginDialogPoppedUp()
@ -109,7 +110,7 @@ Item {
loggingInText.text = "Logging in to Oculus";
loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2;
} else if (loggingInBody.isLoggingInToDomain) {
loggingInText.text = "Logging in to Domain";
loggingInText.text = "Logging in to " + domainLoginDomain;
loggingInText.anchors.centerIn = loggingInHeader;
} else {
loggingInText.text = "Logging in";

View file

@ -1355,7 +1355,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
auto domainAccountManager = DependencyManager::get<DomainAccountManager>();
connect(domainAccountManager.data(), &DomainAccountManager::authRequired, dialogsManager.data(),
&DialogsManager::showDomainLoginDialog);
connect(domainAccountManager.data(), &DomainAccountManager::loginComplete, this,
&Application::updateWindowTitle);
// ####### TODO: Connect any other signals from domainAccountManager.
@ -1582,7 +1584,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// Do not show login dialog if requested not to on the command line
QString hifiNoLoginCommandLineKey = QString("--").append(HIFI_NO_LOGIN_COMMAND_LINE_KEY);
int index = arguments().indexOf(hifiNoLoginCommandLineKey);
if (index != -1) {
if (index != -1 || _disableLoginScreen) {
resumeAfterLoginDialogActionTaken();
return;
}
@ -7079,20 +7081,23 @@ void Application::updateWindowTitle() const {
auto nodeList = DependencyManager::get<NodeList>();
auto accountManager = DependencyManager::get<AccountManager>();
auto domainAccountManager = DependencyManager::get<DomainAccountManager>();
auto isInErrorState = nodeList->getDomainHandler().isInErrorState();
bool isMetaverseLoggedIn = accountManager->isLoggedIn();
bool isDomainLoggedIn = domainAccountManager->isLoggedIn();
QString authedDomain = domainAccountManager->getAuthedDomain();
QString buildVersion = " - Vircadia - "
+ (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build"))
+ " " + applicationVersion();
// ####### TODO
QString loginStatus = accountManager->isLoggedIn() ? "" : " (NOT LOGGED IN)";
QString connectionStatus = isInErrorState ? " (ERROR CONNECTING)" :
nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED)";
QString username = accountManager->getAccountInfo().getUsername();
setCrashAnnotation("sentry[user][username]", username.toStdString());
QString metaverseUsername = accountManager->getAccountInfo().getUsername();
QString domainUsername = domainAccountManager->getUsername();
setCrashAnnotation("sentry[user][metaverseUsername]", metaverseUsername.toStdString());
QString currentPlaceName;
if (isServerlessMode()) {
@ -7108,8 +7113,24 @@ void Application::updateWindowTitle() const {
}
}
QString title = QString() + (!username.isEmpty() ? username + " @ " : QString())
+ currentPlaceName + connectionStatus + loginStatus + buildVersion;
QString metaverseDetails;
if (isMetaverseLoggedIn) {
metaverseDetails = "Metaverse: Logged in as " + metaverseUsername;
} else {
metaverseDetails = "Metaverse: Not Logged In";
}
QString domainDetails;
if (currentPlaceName == authedDomain && isDomainLoggedIn) {
// ###### TODO
// domainDetails = "Domain: Logged in as " + domainUsername;
domainDetails = "Domain: Logged in as " + domainUsername;
} else {
domainDetails = "Domain: Not Logged In";
}
QString title = QString() + currentPlaceName + connectionStatus + " (" + metaverseDetails + ") (" + domainDetails + ")"
+ buildVersion;
#ifndef WIN32
// crashes with vs2013/win32

View file

@ -733,6 +733,7 @@ private:
GraphicsEngine _graphicsEngine;
void updateRenderArgs(float deltaTime);
bool _disableLoginScreen { true };
Overlays _overlays;
ApplicationOverlay _applicationOverlay;

View file

@ -9,6 +9,10 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// For happ(ier) development of QML, use these two things:
// This forces QML files to be pulled from the source as you edit it: set environment variable HIFI_USE_SOURCE_TREE_RESOURCES=1
// Use this to live reload: DependencyManager::get<OffscreenUi>()->clearCache();
#include "Menu.h"
#include <QDesktopServices>
#include <QFileDialog>
@ -84,6 +88,13 @@ Menu::Menu() {
dialogsManager.data(), &DialogsManager::toggleLoginDialog);
}
auto domainLogin = addActionToQMenuAndActionHash(fileMenu, "Domain: Log In");
connect(domainLogin, &QAction::triggered, [] {
auto dialogsManager = DependencyManager::get<DialogsManager>();
dialogsManager->setDomainLoginState();
dialogsManager->showDomainLoginDialog();
});
// File > Quit
addActionToQMenuAndActionHash(fileMenu, MenuOption::Quit, Qt::CTRL | Qt::Key_Q, qApp, SLOT(quit()), QAction::QuitRole);

View file

@ -110,10 +110,21 @@ void DialogsManager::setDomainConnectionFailureVisibility(bool visible) {
}
}
void DialogsManager::setMetaverseLoginState() {
// We're only turning off the domain login trigger but the actual domain auth URL is still saved.
// So we can continue the domain login if desired.
_isDomainLogin = false;
}
void DialogsManager::setDomainLoginState() {
_isDomainLogin = true;
}
void DialogsManager::setDomainLogin(bool isDomainLogin, const QString& domain) {
_isDomainLogin = isDomainLogin;
_domainLoginDomain = domain;
if (!domain.isEmpty()) {
_domainLoginDomain = domain;
}
}
void DialogsManager::toggleLoginDialog() {

View file

@ -41,6 +41,8 @@ public:
QPointer<TestingDialog> getTestingDialog() const { return _testingDialog; }
void emitAddressBarShown(bool visible) { emit addressBarShown(visible); }
void setAddressBarVisible(bool addressBarVisible);
void setMetaverseLoginState();
void setDomainLoginState();
bool getIsDomainLogin() { return _isDomainLogin; }
QString getDomainLoginDomain() { return _domainLoginDomain; }
@ -52,7 +54,7 @@ public slots:
void toggleLoginDialog();
void showLoginDialog();
void hideLoginDialog();
void showDomainLoginDialog(const QString& domain);
void showDomainLoginDialog(const QString& domain = "");
void octreeStatsDetails();
void lodTools();
void hmdTools(bool showTools);

View file

@ -99,14 +99,16 @@ void LoginDialog::toggleAction() {
if (accountManager->isLoggedIn()) {
// change the menu item to logout
loginAction->setText("Logout " + accountManager->getAccountInfo().getUsername());
loginAction->setText("Metaverse: Logout " + accountManager->getAccountInfo().getUsername());
connection = connect(loginAction, &QAction::triggered, accountManager.data(), &AccountManager::logout);
} else {
// change the menu item to login
loginAction->setText("Log In / Sign Up");
loginAction->setText("Metaverse: Log In / Sign Up");
connection = connect(loginAction, &QAction::triggered, [] {
// if not in login state, show.
if (!qApp->getLoginDialogPoppedUp()) {
auto dialogsManager = DependencyManager::get<DialogsManager>();
dialogsManager->setMetaverseLoginState();
LoginDialog::showWithSelection();
}
});

View file

@ -18,7 +18,9 @@
#include <QtNetwork/QNetworkReply>
#include <SettingHandle.h>
#include <DependencyManager.h>
#include "NodeList.h"
#include "NetworkingConstants.h"
#include "NetworkLogging.h"
#include "NetworkAccessManager.h"
@ -101,6 +103,8 @@ void DomainAccountManager::requestAccessTokenFinished() {
// miniOrange plugin provides no scope.
if (rootObject.contains("access_token")) {
// Success.
auto nodeList = DependencyManager::get<NodeList>();
_domain_name = nodeList->getDomainHandler().getHostname();
QUrl rootURL = requestReply->url();
rootURL.setPath("");
setTokensFromJSON(rootObject, rootURL);
@ -133,10 +137,12 @@ bool DomainAccountManager::accessTokenIsExpired() {
bool DomainAccountManager::hasValidAccessToken() {
QString currentDomainAccessToken = domainAccessToken.get();
if (currentDomainAccessToken.isEmpty() || accessTokenIsExpired()) {
// ###### TODO: wire this up to actually retrieve a token (based on session or storage) and confirm that it is in fact valid and relevant to the current domain.
// QString currentDomainAccessToken = domainAccessToken.get();
QString currentDomainAccessToken = _access_token;
// if (currentDomainAccessToken.isEmpty() || accessTokenIsExpired()) {
if (currentDomainAccessToken.isEmpty()) {
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
qCDebug(networking) << "An access token is required for requests to"
<< qPrintable(_authURL.toString());
@ -153,23 +159,20 @@ bool DomainAccountManager::hasValidAccessToken() {
return true;
}
}
void DomainAccountManager::setTokensFromJSON(const QJsonObject& jsonObject, const QUrl& url) {
_access_token = jsonObject["access_token"].toString();
_refresh_token = jsonObject["refresh_token"].toString();
// ####### TODO: Enable and use these.
// ####### TODO: Protect these per AccountManager?
// ######: TODO: clientID needed?
/*
qCDebug(networking) << "Storing a domain account with access-token for" << qPrintable(url.toString());
domainAccessToken.set(jsonObject["access_token"].toString());
domainAccessRefreshToken.set(jsonObject["refresh_token"].toString());
domainAccessTokenExpiresIn.set(QDateTime::currentMSecsSinceEpoch() + (jsonObject["expires_in"].toDouble() * 1000));
domainAccessTokenType.set(jsonObject["token_type"].toString());
*/
// qCDebug(networking) << "Storing a domain account with access-token for" << qPrintable(url.toString());
// domainAccessToken.set(jsonObject["access_token"].toString());
// domainAccessRefreshToken.set(jsonObject["refresh_token"].toString());
// domainAccessTokenExpiresIn.set(QDateTime::currentMSecsSinceEpoch() + (jsonObject["expires_in"].toDouble() * 1000));
// domainAccessTokenType.set(jsonObject["token_type"].toString());
}
bool DomainAccountManager::checkAndSignalForAccessToken() {

View file

@ -29,6 +29,9 @@ public:
QString getUsername() { return _username; }
QString getAccessToken() { return _access_token; }
QString getRefreshToken() { return _refresh_token; }
QString getAuthedDomain() { return _domain_name; }
bool isLoggedIn() { return !_authURL.isEmpty() && hasValidAccessToken(); }
Q_INVOKABLE bool checkAndSignalForAccessToken();
@ -57,6 +60,7 @@ private:
QString _username; // ####### TODO: Store elsewhere?
QString _access_token; // ####... ""
QString _refresh_token; // ####... ""
QString _domain_name; //
};
#endif // hifi_DomainAccountManager_h