Added a login view

This commit is contained in:
emeric
2018-03-13 09:43:16 +01:00
parent 85a3e42dac
commit f91aacb0a3
10 changed files with 203 additions and 115 deletions
+1
View File
@@ -19,6 +19,7 @@ lms_images_DATA = \
lms_approot_DATA = \ lms_approot_DATA = \
approot/artists.xml \ approot/artists.xml \
approot/artist.xml \ approot/artist.xml \
approot/login.xml \
approot/mediaplayer.xml \ approot/mediaplayer.xml \
approot/messages.xml \ approot/messages.xml \
approot/playqueue.xml \ approot/playqueue.xml \
+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" ?>
<messages xmlns:if="Wt.WTemplate.conditions">
<message id="template-login">
<div class="container">
<div class="page-header">
<h2>${tr:msg-login-welcome}</h2>
</div>
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2" for="${id:user-name}">
${tr:msg-login}
</label>
<div class="col-sm-5">
${user-name}
</div>
<div class="help-block col-sm-5">
${user-name-info}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="${id:password}">
${tr:msg-password}
</label>
<div class="col-sm-5">
${password}
</div>
<div class="help-block col-sm-5">
${password-info}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="${id:remember-me}">
${tr:msg-remember-me}
</label>
<div class="col-sm-5">
${remember-me}
</div>
<div class="help-block col-sm-5">
${remember-me-info}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
${login-btn class="btn-primary"}
</div>
</div>
</div>
</div>
</message>
</messages>
+4
View File
@@ -26,6 +26,10 @@
<message id="msg-password-confirm">Verify password</message> <message id="msg-password-confirm">Verify password</message>
<message id="msg-create">Create</message> <message id="msg-create">Create</message>
<message id="msg-remember-me">Remember me</message>
<message id="msg-login-welcome">Welcome!</message>
<message id="msg-logout">Logout</message>
<message id="msg-settings-admin-account">Administrator account</message> <message id="msg-settings-admin-account">Administrator account</message>
<message id="msg-settings-first-connection-done">Account created. Please refresh to continue!</message> <message id="msg-settings-first-connection-done">Account created. Please refresh to continue!</message>
+1 -1
View File
@@ -27,12 +27,12 @@ lms_SOURCES = \
$(srcdir)/ui/Filters.cpp \ $(srcdir)/ui/Filters.cpp \
$(srcdir)/ui/HomeView.cpp \ $(srcdir)/ui/HomeView.cpp \
$(srcdir)/ui/LmsApplication.cpp \ $(srcdir)/ui/LmsApplication.cpp \
$(srcdir)/ui/LoginView.cpp \
$(srcdir)/ui/MediaPlayer.cpp \ $(srcdir)/ui/MediaPlayer.cpp \
$(srcdir)/ui/PlayQueueView.cpp \ $(srcdir)/ui/PlayQueueView.cpp \
$(srcdir)/ui/ReleasesView.cpp \ $(srcdir)/ui/ReleasesView.cpp \
$(srcdir)/ui/ReleaseView.cpp \ $(srcdir)/ui/ReleaseView.cpp \
$(srcdir)/ui/TracksView.cpp \ $(srcdir)/ui/TracksView.cpp \
$(srcdir)/ui/auth/LmsAuth.cpp \
$(srcdir)/ui/common/Validators.cpp \ $(srcdir)/ui/common/Validators.cpp \
$(srcdir)/ui/common/InputRange.cpp \ $(srcdir)/ui/common/InputRange.cpp \
$(srcdir)/ui/common/LineEdit.cpp \ $(srcdir)/ui/common/LineEdit.cpp \
+6 -1
View File
@@ -26,6 +26,7 @@
#include <Wt/Auth/Dbo/UserDatabase> #include <Wt/Auth/Dbo/UserDatabase>
#include <Wt/Auth/AuthService> #include <Wt/Auth/AuthService>
#include <Wt/Auth/HashFunction> #include <Wt/Auth/HashFunction>
#include <Wt/Auth/Identity>
#include <Wt/Auth/PasswordService> #include <Wt/Auth/PasswordService>
#include <Wt/Auth/PasswordStrengthValidator> #include <Wt/Auth/PasswordStrengthValidator>
#include <Wt/Auth/PasswordVerifier> #include <Wt/Auth/PasswordVerifier>
@@ -48,7 +49,11 @@ namespace {
void void
Handler::configureAuth(void) Handler::configureAuth(void)
{ {
authService.setEmailVerificationEnabled(true); authService.setEmailVerificationEnabled(false);
authService.setAuthTokensEnabled(true, "lmsauth");
authService.setIdentityPolicy(Wt::Auth::LoginNameIdentity);
authService.setRandomTokenLength(32);
authService.setTokenHashFunction(new Wt::Auth::BCryptHashFunction(8));
Wt::Auth::PasswordVerifier *verifier = new Wt::Auth::PasswordVerifier(); Wt::Auth::PasswordVerifier *verifier = new Wt::Auth::PasswordVerifier();
verifier->addHashFunction(new Wt::Auth::BCryptHashFunction(8)); verifier->addHashFunction(new Wt::Auth::BCryptHashFunction(8));
+38 -41
View File
@@ -24,12 +24,13 @@
#include <Wt/WMenu> #include <Wt/WMenu>
#include <Wt/WPopupMenu> #include <Wt/WPopupMenu>
#include <Wt/WText> #include <Wt/WText>
#include <Wt/Auth/Identity>
#include "config/config.h" #include "config/config.h"
#include "utils/Logger.hpp" #include "utils/Logger.hpp"
#include "utils/Utils.hpp" #include "utils/Utils.hpp"
#include "auth/LmsAuth.hpp" #include "LoginView.hpp"
#include "Explore.hpp" #include "Explore.hpp"
#include "HomeView.hpp" #include "HomeView.hpp"
#include "MediaPlayer.hpp" #include "MediaPlayer.hpp"
@@ -86,6 +87,7 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
// Add a resource bundle // Add a resource bundle
messageResourceBundle().use(appRoot() + "artist"); messageResourceBundle().use(appRoot() + "artist");
messageResourceBundle().use(appRoot() + "artists"); messageResourceBundle().use(appRoot() + "artists");
messageResourceBundle().use(appRoot() + "login");
messageResourceBundle().use(appRoot() + "mediaplayer"); messageResourceBundle().use(appRoot() + "mediaplayer");
messageResourceBundle().use(appRoot() + "messages"); messageResourceBundle().use(appRoot() + "messages");
messageResourceBundle().use(appRoot() + "playqueue"); messageResourceBundle().use(appRoot() + "playqueue");
@@ -109,9 +111,19 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
LMS_LOG(UI, DEBUG) << "Creating root widget. First connection = " << std::boolalpha << firstConnection; LMS_LOG(UI, DEBUG) << "Creating root widget. First connection = " << std::boolalpha << firstConnection;
if (firstConnection) if (firstConnection)
createFirstConnectionUI(); {
// Hack, use the auth widget builtin strings
builtinLocalizedStrings().useBuiltin(skeletons::AuthStrings_xml1);
root()->addWidget(new Settings::FirstConnectionView());
}
else else
createLmsUI(); {
DbHandler().getLogin().changed().connect(this, &LmsApplication::handleAuthEvent);
auto auth = new LoginView(DbHandler().getLogin());
root()->addWidget(auth);
}
} }
Database::Handler& DbHandler() Database::Handler& DbHandler()
@@ -130,8 +142,7 @@ const Wt::Auth::User& CurrentAuthUser()
Database::User::pointer CurrentUser() Database::User::pointer CurrentUser()
{ {
return Database::User::getById(DboSession(), 1); return DbHandler().getCurrentUser();
// return DbHandler().getCurrentUser();
} }
ImageResource* SessionImageResource() ImageResource* SessionImageResource()
@@ -156,36 +167,12 @@ LmsApplication::goHome()
} }
void void
LmsApplication::createFirstConnectionUI() LmsApplication::quit()
{ {
// Hack, use the auth widget builtin strings WApplication::quit("");
builtinLocalizedStrings().useBuiltin(skeletons::AuthStrings_xml1); redirect("/");
root()->addWidget(new Settings::FirstConnectionView());
} }
void
LmsApplication::createLmsUI()
{
_imageResource = new ImageResource(_db, root());
_transcodeResource = new TranscodeResource(_db, root());
handleAuthEvent();
/*
DbHandler().getLogin().changed().connect(this, &LmsApplication::handleAuthEvent);
LmsAuth *authWidget = new LmsAuth();
authWidget->model()->addPasswordAuth(&Database::Handler::getPasswordService());
authWidget->setRegistrationEnabled(false);
authWidget->processEnvironment();
root()->addWidget(authWidget);
*/
}
enum IdxRoot enum IdxRoot
{ {
IdxHome = 0, IdxHome = 0,
@@ -194,8 +181,6 @@ enum IdxRoot
IdxSettingsDatabase, IdxSettingsDatabase,
}; };
static void static void
handlePathChange(Wt::WStackedWidget* stack) handlePathChange(Wt::WStackedWidget* stack)
{ {
@@ -228,19 +213,19 @@ handlePathChange(Wt::WStackedWidget* stack)
void void
LmsApplication::handleAuthEvent(void) LmsApplication::handleAuthEvent(void)
{ {
/*
if (!DbHandler().getLogin().loggedIn()) if (!DbHandler().getLogin().loggedIn())
{ {
LMS_LOG(UI, INFO) << "User logged out, session = " << Wt::WApplication::instance()->sessionId(); LMS_LOG(UI, INFO) << "User logged out, session = " << Wt::WApplication::instance()->sessionId();
quit(""); quit();
redirect("/");
return; return;
} }
LMS_LOG(UI, INFO) << "User '" << CurrentAuthUser().identity(Wt::Auth::Identity::LoginName) << "' logged in from '" << Wt::WApplication::instance()->environment().clientAddress() << "', user agent = " << Wt::WApplication::instance()->environment().agent() << ", session = " << Wt::WApplication::instance()->sessionId(); LMS_LOG(UI, INFO) << "User '" << CurrentAuthUser().identity(Wt::Auth::Identity::LoginName) << "' logged in from '" << Wt::WApplication::instance()->environment().clientAddress() << "', user agent = " << Wt::WApplication::instance()->environment().agent() << ", session = " << Wt::WApplication::instance()->sessionId();
*/
_imageResource = new ImageResource(_db, root());
_transcodeResource = new TranscodeResource(_db, root());
setConfirmCloseMessage(Wt::WString::tr("msg-quit-confirm")); setConfirmCloseMessage(Wt::WString::tr("msg-quit-confirm"));
auto main = new Wt::WTemplate(Wt::WString::tr("template-main"), root()); auto main = new Wt::WTemplate(Wt::WString::tr("template-main"), root());
@@ -273,8 +258,11 @@ LmsApplication::handleAuthEvent(void)
menuItem->setLink(Wt::WLink(Wt::WLink::InternalPath, "/playqueue")); menuItem->setLink(Wt::WLink(Wt::WLink::InternalPath, "/playqueue"));
menuItem->setSelectable(false); menuItem->setSelectable(false);
} }
navbar->addMenu(menu);
auto rightMenu = new Wt::WMenu();
{ {
auto menuItem = menu->insertItem(4, Wt::WString::tr("msg-settings")); auto menuItem = rightMenu->insertItem(0, Wt::WString::tr("msg-settings"));
menuItem->setSelectable(false); menuItem->setSelectable(false);
Wt::WPopupMenu *settings = new Wt::WPopupMenu(); Wt::WPopupMenu *settings = new Wt::WPopupMenu();
@@ -285,7 +273,16 @@ LmsApplication::handleAuthEvent(void)
menuItem->setMenu(settings); menuItem->setMenu(settings);
} }
navbar->addMenu(menu); {
auto menuItem = rightMenu->insertItem(1, Wt::WString::tr("msg-logout"));
menuItem->setSelectable(true);
menuItem->triggered().connect(std::bind([=]
{
setConfirmCloseMessage("");
DbHandler().getLogin().logout();
}));
}
navbar->addMenu(rightMenu, Wt::AlignRight);
// Contents // Contents
Wt::WStackedWidget* mainStack = new Wt::WStackedWidget(); Wt::WStackedWidget* mainStack = new Wt::WStackedWidget();
+1 -4
View File
@@ -20,9 +20,7 @@
#ifndef LMS_APPLICATION_HPP #ifndef LMS_APPLICATION_HPP
#define LMS_APPLICATION_HPP #define LMS_APPLICATION_HPP
#include <boost/filesystem.hpp>
#include <Wt/WApplication> #include <Wt/WApplication>
#include <Wt/Dbo/SqlConnectionPool> #include <Wt/Dbo/SqlConnectionPool>
#include "database/DatabaseHandler.hpp" #include "database/DatabaseHandler.hpp"
@@ -48,6 +46,7 @@ class LmsApplication : public Wt::WApplication
// Utils // Utils
void goHome(); void goHome();
void quit();
void notify(const Wt::WString& message); void notify(const Wt::WString& message);
private: private:
@@ -55,8 +54,6 @@ class LmsApplication : public Wt::WApplication
LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner); LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
void handleAuthEvent(void); void handleAuthEvent(void);
void createFirstConnectionUI();
void createLmsUI();
Database::Handler _db; Database::Handler _db;
Scanner::MediaScanner& _scanner; Scanner::MediaScanner& _scanner;
+89
View File
@@ -0,0 +1,89 @@
/*
* Copyright (C) 2018 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Wt/WFormModel>
#include <Wt/WLineEdit>
#include <Wt/WCheckBox>
#include <Wt/WPushButton>
#include <Wt/Auth/AuthModel>
#include "utils/Logger.hpp"
#include "common/Validators.hpp"
#include "LmsApplication.hpp"
#include "LoginView.hpp"
namespace UserInterface {
LoginView::LoginView(Wt::Auth::Login& login, Wt::WContainerWidget *parent)
: Wt::WTemplateFormView(parent)
{
auto model = new Wt::Auth::AuthModel(DbHandler().getAuthService(), DbHandler().getUserDatabase());
model->addPasswordAuth(&Database::Handler::getPasswordService());
setTemplateText(Wt::WString::tr("template-login"));
addFunction("tr", &WTemplate::Functions::tr);
addFunction("id", &WTemplate::Functions::id);
// LoginName
auto loginName = new Wt::WLineEdit();
setFormWidget(Wt::Auth::AuthModel::LoginNameField, loginName);
// Password
auto password = new Wt::WLineEdit();
setFormWidget(Wt::Auth::AuthModel::PasswordField, password);
password->setEchoMode(Wt::WLineEdit::Password);
// Remember Me
auto rememberMe = new Wt::WCheckBox();
setFormWidget(Wt::Auth::AuthModel::RememberMeField, rememberMe);
auto loginBtn = new Wt::WPushButton(Wt::WString::tr("msg-login"));
bindWidget("login-btn", loginBtn);
loginBtn->clicked().connect(std::bind([=, &login]
{
updateModel(model);
if (model->validate())
model->login(login);
else
updateView(model);
}));
password->enterPressed().connect(std::bind([=]
{
loginBtn->clicked().emit(Wt::WMouseEvent());
}));
login.changed().connect(std::bind([=, &login]
{
if (login.loggedIn())
this->setHidden(true);
}));
Wt::Auth::User user = model->processAuthToken();
model->loginUser(login, user, Wt::Auth::WeakLogin);
updateView(model);
}
} // namespace UserInterface
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Emeric Poupon * Copyright (C) 2018 Emeric Poupon
* *
* This file is part of LMS. * This file is part of LMS.
* *
@@ -17,33 +17,21 @@
* along with LMS. If not, see <http://www.gnu.org/licenses/>. * along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef UI_AUTH_HPP #pragma once
#define UI_AUTH_HPP
#include <Wt/Auth/AuthService>
#include <Wt/Auth/AbstractUserDatabase>
#include <Wt/Auth/Login>
#include <Wt/Auth/AuthWidget>
#include <Wt/WContainerWidget> #include <Wt/WContainerWidget>
#include <Wt/WTemplateFormView>
#include <Wt/Auth/Login>
namespace UserInterface { namespace UserInterface {
class LmsAuth : public Wt::Auth::AuthWidget class LoginView : public Wt::WTemplateFormView
{ {
public: public:
LoginView(Wt::Auth::Login& login, Wt::WContainerWidget *parent = 0);
LmsAuth();
// LoggedInView is delegated to LmsHome
void createLoggedInView () ;
void createLoginView ();
private:
}; };
} // namespace UserInterface } // namespace UserInterface
#endif
-49
View File
@@ -1,49 +0,0 @@
/*
* Copyright (C) 2013 Emeric Poupon
*
* This file is part of LMS.
*
* LMS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LmsAuth.hpp"
#include "LmsApplication.hpp"
namespace UserInterface {
LmsAuth::LmsAuth()
: Wt::Auth::AuthWidget(DbHandler().getAuthService(),
DbHandler().getUserDatabase(),
DbHandler().getLogin())
{
// Root div has to be a container
this->setStyleClass("container");
}
void
LmsAuth::createLoggedInView()
{
hide();
}
void
LmsAuth::createLoginView()
{
show();
Wt::Auth::AuthWidget::createLoginView();
}
} // namespace UserInterface