Uncomment user actions and fix by finding active DB object instead of converting dead one. Use font-awesome to make icons for buttons. Implement rest of basic logic for login page. Some style fixings. Start adding skip controls.

This commit is contained in:
Kevin Whitaker
2017-02-18 14:25:52 -05:00
parent c5e979e948
commit cb393b0c0d
7 changed files with 113 additions and 42 deletions

View File

@@ -355,8 +355,8 @@ void GroovePlayerMgr::grooveEventLoop()
Wt::Dbo::Transaction voteTransaction(sqlSession);
UserAction* action = new UserAction();
action->action = UserAction::UAction::VoteTrack;
action->user = Wt::Dbo::ptr<User>(&event.userInvolved);
action->trackInvolved = Wt::Dbo::ptr<AudioTrack>(&event.tracksInvolved.front());
action->user = sqlSession.find<User>().where("username = ?").bind(event.userInvolved.username);
action->trackInvolved = sqlSession.find<AudioTrack>().where("fingerprint = ?").bind(event.tracksInvolved.front().trackFingerprint);
action->datetime = Wt::WDateTime::currentDateTime();
sqlSession.add(action);
voteTransaction.commit();
@@ -383,15 +383,15 @@ void GroovePlayerMgr::grooveEventLoop()
}
else if(event.eventType == PLAYING_PAUSED)
{
//Add action to DB TODO
// Wt::Dbo::Transaction pauseTransaction(sqlSession);
// UserAction* action = new UserAction();
// action->action = UserAction::UAction::PlayPause;
// action->user = Wt::Dbo::ptr<User>(&event.userInvolved);
// action->trackInvolved = Wt::Dbo::ptr<AudioTrack>(&event.tracksInvolved.front());
// action->datetime = Wt::WDateTime::currentDateTime();
// sqlSession.add(action);
// pauseTransaction.commit();
//Add action to DB
Wt::Dbo::Transaction pauseTransaction(sqlSession);
UserAction* action = new UserAction();
action->action = UserAction::UAction::PlayPause;
action->user = sqlSession.find<User>().where("username = ?").bind(event.userInvolved.username);
action->trackInvolved = sqlSession.find<AudioTrack>().where("fingerprint = ?").bind(event.tracksInvolved.front().trackFingerprint);
action->datetime = Wt::WDateTime::currentDateTime();
sqlSession.add(action);
pauseTransaction.commit();
groove_playlist_pause(currentPlaylist);
@@ -407,15 +407,15 @@ void GroovePlayerMgr::grooveEventLoop()
}
else if(event.eventType == PLAYING_RESUMED)
{
//Add action to DB TODO
// Wt::Dbo::Transaction playTransaction(sqlSession);
// UserAction* action = new UserAction();
// action->action = UserAction::UAction::PlayPause;
// action->user = Wt::Dbo::ptr<User>(&event.userInvolved);
// action->trackInvolved = Wt::Dbo::ptr<AudioTrack>(&event.tracksInvolved.front());
// action->datetime = Wt::WDateTime::currentDateTime();
// sqlSession.add(action);
// playTransaction.commit();
//Add action to DB
Wt::Dbo::Transaction playTransaction(sqlSession);
UserAction* action = new UserAction();
action->action = UserAction::UAction::PlayPause;
action->user = sqlSession.find<User>().where("username = ?").bind(event.userInvolved.username);
action->trackInvolved = sqlSession.find<AudioTrack>().where("fingerprint = ?").bind(event.tracksInvolved.front().trackFingerprint);
action->datetime = Wt::WDateTime::currentDateTime();
sqlSession.add(action);
playTransaction.commit();
groove_playlist_play(currentPlaylist);
@@ -439,8 +439,8 @@ void GroovePlayerMgr::grooveEventLoop()
Wt::Dbo::Transaction skipTransaction(sqlSession);
UserAction* action = new UserAction();
action->action = UserAction::UAction::RequestSkip;
action->user = Wt::Dbo::ptr<User>(&event.userInvolved);
action->trackInvolved = Wt::Dbo::ptr<AudioTrack>(&event.tracksInvolved.front());
action->user = sqlSession.find<User>().where("username = ?").bind(event.userInvolved.username);
action->trackInvolved = sqlSession.find<AudioTrack>().where("fingerprint = ?").bind(event.tracksInvolved.front().trackFingerprint);
action->datetime = Wt::WDateTime::currentDateTime();
sqlSession.add(action);
skipTransaction.commit();

View File

@@ -32,14 +32,16 @@ struct WebInterface::internal
WebInterface::WebInterface(const Wt::WEnvironment& env) : Wt::WApplication(env)
{
priv_int = new internal;
this->useStyleSheet(Wt::WLink("/resources/font-awesome/css/font-awesome.min.css"));
setTitle("Arbitrateor - Audio Jukebox");
enableUpdates(true);
priv_int->playerUI = new PlayerInterface(this);
priv_int->playerUI->hide();
priv_int->loginUI = new LoginInterface(this);
priv_int->loginUI->animateShow(Wt::WAnimation(Wt::WAnimation::AnimationEffect::SlideInFromTop));
root()->addWidget(priv_int->playerUI);
root()->addWidget(priv_int->loginUI);
priv_int->loginUI->animateShow(Wt::WAnimation(Wt::WAnimation::AnimationEffect::SlideInFromTop));
priv_int->loginUI->checkSessionValidity();
}
WebInterface::~WebInterface()

View File

@@ -19,11 +19,15 @@
#include "LoginInterface.h"
#include "../db/UserAction.h"
#include <Wt/WApplication>
#include <Wt/WEnvironment>
#include <Wt/Dbo/ptr>
#include <Wt/Auth/HashFunction>
#include <Wt/WRandom>
LoginInterface::LoginInterface(WebInterface* app)
{
this->app = app;
//TODO: First check if cookie is set and if is a valid user. Skip login if valid.
loginContainer = new Wt::WContainerWidget();
loginLayout = new Wt::WVBoxLayout();
loginMessage = new Wt::WText("Please Login to access.");
@@ -52,6 +56,24 @@ LoginInterface::LoginInterface(WebInterface* app)
loginContainer->setWidth(Wt::WLength(50, Wt::WLength::Percentage));
}
void LoginInterface::checkSessionValidity()
{
Wt::Dbo::Session sqlSession;
sqlSession.setConnectionPool(*GroovePlayerMgr::getInstance()->connectionPool);
sqlSession.mapClass<User>("user");
sqlSession.mapClass<AudioTrack>("tracks");
sqlSession.mapClass<UserAction>("actions");
//First check if cookie is set and if is a valid user. Skip login if valid.
try{
if(Wt::WApplication::instance()->environment().getCookieValue("arbitrateor_user") != nullptr && getUserForLoginCookie(&sqlSession, *Wt::WApplication::instance()->environment().getCookieValue("arbitrateor_user")).username != User().username)
{
app->currentUser = getUserForLoginCookie(&sqlSession, *Wt::WApplication::instance()->environment().getCookieValue("arbitrateor_user"));
app->loginCompleted();
}
}
catch(std::runtime_error e){}
}
void LoginInterface::loginCheck()
{
//Reset message in case of success.
@@ -78,9 +100,10 @@ void LoginInterface::loginCheck()
createUser(&sqlSession, usernameField->text().toUTF8(),passwordField->text().toUTF8(), true);
}
//Check if the credentials match anything in the DB. If so, store cookie to skip login.
if(getUserForLoginAuth(&sqlSession, usernameField->text().toUTF8(),passwordField->text().toUTF8()) != nullptr)
if(getUserForLoginAuth(&sqlSession, usernameField->text().toUTF8(),passwordField->text().toUTF8()).username != User().username && !getUserForLoginAuth(&sqlSession, usernameField->text().toUTF8(),passwordField->text().toUTF8()).isDisabled)
{
app->currentUser = *getUserForLoginAuth(&sqlSession, usernameField->text().toUTF8(),passwordField->text().toUTF8());
app->currentUser = getUserForLoginAuth(&sqlSession, usernameField->text().toUTF8(),passwordField->text().toUTF8());
Wt::log("info") << "login by "<< app->currentUser.username << " happened.";
setLocalCookieForUser(app->currentUser);
app->loginCompleted();
}
@@ -94,25 +117,54 @@ void LoginInterface::loginCheck()
void LoginInterface::createUser(Wt::Dbo::Session* session, std::string username, std::string rawPassword, bool isAdmin)
{
//TODO
Wt::Dbo::Transaction transaction(*session);
Wt::Auth::BCryptHashFunction hasher;
User* user = new User();
user->isAdmin = isAdmin;
user->username = username;
user->isDisabled = false;
user->passwordSalt = Wt::WRandom::generateId();
user->passwordHash = hasher.compute(rawPassword, user->passwordSalt);
user->loginCookieToken = Wt::WRandom::generateId();
session->add(user);
transaction.commit();
}
int LoginInterface::getUserCount(Wt::Dbo::Session* session)
{
//TODO
Wt::Dbo::Transaction transaction(*session);
int userCount = session->query<int>("select count(username) from user");
transaction.commit();
return userCount;
}
User* LoginInterface::getUserForLoginCookie(Wt::Dbo::Session* session, std::string cookie)
User LoginInterface::getUserForLoginCookie(Wt::Dbo::Session* session, std::string cookie)
{
//TODO
Wt::Dbo::Transaction transaction(*session);
Wt::Dbo::ptr<User> user = session->find<User>().where("cookie = ?").bind(cookie);
transaction.commit();
if(user.get() != nullptr)
{
return (*user);
}
return User();
}
User* LoginInterface::getUserForLoginAuth(Wt::Dbo::Session* session, std::string username, std::string rawPassword)
User LoginInterface::getUserForLoginAuth(Wt::Dbo::Session* session, std::string username, std::string rawPassword)
{
//TODO
Wt::Dbo::Transaction transaction(*session);
Wt::Auth::BCryptHashFunction hasher;
Wt::Dbo::ptr<User> user = session->find<User>().where("username = ?").bind(username);
if(user.get() != nullptr && hasher.compute(rawPassword,(*user).passwordSalt) == (*user).passwordHash)
{
transaction.commit();
return (*user);
}
transaction.commit();
return User();
}
void LoginInterface::setLocalCookieForUser(User user)
{
//TODO
this->app->setCookie("arbitrateor_user", user.loginCookieToken,2628000);
}

View File

@@ -33,6 +33,7 @@ class LoginInterface : public Wt::WContainerWidget
{
public:
LoginInterface(WebInterface* app);
void checkSessionValidity();
private:
Wt::WPushButton* loginButton;
Wt::WVBoxLayout* loginLayout;
@@ -48,8 +49,8 @@ private:
void loginCheck();
void createUser(Wt::Dbo::Session* session, std::string username, std::string rawPassword, bool isAdmin);
int getUserCount(Wt::Dbo::Session* session);
User* getUserForLoginCookie(Wt::Dbo::Session* session, std::string cookie);
User* getUserForLoginAuth(Wt::Dbo::Session* session, std::string username, std::string rawPassword);
User getUserForLoginCookie(Wt::Dbo::Session* session, std::string cookie);
User getUserForLoginAuth(Wt::Dbo::Session* session, std::string username, std::string rawPassword);
void setLocalCookieForUser(User user);
};

View File

@@ -24,6 +24,7 @@
#include <Wt/WLength>
#include <Wt/WColor>
#include <Wt/WBorder>
#include <Wt/WString>
PlayerInterface::PlayerInterface(WebInterface* app)
{
@@ -33,6 +34,7 @@ PlayerInterface::PlayerInterface(WebInterface* app)
playControlLayout = new Wt::WHBoxLayout();
voteControlLayout = new Wt::WVBoxLayout();
playControlWidget = new Wt::WContainerWidget();
skipControls = new Wt::WContainerWidget();
playControlWidget->setLayout(playControlLayout);
currentTrackProgress = new Wt::WProgressBar();
@@ -43,10 +45,17 @@ PlayerInterface::PlayerInterface(WebInterface* app)
trackProgress->timeout().connect(this,&PlayerInterface::updateProgressFromTimer);
currentTrackDetails = new TrackDetails();
playpause = new Wt::WPushButton();
playpause->setText(groove_playlist_playing(GroovePlayerMgr::getInstance()->currentPlaylist)==1?"Pause":"Resume");
playpause->setTextFormat(Wt::XHTMLText);
playpause->decorationStyle().font().setFamily(Wt::WFont::Default,"FontAwesome");
playpause->setText(groove_playlist_playing(GroovePlayerMgr::getInstance()->currentPlaylist)==1?Wt::WString::fromUTF8("&#61516;"):Wt::WString::fromUTF8("&#61515;"));
playpause->setMaximumSize(Wt::WLength(60,Wt::WLength::Point),Wt::WLength(30,Wt::WLength::Point));
isPaused = groove_playlist_playing(GroovePlayerMgr::getInstance()->currentPlaylist)==0;
playpause->clicked().connect(this, &PlayerInterface::playpauseClicked);
skipRequest = new Wt::WPushButton();
skipRequest->setTextFormat(Wt::XHTMLText);
skipRequest->decorationStyle().font().setFamily(Wt::WFont::Default,"FontAwesome");
skipRequest->setText("&#61521;"); //cancel skip? &#61534;
skipControls->addWidget(skipRequest);
interfaceLayout->addWidget(playControlWidget);
interfaceLayout->addWidget(currentTrackProgress);
@@ -55,17 +64,18 @@ PlayerInterface::PlayerInterface(WebInterface* app)
playControlWidget->decorationStyle().setBackgroundColor(Wt::WColor("#00B200"));
playControlLayout->addWidget(playpause,0,Wt::AlignmentFlag::AlignLeft | Wt::AlignmentFlag::AlignMiddle);
playControlLayout->addWidget(currentTrackDetails);
playControlLayout->addWidget(skipControls,0,Wt::AlignmentFlag::AlignRight | Wt::AlignmentFlag::AlignMiddle);
}
void PlayerInterface::playpauseClicked()
{
if(!isPaused)
{
GroovePlayerMgr::getInstance()->lastInternalEvents.push_back(GroovePlayerMgr::PlayerEvent() = {GroovePlayerMgr::PlayerEventType::PLAYING_PAUSED, app->currentUser});
GroovePlayerMgr::getInstance()->lastInternalEvents.push_back(GroovePlayerMgr::PlayerEvent() = {GroovePlayerMgr::PlayerEventType::PLAYING_PAUSED, app->currentUser, std::list<AudioTrack>{GroovePlayerMgr::getInstance()->currentTrack}});
}
else
{
GroovePlayerMgr::getInstance()->lastInternalEvents.push_back(GroovePlayerMgr::PlayerEvent() = {GroovePlayerMgr::PlayerEventType::PLAYING_RESUMED, app->currentUser});
GroovePlayerMgr::getInstance()->lastInternalEvents.push_back(GroovePlayerMgr::PlayerEvent() = {GroovePlayerMgr::PlayerEventType::PLAYING_RESUMED, app->currentUser, std::list<AudioTrack>{GroovePlayerMgr::getInstance()->currentTrack}});
}
}
@@ -73,11 +83,11 @@ void PlayerInterface::playpauseUpdated()
{
if(isPaused)
{
playpause->setText("Resume");
playpause->setText(Wt::WString::fromUTF8("&#61515;"));
}
else
{
playpause->setText("Pause");
playpause->setText(Wt::WString::fromUTF8("&#61516;"));
}
}

View File

@@ -48,6 +48,8 @@ public:
Wt::WHBoxLayout* currentTrackLayout;
Wt::WContainerWidget* currentTrackContainer;
Wt::WPushButton* playpause;
Wt::WContainerWidget* skipControls;
Wt::WPushButton* skipRequest;
bool isPaused = false;
//TODO:put in controls for requesting/admin skip and adding users as admin.

View File

@@ -23,7 +23,7 @@
TrackDetails::TrackDetails()
{
this->setMaximumSize(Wt::WLength(600, Wt::WLength::Pixel),Wt::WLength(200, Wt::WLength::Pixel));
this->setMaximumSize(Wt::WLength::Auto,Wt::WLength(200, Wt::WLength::Pixel));
this->decorationStyle().setBorder(Wt::WBorder::Ridge);
this->decorationStyle().setBackgroundColor(Wt::WColor("#6FFF6F"));
mainLayout = new Wt::WHBoxLayout();
@@ -34,14 +34,18 @@ TrackDetails::TrackDetails()
albumCover->setMinimumSize(Wt::WLength(100,Wt::WLength::Pixel),Wt::WLength(100,Wt::WLength::Pixel));
albumCover->setMaximumSize(Wt::WLength(200,Wt::WLength::Pixel),Wt::WLength(200,Wt::WLength::Pixel));
mainLayout->addWidget(albumCover);
mainLayout->addSpacing(Wt::WLength(20, Wt::WLength::Pixel));
mainLayout->addSpacing(Wt::WLength(10, Wt::WLength::Pixel));
mainLayout->addLayout(metaLayout);
mainLayout->addSpacing(Wt::WLength(10, Wt::WLength::Pixel));
trackTitle = new Wt::WText();
trackTitle->setWordWrap(false);
trackTitle->decorationStyle().setTextDecoration(Wt::WCssDecorationStyle::Underline);
trackTitle->decorationStyle().font().setSize(Wt::WFont::Size::Large);
trackTitle->decorationStyle().font().setWeight(Wt::WFont::Weight::Bold);
trackArtist = new Wt::WText();
trackArtist->setWordWrap(false);
trackAlbum = new Wt::WText();
trackAlbum->setWordWrap(false);
metaLayout->addWidget(trackTitle,2);
metaLayout->addWidget(trackAlbum,1,Wt::AlignmentFlag::AlignBottom);
metaLayout->addWidget(trackArtist,1,Wt::AlignmentFlag::AlignBottom);