WIP. User authentication on user interface
This commit is contained in:
@@ -19,6 +19,7 @@ lms_SOURCES = \
|
|||||||
$(top_srcdir)/cover/CoverArt.cpp \
|
$(top_srcdir)/cover/CoverArt.cpp \
|
||||||
$(top_srcdir)/cover/CoverArtGrabber.cpp \
|
$(top_srcdir)/cover/CoverArtGrabber.cpp \
|
||||||
$(top_srcdir)/ui/LmsApplication.cpp \
|
$(top_srcdir)/ui/LmsApplication.cpp \
|
||||||
|
$(top_srcdir)/ui/LmsHome.cpp \
|
||||||
$(top_srcdir)/ui/audio/AudioWidget.cpp \
|
$(top_srcdir)/ui/audio/AudioWidget.cpp \
|
||||||
$(top_srcdir)/ui/audio/AudioDatabaseWidget.cpp \
|
$(top_srcdir)/ui/audio/AudioDatabaseWidget.cpp \
|
||||||
$(top_srcdir)/ui/audio/AudioMediaPlayerWidget.cpp \
|
$(top_srcdir)/ui/audio/AudioMediaPlayerWidget.cpp \
|
||||||
|
|||||||
@@ -1,14 +1,55 @@
|
|||||||
#include "DatabaseHandler.hpp"
|
#include <Wt/Auth/Dbo/AuthInfo>
|
||||||
|
#include <Wt/Auth/Dbo/UserDatabase>
|
||||||
|
#include <Wt/Auth/AuthService>
|
||||||
|
#include <Wt/Auth/HashFunction>
|
||||||
|
#include <Wt/Auth/PasswordService>
|
||||||
|
#include <Wt/Auth/PasswordStrengthValidator>
|
||||||
|
#include <Wt/Auth/PasswordVerifier>
|
||||||
|
|
||||||
|
// Db types
|
||||||
#include "AudioTypes.hpp"
|
#include "AudioTypes.hpp"
|
||||||
#include "FileTypes.hpp"
|
#include "FileTypes.hpp"
|
||||||
#include "MediaDirectory.hpp"
|
#include "MediaDirectory.hpp"
|
||||||
|
#include "User.hpp"
|
||||||
|
|
||||||
|
#include "DatabaseHandler.hpp"
|
||||||
|
|
||||||
namespace Database {
|
namespace Database {
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
Wt::Auth::AuthService authService;
|
||||||
|
Wt::Auth::PasswordService passwordService(authService);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Handler::configureAuth(void)
|
||||||
|
{
|
||||||
|
authService.setEmailVerificationEnabled(true);
|
||||||
|
|
||||||
|
Wt::Auth::PasswordVerifier *verifier = new Wt::Auth::PasswordVerifier();
|
||||||
|
verifier->addHashFunction(new Wt::Auth::BCryptHashFunction(8));
|
||||||
|
passwordService.setVerifier(verifier);
|
||||||
|
passwordService.setAttemptThrottlingEnabled(true);
|
||||||
|
passwordService.setStrengthValidator(new Wt::Auth::PasswordStrengthValidator());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Wt::Auth::AuthService&
|
||||||
|
Handler::getAuthService()
|
||||||
|
{
|
||||||
|
return authService;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Wt::Auth::PasswordService&
|
||||||
|
Handler::getPasswordService()
|
||||||
|
{
|
||||||
|
return passwordService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Handler::Handler(boost::filesystem::path db)
|
Handler::Handler(boost::filesystem::path db)
|
||||||
:
|
:
|
||||||
_path(db),
|
|
||||||
_dbBackend( db.string() )
|
_dbBackend( db.string() )
|
||||||
{
|
{
|
||||||
_session.setConnection(_dbBackend);
|
_session.setConnection(_dbBackend);
|
||||||
@@ -22,6 +63,11 @@ _dbBackend( db.string() )
|
|||||||
_session.mapClass<Database::MediaDirectory>("media_directory");
|
_session.mapClass<Database::MediaDirectory>("media_directory");
|
||||||
_session.mapClass<Database::MediaDirectorySettings>("media_directory_settings");
|
_session.mapClass<Database::MediaDirectorySettings>("media_directory_settings");
|
||||||
|
|
||||||
|
_session.mapClass<Database::User>("user");
|
||||||
|
_session.mapClass<Database::AuthInfo>("auth_info");
|
||||||
|
_session.mapClass<Database::AuthInfo::AuthIdentityType>("auth_identity");
|
||||||
|
_session.mapClass<Database::AuthInfo::AuthTokenType>("auth_token");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_session.createTables();
|
_session.createTables();
|
||||||
}
|
}
|
||||||
@@ -30,6 +76,19 @@ _dbBackend( db.string() )
|
|||||||
}
|
}
|
||||||
|
|
||||||
_dbBackend.executeSql("pragma journal_mode=WAL");
|
_dbBackend.executeSql("pragma journal_mode=WAL");
|
||||||
|
|
||||||
|
_users = new UserDatabase(_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler::~Handler()
|
||||||
|
{
|
||||||
|
delete _users;
|
||||||
|
}
|
||||||
|
|
||||||
|
Wt::Auth::AbstractUserDatabase&
|
||||||
|
Handler::getUserDatabase()
|
||||||
|
{
|
||||||
|
return *_users;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Database
|
} // namespace Database
|
||||||
|
|||||||
@@ -5,26 +5,44 @@
|
|||||||
|
|
||||||
#include <Wt/Dbo/Dbo>
|
#include <Wt/Dbo/Dbo>
|
||||||
#include <Wt/Dbo/backend/Sqlite3>
|
#include <Wt/Dbo/backend/Sqlite3>
|
||||||
|
#include <Wt/Auth/Dbo/UserDatabase>
|
||||||
|
#include <Wt/Auth/Login>
|
||||||
|
#include <Wt/Auth/PasswordService>
|
||||||
|
|
||||||
|
#include "User.hpp"
|
||||||
|
|
||||||
namespace Database {
|
namespace Database {
|
||||||
|
|
||||||
// Long living class handling the database
|
typedef Wt::Auth::Dbo::UserDatabase<AuthInfo> UserDatabase;
|
||||||
|
|
||||||
|
// Session living class handling the database
|
||||||
class Handler
|
class Handler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Handler(boost::filesystem::path db);
|
Handler(boost::filesystem::path db);
|
||||||
|
~Handler();
|
||||||
|
|
||||||
Wt::Dbo::Session& getSession() { return _session; }
|
Wt::Dbo::Session& getSession() { return _session; }
|
||||||
|
|
||||||
boost::filesystem::path getPath() const { return _path; }
|
Wt::Auth::AbstractUserDatabase& getUserDatabase();
|
||||||
|
Wt::Auth::Login& getLogin() { return _login; }
|
||||||
|
|
||||||
|
// Long living shared associated services
|
||||||
|
static void configureAuth();
|
||||||
|
|
||||||
|
static const Wt::Auth::AuthService& getAuthService();
|
||||||
|
static const Wt::Auth::PasswordService& getPasswordService();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::filesystem::path _path;
|
|
||||||
Wt::Dbo::backend::Sqlite3 _dbBackend;
|
Wt::Dbo::backend::Sqlite3 _dbBackend;
|
||||||
Wt::Dbo::Session _session;
|
Wt::Dbo::Session _session;
|
||||||
|
|
||||||
|
UserDatabase* _users;
|
||||||
|
Wt::Auth::Login _login;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Database
|
} // namespace Database
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef DATABASE_USER_HPP
|
||||||
|
#define DATABASE_USER_HPP
|
||||||
|
|
||||||
|
|
||||||
|
#include <Wt/Auth/Dbo/AuthInfo>
|
||||||
|
|
||||||
|
namespace Database {
|
||||||
|
|
||||||
|
class User;
|
||||||
|
typedef Wt::Auth::Dbo::AuthInfo<User> AuthInfo;
|
||||||
|
|
||||||
|
class User {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<class Action>
|
||||||
|
void persist(Action& a)
|
||||||
|
{
|
||||||
|
Wt::Dbo::field(a, _isAdmin, "admin");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool _isAdmin;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Databas'
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -11,7 +11,7 @@ DatabaseUpdateService::DatabaseUpdateService(boost::asio::io_service& ioService,
|
|||||||
void
|
void
|
||||||
DatabaseUpdateService::start(void)
|
DatabaseUpdateService::start(void)
|
||||||
{
|
{
|
||||||
// _thread = boost::thread(boost::bind(&DatabaseUpdater::Updater::process, &_databaseUpdater));
|
_thread = boost::thread(boost::bind(&DatabaseUpdater::Updater::process, &_databaseUpdater));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
+3
-1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "transcode/AvConvTranscoder.hpp"
|
#include "transcode/AvConvTranscoder.hpp"
|
||||||
#include "av/Common.hpp"
|
#include "av/Common.hpp"
|
||||||
|
#include "database/DatabaseHandler.hpp"
|
||||||
|
|
||||||
#include "ServiceManager.hpp"
|
#include "ServiceManager.hpp"
|
||||||
#include "DatabaseUpdateService.hpp"
|
#include "DatabaseUpdateService.hpp"
|
||||||
@@ -29,10 +30,11 @@ int main(int argc, char* argv[])
|
|||||||
// lib init
|
// lib init
|
||||||
Av::AvInit();
|
Av::AvInit();
|
||||||
Transcode::AvConvTranscoder::init();
|
Transcode::AvConvTranscoder::init();
|
||||||
|
Database::Handler::configureAuth();
|
||||||
|
|
||||||
std::cout << "Starting services..." << std::endl;
|
std::cout << "Starting services..." << std::endl;
|
||||||
|
|
||||||
serviceManager.startService( std::make_shared<DatabaseUpdateService>( serviceManager.getIoService(), dbPath) );
|
// serviceManager.startService( std::make_shared<DatabaseUpdateService>( serviceManager.getIoService(), dbPath) );
|
||||||
serviceManager.startService( std::make_shared<RemoteServerService>( serviceManager.getIoService(), remoteListenEndpoint, dbPath) );
|
serviceManager.startService( std::make_shared<RemoteServerService>( serviceManager.getIoService(), remoteListenEndpoint, dbPath) );
|
||||||
serviceManager.startService( std::make_shared<UserInterfaceService>(argc, argv, dbPath) );
|
serviceManager.startService( std::make_shared<UserInterfaceService>(argc, argv, dbPath) );
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ namespace Server {
|
|||||||
Connection::Connection(boost::asio::io_service& ioService,
|
Connection::Connection(boost::asio::io_service& ioService,
|
||||||
boost::asio::ssl::context& context,
|
boost::asio::ssl::context& context,
|
||||||
ConnectionManager& manager,
|
ConnectionManager& manager,
|
||||||
RequestHandler& handler)
|
const boost::filesystem::path& dbPath)
|
||||||
: _closing(false),
|
: _closing(false),
|
||||||
_socket(ioService, context),
|
_socket(ioService, context),
|
||||||
_connectionManager(manager),
|
_connectionManager(manager),
|
||||||
_requestHandler(handler)
|
_requestHandler(dbPath)
|
||||||
{
|
{
|
||||||
std::cout << "Server::Connection::Connection, Creating connection" << std::endl;
|
std::cout << "Server::Connection::Connection, Creating connection" << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ class Connection : public std::enable_shared_from_this<Connection>
|
|||||||
|
|
||||||
/// Construct a connection with the given io_service.
|
/// Construct a connection with the given io_service.
|
||||||
explicit Connection(boost::asio::io_service& ioService, boost::asio::ssl::context& context,
|
explicit Connection(boost::asio::io_service& ioService, boost::asio::ssl::context& context,
|
||||||
ConnectionManager& manager, RequestHandler& handler);
|
ConnectionManager& manager,
|
||||||
|
const boost::filesystem::path& dbPath);
|
||||||
|
|
||||||
ssl_socket::lowest_layer_type& getSocket() {return _socket.lowest_layer();}
|
ssl_socket::lowest_layer_type& getSocket() {return _socket.lowest_layer();}
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ class Connection : public std::enable_shared_from_this<Connection>
|
|||||||
ConnectionManager& _connectionManager;
|
ConnectionManager& _connectionManager;
|
||||||
|
|
||||||
/// The handler used to process the incoming requests.
|
/// The handler used to process the incoming requests.
|
||||||
RequestHandler& _requestHandler;
|
RequestHandler _requestHandler;
|
||||||
|
|
||||||
boost::asio::streambuf _inputStreamBuf;
|
boost::asio::streambuf _inputStreamBuf;
|
||||||
boost::asio::streambuf _outputStreamBuf;
|
boost::asio::streambuf _outputStreamBuf;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ _ioService(ioService),
|
|||||||
_acceptor(_ioService, bindEndpoint, true /*SO_REUSEADDR*/),
|
_acceptor(_ioService, bindEndpoint, true /*SO_REUSEADDR*/),
|
||||||
_connectionManager(),
|
_connectionManager(),
|
||||||
_context(boost::asio::ssl::context::tlsv1_server),
|
_context(boost::asio::ssl::context::tlsv1_server),
|
||||||
_requestHandler(dbPath)
|
_dbPath(dbPath)
|
||||||
{
|
{
|
||||||
_context.set_options( boost::asio::ssl::context::default_workarounds // TODO check this thing
|
_context.set_options( boost::asio::ssl::context::default_workarounds // TODO check this thing
|
||||||
| boost::asio::ssl::context::single_dh_use
|
| boost::asio::ssl::context::single_dh_use
|
||||||
@@ -40,7 +40,7 @@ Server::run()
|
|||||||
void
|
void
|
||||||
Server::asyncAccept()
|
Server::asyncAccept()
|
||||||
{
|
{
|
||||||
std::shared_ptr<Connection> newConnection = std::make_shared<Connection>(_ioService, _context, _connectionManager, _requestHandler);
|
std::shared_ptr<Connection> newConnection = std::make_shared<Connection>(_ioService, _context, _connectionManager, _dbPath);
|
||||||
|
|
||||||
_acceptor.async_accept(newConnection->getSocket(),
|
_acceptor.async_accept(newConnection->getSocket(),
|
||||||
boost::bind(&Server::handleAccept, this, newConnection, boost::asio::placeholders::error));
|
boost::bind(&Server::handleAccept, this, newConnection, boost::asio::placeholders::error));
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ class Server
|
|||||||
|
|
||||||
boost::asio::ssl::context _context;
|
boost::asio::ssl::context _context;
|
||||||
|
|
||||||
/// The handler for all incoming requests.
|
/// The database to be used for requests
|
||||||
RequestHandler _requestHandler;
|
boost::filesystem::path _dbPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Server
|
} // namespace Server
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include "database/DatabaseHandler.hpp"
|
||||||
|
#include <Wt/Auth/PasswordService>
|
||||||
|
#include <Wt/Auth/Identity>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::filesystem::remove("test_user.db");
|
||||||
|
|
||||||
|
// Set up the database session
|
||||||
|
Database::Handler::configureAuth();
|
||||||
|
|
||||||
|
Database::Handler db("test_user.db");
|
||||||
|
|
||||||
|
Wt::Dbo::Transaction transaction(db.getSession());
|
||||||
|
|
||||||
|
Wt::Auth::Identity identity;
|
||||||
|
Wt::Auth::User user = db.getUserDatabase().registerNew();
|
||||||
|
std::cout << "User is valid = " << std::boolalpha << user.isValid() << std::endl;
|
||||||
|
|
||||||
|
user.setIdentity(identity.provider(), "toto");
|
||||||
|
|
||||||
|
std::cout << "User is valid = " << std::boolalpha << user.isValid() << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Updating password" << std::endl;
|
||||||
|
db.getPasswordService().updatePassword(user, "This is my password");
|
||||||
|
|
||||||
|
// db.getSession().add( user );
|
||||||
|
|
||||||
|
std::cout << "Committing" << std::endl;
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Caught exception " << e.what() << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
+16
-2
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
TESTS = database-integrity sql-query database-basics remote
|
TESTS = database-integrity sql-query database-basics database-user remote
|
||||||
|
|
||||||
check_PROGRAMS = database-integrity sql-query database-basics remote
|
check_PROGRAMS = database-integrity sql-query database-basics database-user remote
|
||||||
|
|
||||||
remote_SOURCES = \
|
remote_SOURCES = \
|
||||||
$(srcdir)/RemoteClientServer.cpp \
|
$(srcdir)/RemoteClientServer.cpp \
|
||||||
@@ -22,6 +22,20 @@ remote_SOURCES = \
|
|||||||
|
|
||||||
remote_CXXFLAGS=-std=c++11 -Wall -Wextra -I$(top_srcdir) -I$(top_srcdir)/remote -I$(top_srcdir)/boost
|
remote_CXXFLAGS=-std=c++11 -Wall -Wextra -I$(top_srcdir) -I$(top_srcdir)/remote -I$(top_srcdir)/boost
|
||||||
|
|
||||||
|
database_user_SOURCES = \
|
||||||
|
$(srcdir)/CheckDatabaseUser.cpp \
|
||||||
|
$(top_srcdir)/database/Artist.cpp \
|
||||||
|
$(top_srcdir)/database/Genre.cpp \
|
||||||
|
$(top_srcdir)/database/Release.cpp \
|
||||||
|
$(top_srcdir)/database/Track.cpp \
|
||||||
|
$(top_srcdir)/database/DatabaseHandler.cpp \
|
||||||
|
$(top_srcdir)/database/SqlQuery.cpp \
|
||||||
|
$(top_srcdir)/database/Path.cpp \
|
||||||
|
$(top_srcdir)/database/Video.cpp
|
||||||
|
|
||||||
|
database_user_CXXFLAGS=-std=c++11 -Wall -Wextra -I$(top_srcdir)
|
||||||
|
|
||||||
|
|
||||||
database_integrity_SOURCES = \
|
database_integrity_SOURCES = \
|
||||||
$(srcdir)/DatabaseIntegrity.cpp \
|
$(srcdir)/DatabaseIntegrity.cpp \
|
||||||
$(top_srcdir)/database/Artist.cpp \
|
$(top_srcdir)/database/Artist.cpp \
|
||||||
|
|||||||
+37
-52
@@ -1,13 +1,6 @@
|
|||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
|
||||||
#include <Wt/WBreak>
|
|
||||||
#include <Wt/WLabel>
|
|
||||||
#include <Wt/WBootstrapTheme>
|
#include <Wt/WBootstrapTheme>
|
||||||
#include <Wt/WStackedWidget>
|
#include "LmsAuth.hpp"
|
||||||
#include <Wt/WMenu>
|
#include "LmsHome.hpp"
|
||||||
#include <Wt/WNavigationBar>
|
|
||||||
#include <Wt/WPopupMenu>
|
|
||||||
#include <Wt/WPopupMenuItem>
|
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
|
||||||
@@ -32,65 +25,57 @@ LmsApplication::create(const Wt::WEnvironment& env, boost::filesystem::path dbPa
|
|||||||
*/
|
*/
|
||||||
LmsApplication::LmsApplication(const Wt::WEnvironment& env, boost::filesystem::path dbPath)
|
LmsApplication::LmsApplication(const Wt::WEnvironment& env, boost::filesystem::path dbPath)
|
||||||
: Wt::WApplication(env),
|
: Wt::WApplication(env),
|
||||||
_sessionData(dbPath)
|
_sessionData(dbPath),
|
||||||
|
_home(nullptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
setTheme(new Wt::WBootstrapTheme());
|
setTheme(new Wt::WBootstrapTheme());
|
||||||
|
|
||||||
setTitle("LMS"); // application title
|
setTitle("LMS"); // application title
|
||||||
|
|
||||||
Wt::WContainerWidget* container (new Wt::WContainerWidget(root()));
|
_sessionData.getDatabaseHandler().getLogin().changed().connect(this, &LmsApplication::handleAuthEvent);
|
||||||
|
|
||||||
// Create a navigation bar with a link to a web page.
|
LmsAuth *authWidget = new LmsAuth(Database::Handler::getAuthService(),
|
||||||
Wt::WNavigationBar *navigation = new Wt::WNavigationBar(container);
|
_sessionData.getDatabaseHandler().getUserDatabase(),
|
||||||
navigation->setTitle("LMS");
|
_sessionData.getDatabaseHandler().getLogin());
|
||||||
navigation->setResponsive(true);
|
|
||||||
|
|
||||||
Wt::WStackedWidget *contentsStack = new Wt::WStackedWidget(container);
|
authWidget->model()->addPasswordAuth(&Database::Handler::getPasswordService());
|
||||||
contentsStack->addStyleClass("contents");
|
authWidget->setRegistrationEnabled(true);
|
||||||
|
|
||||||
// Setup a Left-aligned menu.
|
authWidget->processEnvironment();
|
||||||
Wt::WMenu *leftMenu = new Wt::WMenu(contentsStack, container);
|
|
||||||
navigation->addMenu(leftMenu);
|
|
||||||
|
|
||||||
_audioWidget = new AudioWidget(_sessionData);
|
root()->addWidget(authWidget);
|
||||||
_videoWidget = new VideoWidget(_sessionData);
|
|
||||||
|
|
||||||
leftMenu->addItem("Audio", _audioWidget);
|
|
||||||
leftMenu->addItem("Video", _videoWidget);
|
|
||||||
|
|
||||||
// Setup a Right-aligned menu.
|
|
||||||
Wt::WMenu *rightMenu = new Wt::WMenu();
|
|
||||||
navigation->addMenu(rightMenu, Wt::AlignRight);
|
|
||||||
|
|
||||||
Wt::WPopupMenu *popup = new Wt::WPopupMenu();
|
|
||||||
popup->addItem("Parameters");
|
|
||||||
popup->addSeparator();
|
|
||||||
popup->addItem("Logout");
|
|
||||||
|
|
||||||
Wt::WMenuItem *item = new Wt::WMenuItem("User");
|
|
||||||
item->setMenu(popup);
|
|
||||||
rightMenu->addItem(item);
|
|
||||||
|
|
||||||
// Add a Search control.
|
|
||||||
_searchEdit = new Wt::WLineEdit();
|
|
||||||
_searchEdit->setEmptyText("Search...");
|
|
||||||
|
|
||||||
_searchEdit->keyWentUp().connect(this, &LmsApplication::handleSearch);
|
|
||||||
|
|
||||||
navigation->addSearch(_searchEdit, Wt::AlignLeft);
|
|
||||||
|
|
||||||
container->addWidget(contentsStack);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
LmsApplication::handleSearch(void)
|
LmsApplication::handleAuthEvent(void)
|
||||||
{
|
{
|
||||||
// Check currently selected menu item and search it
|
_sessionData.getDatabaseHandler().getLogin().changed().connect(this, &LmsApplication::handleAuthEvent);
|
||||||
_audioWidget->search( _searchEdit->text().toUTF8() );
|
if (_sessionData.getDatabaseHandler().getLogin().loggedIn())
|
||||||
|
{
|
||||||
|
if (_home == nullptr) {
|
||||||
|
_home = new LmsHome(_sessionData );
|
||||||
|
root()->addWidget( _home );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cerr << "Already logged in??" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "user log out" << std::endl;
|
||||||
|
if (_home != nullptr) {
|
||||||
|
std::cerr << "Deleting home pointer..." << std::endl;
|
||||||
|
delete _home;
|
||||||
|
_home = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cerr << "Already logged out??" << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace DatabaseHandler
|
} // namespace UserInterface
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
#include <Wt/WApplication>
|
#include <Wt/WApplication>
|
||||||
#include <Wt/WLineEdit>
|
|
||||||
|
|
||||||
#include "audio/AudioWidget.hpp"
|
#include "common/SessionData.hpp"
|
||||||
#include "video/VideoWidget.hpp"
|
|
||||||
|
#include "LmsHome.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
@@ -18,13 +18,11 @@ class LmsApplication : public Wt::WApplication
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void handleSearch();
|
void handleAuthEvent(void);
|
||||||
|
|
||||||
SessionData _sessionData;
|
SessionData _sessionData;
|
||||||
|
|
||||||
Wt::WLineEdit* _searchEdit;
|
LmsHome* _home;
|
||||||
AudioWidget* _audioWidget;
|
|
||||||
VideoWidget* _videoWidget;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#include <Wt/Auth/AuthService>
|
||||||
|
#include <Wt/Auth/AbstractUserDatabase>
|
||||||
|
#include <Wt/Auth/Login>
|
||||||
|
#include <Wt/Auth/AuthWidget>
|
||||||
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class LmsAuth : public Wt::Auth::AuthWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LmsAuth(const Wt::Auth::AuthService &baseAuth,
|
||||||
|
Wt::Auth::AbstractUserDatabase &users,
|
||||||
|
Wt::Auth::Login &login,
|
||||||
|
Wt::WContainerWidget *parent=0)
|
||||||
|
: Wt::Auth::AuthWidget(baseAuth, users, login, parent) {}
|
||||||
|
|
||||||
|
// LoggedInView is delegated to LmsHome
|
||||||
|
void createLoggedInView () { hide();}
|
||||||
|
|
||||||
|
void createLoginView () { show(); Wt::Auth::AuthWidget::createLoginView();}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
#include <Wt/WStackedWidget>
|
||||||
|
#include <Wt/WMenu>
|
||||||
|
#include <Wt/WNavigationBar>
|
||||||
|
#include <Wt/WPopupMenu>
|
||||||
|
#include <Wt/WPopupMenuItem>
|
||||||
|
#include <Wt/Auth/Identity>
|
||||||
|
|
||||||
|
#include "LmsHome.hpp"
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
|
||||||
|
LmsHome::LmsHome(SessionData& sessionData)
|
||||||
|
: _sessionData(sessionData)
|
||||||
|
{
|
||||||
|
const Wt::Auth::User& user = sessionData.getDatabaseHandler().getLogin().user();
|
||||||
|
|
||||||
|
// Create a navigation bar with a link to a web page.
|
||||||
|
Wt::WNavigationBar *navigation = new Wt::WNavigationBar(this);
|
||||||
|
navigation->setTitle("LMS");
|
||||||
|
navigation->setResponsive(true);
|
||||||
|
|
||||||
|
Wt::WStackedWidget *contentsStack = new Wt::WStackedWidget(this);
|
||||||
|
contentsStack->addStyleClass("contents");
|
||||||
|
|
||||||
|
// Setup a Left-aligned menu.
|
||||||
|
Wt::WMenu *leftMenu = new Wt::WMenu(contentsStack, this);
|
||||||
|
navigation->addMenu(leftMenu);
|
||||||
|
|
||||||
|
_audioWidget = new AudioWidget(_sessionData);
|
||||||
|
_videoWidget = new VideoWidget(_sessionData);
|
||||||
|
|
||||||
|
leftMenu->addItem("Audio", _audioWidget);
|
||||||
|
leftMenu->addItem("Video", _videoWidget);
|
||||||
|
|
||||||
|
// Setup a Right-aligned menu.
|
||||||
|
Wt::WMenu *rightMenu = new Wt::WMenu();
|
||||||
|
|
||||||
|
navigation->addMenu(rightMenu, Wt::AlignRight);
|
||||||
|
|
||||||
|
Wt::WPopupMenu *popup = new Wt::WPopupMenu();
|
||||||
|
popup->addItem("Parameters");
|
||||||
|
popup->addSeparator();
|
||||||
|
popup->addItem("Logout");
|
||||||
|
|
||||||
|
popup->itemSelected().connect(this, &LmsHome::handleUserMenuSelected);
|
||||||
|
|
||||||
|
Wt::WMenuItem *item = new Wt::WMenuItem( user.identity(Wt::Auth::Identity::LoginName) );
|
||||||
|
item->setMenu(popup);
|
||||||
|
rightMenu->addItem(item);
|
||||||
|
|
||||||
|
// Add a Search control.
|
||||||
|
_searchEdit = new Wt::WLineEdit();
|
||||||
|
_searchEdit->setEmptyText("Search...");
|
||||||
|
|
||||||
|
_searchEdit->keyWentUp().connect(this, &LmsHome::handleSearch);
|
||||||
|
|
||||||
|
navigation->addSearch(_searchEdit, Wt::AlignLeft);
|
||||||
|
|
||||||
|
addWidget(contentsStack);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LmsHome::handleUserMenuSelected( Wt::WMenuItem* item)
|
||||||
|
{
|
||||||
|
if (item && item->text() == "Logout") {
|
||||||
|
_sessionData.getDatabaseHandler().getLogin().logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LmsHome::handleSearch(void)
|
||||||
|
{
|
||||||
|
// TODO Check currently selected menu item and search it
|
||||||
|
_audioWidget->search( _searchEdit->text().toUTF8() );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef LMS_HOME_HPP
|
||||||
|
#define LMS_HOME_HPP
|
||||||
|
|
||||||
|
#include <Wt/WContainerWidget>
|
||||||
|
#include <Wt/WLineEdit>
|
||||||
|
|
||||||
|
#include "common/SessionData.hpp"
|
||||||
|
|
||||||
|
#include "audio/AudioWidget.hpp"
|
||||||
|
#include "video/VideoWidget.hpp"
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class LmsHome : public Wt::WContainerWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LmsHome(SessionData& sessionData);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void handleSearch(void);
|
||||||
|
void handleUserMenuSelected( Wt::WMenuItem* item );
|
||||||
|
|
||||||
|
SessionData& _sessionData;
|
||||||
|
|
||||||
|
Wt::WLineEdit* _searchEdit;
|
||||||
|
AudioWidget* _audioWidget;
|
||||||
|
VideoWidget* _videoWidget;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Reference in New Issue
Block a user