WIP. Added Account and Audio forms
This commit is contained in:
@@ -66,7 +66,10 @@ lms_SOURCES = \
|
||||
$(top_srcdir)/ui/video/VideoMediaPlayerWidget.cpp \
|
||||
$(top_srcdir)/ui/video/VideoParametersDialog.cpp \
|
||||
$(top_srcdir)/ui/settings/Settings.cpp \
|
||||
$(top_srcdir)/ui/settings/SettingsAccountFormView.cpp \
|
||||
$(top_srcdir)/ui/settings/SettingsAudioFormView.cpp \
|
||||
$(top_srcdir)/ui/settings/SettingsDatabaseFormView.cpp \
|
||||
$(top_srcdir)/ui/settings/SettingsUserFormView.cpp \
|
||||
$(top_srcdir)/ui/settings/SettingsUsers.cpp
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,14 @@ Handler::configureAuth(void)
|
||||
verifier->addHashFunction(new Wt::Auth::BCryptHashFunction(8));
|
||||
passwordService.setVerifier(verifier);
|
||||
passwordService.setAttemptThrottlingEnabled(true);
|
||||
passwordService.setStrengthValidator(new Wt::Auth::PasswordStrengthValidator());
|
||||
|
||||
Wt::Auth::PasswordStrengthValidator* strengthValidator = new Wt::Auth::PasswordStrengthValidator();
|
||||
// Reduce some constraints...
|
||||
strengthValidator->setMinimumLength( Wt::Auth::PasswordStrengthValidator::TwoCharClass, 11);
|
||||
strengthValidator->setMinimumLength( Wt::Auth::PasswordStrengthValidator::ThreeCharClass, 8 );
|
||||
strengthValidator->setMinimumLength( Wt::Auth::PasswordStrengthValidator::FourCharClass, 6 );
|
||||
|
||||
passwordService.setStrengthValidator(strengthValidator);
|
||||
}
|
||||
|
||||
const Wt::Auth::AuthService&
|
||||
|
||||
@@ -4,6 +4,33 @@
|
||||
|
||||
namespace Database {
|
||||
|
||||
|
||||
// must be ordered
|
||||
const std::vector<std::size_t>
|
||||
User::audioBitrates =
|
||||
{
|
||||
64000,
|
||||
96000,
|
||||
128000,
|
||||
160000,
|
||||
192000,
|
||||
224000,
|
||||
256000,
|
||||
320000,
|
||||
512000
|
||||
};
|
||||
|
||||
|
||||
const std::vector<std::size_t>
|
||||
User::videoBitrates =
|
||||
{
|
||||
256000,
|
||||
512000,
|
||||
1024000,
|
||||
2048000,
|
||||
4096000,
|
||||
8192000
|
||||
};
|
||||
User::User()
|
||||
: _maxAudioBitrate(maxAudioBitrate),
|
||||
_maxVideoBitrate(maxVideoBitrate),
|
||||
@@ -27,6 +54,73 @@ User::getById(Wt::Dbo::Session& session, std::string id)
|
||||
return session.find<User>().where("id = ?").bind( id );
|
||||
}
|
||||
|
||||
std::string
|
||||
User::getId( pointer user)
|
||||
{
|
||||
std::ostringstream oss; oss << user.id();
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void
|
||||
User::setAudioBitrate(std::size_t bitrate)
|
||||
{
|
||||
_audioBitrate = std::min(bitrate, std::min(static_cast<std::size_t>(_maxAudioBitrate), audioBitrates.back()));
|
||||
}
|
||||
|
||||
void
|
||||
User::setVideoBitrate(std::size_t bitrate)
|
||||
{
|
||||
_videoBitrate = std::min(bitrate, std::min(static_cast<std::size_t>(_maxVideoBitrate), videoBitrates.back()));
|
||||
}
|
||||
|
||||
void
|
||||
User::setMaxAudioBitrate(std::size_t bitrate)
|
||||
{
|
||||
_maxAudioBitrate = std::min(bitrate, static_cast<std::size_t>(_maxAudioBitrate));
|
||||
}
|
||||
|
||||
void
|
||||
User::setMaxVideoBitrate(std::size_t bitrate)
|
||||
{
|
||||
_maxVideoBitrate = std::min(bitrate, static_cast<std::size_t>(_maxVideoBitrate));
|
||||
}
|
||||
|
||||
std::size_t
|
||||
User::getAudioBitrate(void) const
|
||||
{
|
||||
if (!isAdmin())
|
||||
return std::min(static_cast<std::size_t>(_audioBitrate), std::min(static_cast<std::size_t>(_maxAudioBitrate), audioBitrates.back()));
|
||||
else
|
||||
return std::min(static_cast<std::size_t>(_audioBitrate), audioBitrates.back());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
User::getVideoBitrate(void) const
|
||||
{
|
||||
if (!isAdmin())
|
||||
return std::min(static_cast<std::size_t>(_videoBitrate), std::min(static_cast<std::size_t>(_maxVideoBitrate), videoBitrates.back()));
|
||||
else
|
||||
return std::min(static_cast<std::size_t>(_videoBitrate), videoBitrates.back());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
User::getMaxAudioBitrate(void) const
|
||||
{
|
||||
if (!isAdmin())
|
||||
return std::min(static_cast<std::size_t>(_maxAudioBitrate), audioBitrates.back());
|
||||
else
|
||||
return audioBitrates.back();
|
||||
}
|
||||
|
||||
std::size_t
|
||||
User::getMaxVideoBitrate(void) const
|
||||
{
|
||||
if (!isAdmin())
|
||||
return std::min(static_cast<std::size_t>(_maxVideoBitrate), videoBitrates.back());
|
||||
else
|
||||
return videoBitrates.back();
|
||||
}
|
||||
|
||||
|
||||
} // namespace Database
|
||||
|
||||
|
||||
+15
-6
@@ -14,6 +14,10 @@ class User {
|
||||
public:
|
||||
static const std::size_t MaxNameLength = 15;
|
||||
|
||||
// list of commonly used bitrates
|
||||
static const std::vector<std::size_t> audioBitrates;
|
||||
static const std::vector<std::size_t> videoBitrates;
|
||||
|
||||
User();
|
||||
|
||||
typedef Wt::Dbo::ptr<User> pointer;
|
||||
@@ -21,16 +25,21 @@ class User {
|
||||
// accessors
|
||||
static pointer getById(Wt::Dbo::Session& session, std::string id);
|
||||
static std::vector<pointer> getAll(Wt::Dbo::Session& session);
|
||||
static std::string getId(pointer user);
|
||||
|
||||
// write
|
||||
void setAdmin(bool admin) { _isAdmin = admin; }
|
||||
void setMaxAudioBitrate(std::size_t bitrate) { _maxAudioBitrate = bitrate; }
|
||||
void setMaxVideoBitrate(std::size_t bitrate) { _maxVideoBitrate = bitrate; }
|
||||
void setAudioBitrate(std::size_t bitrate);
|
||||
void setVideoBitrate(std::size_t bitrate);
|
||||
void setMaxAudioBitrate(std::size_t bitrate);
|
||||
void setMaxVideoBitrate(std::size_t bitrate);
|
||||
|
||||
// read
|
||||
bool isAdmin() const {return _isAdmin;}
|
||||
std::size_t getMaxAudioBitrate() const { return _maxAudioBitrate; }
|
||||
std::size_t getMaxVideoBitrate() const { return _maxVideoBitrate; }
|
||||
std::size_t getAudioBitrate() const;
|
||||
std::size_t getVideoBitrate() const;
|
||||
std::size_t getMaxAudioBitrate() const;
|
||||
std::size_t getMaxVideoBitrate() const;
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
@@ -45,10 +54,10 @@ class User {
|
||||
private:
|
||||
|
||||
static const std::size_t maxAudioBitrate = 320000;
|
||||
static const std::size_t maxVideoBitrate = 7500000;
|
||||
static const std::size_t maxVideoBitrate = 2048000;
|
||||
|
||||
static const std::size_t defaultAudioBitrate = 128000;
|
||||
static const std::size_t defaultVideoBitrate = 1500000;
|
||||
static const std::size_t defaultVideoBitrate = 1024000;
|
||||
|
||||
// Admin defined settings
|
||||
int _maxAudioBitrate;
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<legend>Access</legend>
|
||||
<legend>${access}</legend>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="${id:admin}">
|
||||
@@ -91,6 +91,8 @@
|
||||
${video-bitrate-limit-info}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
${save-button} ${cancel-button}
|
||||
@@ -100,6 +102,88 @@
|
||||
|
||||
</message>
|
||||
|
||||
<message id="userAccountForm-template">
|
||||
<legend>${title}</legend>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="${id:name}">
|
||||
Name
|
||||
</label>
|
||||
<div class="col-sm-5">
|
||||
${name}
|
||||
</div>
|
||||
<div class="help-block col-sm-5">
|
||||
${name-info}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="${id:email}">
|
||||
e-Mail
|
||||
</label>
|
||||
<div class="col-sm-5">
|
||||
${email}
|
||||
</div>
|
||||
<div class="help-block col-sm-5">
|
||||
${email-info}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="${id:password}">
|
||||
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:password-confirm}">
|
||||
Confirm password
|
||||
</label>
|
||||
<div class="col-sm-5">
|
||||
${password-confirm}
|
||||
</div>
|
||||
<div class="help-block col-sm-5">
|
||||
${password-confirm-info}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
${save-button} ${cancel-button}
|
||||
</div>
|
||||
</div>
|
||||
${apply-info}
|
||||
</div>
|
||||
</message>
|
||||
|
||||
<message id="audioForm-template">
|
||||
<legend>${title}</legend>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="${id:bitrate}">
|
||||
Audio bitrate
|
||||
</label>
|
||||
<div class="col-sm-5">
|
||||
<div class="input-group">
|
||||
${bitrate}
|
||||
<span class="input-group-addon">kbps</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="help-block col-sm-5">
|
||||
${bitrate-info}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
${save-button} ${cancel-button}
|
||||
</div>
|
||||
</div>
|
||||
${apply-info}
|
||||
</div>
|
||||
</message>
|
||||
|
||||
<message id="databaseForm-template">
|
||||
<legend>${title}</legend>
|
||||
<div class="form-horizontal">
|
||||
@@ -150,7 +234,6 @@
|
||||
${update-request-immediate-scan-info}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
${apply-button} ${discard-button}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace UserInterface {
|
||||
|
||||
AudioWidget::AudioWidget(SessionData& sessionData, Wt::WContainerWidget* parent)
|
||||
: Wt::WContainerWidget(parent),
|
||||
_sessionData(sessionData),
|
||||
_db(sessionData.getDatabaseHandler()),
|
||||
_audioDbWidget(nullptr),
|
||||
_mediaPlayer(nullptr),
|
||||
_imgResource(nullptr),
|
||||
@@ -39,11 +39,22 @@ AudioWidget::playTrack(boost::filesystem::path p)
|
||||
{
|
||||
std::cout << "play track '" << p << "'" << std::endl;
|
||||
try {
|
||||
// TODO get user's encoding preference
|
||||
|
||||
std::size_t bitrate = 0;
|
||||
|
||||
// Get user preferences
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
Database::User::pointer user = _db.getCurrentUser();
|
||||
if (user)
|
||||
bitrate = user->getAudioBitrate();
|
||||
else
|
||||
return; // TODO logout?
|
||||
}
|
||||
|
||||
Transcode::InputMediaFile inputFile(p);
|
||||
|
||||
Transcode::Parameters parameters(inputFile, Transcode::Format::get(Transcode::Format::OGA), 128000);
|
||||
Transcode::Parameters parameters(inputFile, Transcode::Format::get(Transcode::Format::OGA), bitrate);
|
||||
|
||||
_mediaPlayer->load( parameters );
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class AudioWidget : public Wt::WContainerWidget
|
||||
|
||||
void handleTrackEnded(void);
|
||||
|
||||
SessionData& _sessionData;
|
||||
Database::Handler& _db;
|
||||
|
||||
AudioDatabaseWidget* _audioDbWidget;
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#include <Wt/WRegExpValidator>
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
static inline Wt::WValidator *createEmailValidator()
|
||||
{
|
||||
return new Wt::WRegExpValidator("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}");
|
||||
}
|
||||
|
||||
} // namespace UserInterface
|
||||
@@ -0,0 +1,23 @@
|
||||
#include <Wt/WRegExpValidator>
|
||||
#include <Wt/WLengthValidator>
|
||||
|
||||
#include "database/User.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
static inline Wt::WValidator *createEmailValidator()
|
||||
{
|
||||
Wt::WValidator *res = new Wt::WRegExpValidator("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}");
|
||||
res->setMandatory(true);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline Wt::WValidator *createNameValidator() {
|
||||
Wt::WLengthValidator *v = new Wt::WLengthValidator();
|
||||
v->setMandatory(true);
|
||||
v->setMinimumLength(3);
|
||||
v->setMaximumLength(::Database::User::MaxNameLength);
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace UserInterface
|
||||
@@ -2,6 +2,9 @@
|
||||
#include <Wt/WStackedWidget>
|
||||
#include <Wt/WTextArea>
|
||||
|
||||
#include "SettingsAudioFormView.hpp"
|
||||
#include "SettingsUserFormView.hpp"
|
||||
#include "SettingsAccountFormView.hpp"
|
||||
#include "SettingsDatabaseFormView.hpp"
|
||||
#include "SettingsUsers.hpp"
|
||||
|
||||
@@ -28,16 +31,16 @@ _sessionData(sessionData)
|
||||
// Must be logged in here
|
||||
assert(user);
|
||||
|
||||
menu->addItem("Audio", new AudioFormView(sessionData, Database::User::getId(user)));
|
||||
if (user->isAdmin())
|
||||
{
|
||||
// TODO Special admin settings
|
||||
menu->addItem("Database", new DatabaseFormView(sessionData));
|
||||
menu->addItem("Users", new Users(sessionData));
|
||||
}
|
||||
|
||||
// User specifics settings
|
||||
menu->addItem("Transcoding", new Wt::WTextArea("User's transcoding settings here!"));
|
||||
menu->addItem("Personal", new Wt::WTextArea("User's password + mail here!"));
|
||||
else
|
||||
{
|
||||
menu->addItem("Account", new AccountFormView(sessionData, Database::User::getId(user)));
|
||||
}
|
||||
|
||||
addWidget(contents);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
#include <vector>
|
||||
|
||||
#include <Wt/WStringListModel>
|
||||
#include <Wt/WFormModel>
|
||||
#include <Wt/WLineEdit>
|
||||
#include <Wt/WCheckBox>
|
||||
#include <Wt/WComboBox>
|
||||
#include <Wt/WPushButton>
|
||||
#include <Wt/Auth/Identity>
|
||||
|
||||
#include "common/Validators.hpp"
|
||||
|
||||
#include "SettingsAccountFormView.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
namespace Settings {
|
||||
|
||||
class AccountFormModel : public Wt::WFormModel
|
||||
{
|
||||
public:
|
||||
|
||||
// Associate each field with a unique string literal.
|
||||
static const Field NameField;
|
||||
static const Field EmailField;
|
||||
static const Field PasswordField;
|
||||
static const Field PasswordConfirmField;
|
||||
|
||||
AccountFormModel(SessionData& sessionData, std::string userId, Wt::WObject *parent = 0)
|
||||
: Wt::WFormModel(parent),
|
||||
_db(sessionData.getDatabaseHandler()),
|
||||
_userId(userId)
|
||||
{
|
||||
addField(NameField);
|
||||
addField(EmailField);
|
||||
addField(PasswordField);
|
||||
addField(PasswordConfirmField);
|
||||
|
||||
setValidator(NameField, createNameValidator());
|
||||
setValidator(EmailField, createEmailValidator());
|
||||
|
||||
// populate the model with initial data
|
||||
loadData();
|
||||
}
|
||||
|
||||
void loadData()
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
|
||||
Wt::Auth::User authUser = _db.getUserDatabase().findWithId( _userId );
|
||||
Database::User::pointer user = _db.getUser(authUser);
|
||||
|
||||
if (user && authUser.isValid())
|
||||
{
|
||||
setValue(NameField, authUser.identity(Wt::Auth::Identity::LoginName));
|
||||
if (!authUser.email().empty())
|
||||
setValue(EmailField, authUser.email());
|
||||
else
|
||||
setValue(EmailField, authUser.unverifiedEmail());
|
||||
}
|
||||
setValue(PasswordField, Wt::WString());
|
||||
setValue(PasswordConfirmField, Wt::WString());
|
||||
}
|
||||
|
||||
bool saveData(Wt::WString& error)
|
||||
{
|
||||
// DBO transaction active here
|
||||
try {
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
|
||||
// Update user
|
||||
Wt::Auth::User authUser = _db.getUserDatabase().findWithId(_userId);
|
||||
Database::User::pointer user = _db.getUser( authUser );
|
||||
|
||||
// user may have been deleted by someone else
|
||||
if (!authUser.isValid()) {
|
||||
error = Wt::WString("User identity does not exist");
|
||||
return false;
|
||||
}
|
||||
else if(!user)
|
||||
{
|
||||
error = Wt::WString("User not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Account
|
||||
authUser.setIdentity(Wt::Auth::Identity::LoginName, valueText(NameField));
|
||||
authUser.setEmail(valueText(EmailField).toUTF8());
|
||||
|
||||
// Password
|
||||
if (!valueText(PasswordField).empty())
|
||||
Database::Handler::getPasswordService().updatePassword(authUser, valueText(PasswordField));
|
||||
|
||||
setValue(PasswordField, Wt::WString());
|
||||
setValue(PasswordConfirmField, Wt::WString());
|
||||
|
||||
}
|
||||
catch(Wt::Dbo::Exception& exception)
|
||||
{
|
||||
std::cerr << "Dbo exception: " << exception.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validateField(Field field)
|
||||
{
|
||||
// DBO transaction active here
|
||||
|
||||
Wt::WString error;
|
||||
|
||||
if (field == NameField)
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
// Must be unique since used as LoginIdentity
|
||||
Wt::Auth::User user = _db.getUserDatabase().findWithIdentity(Wt::Auth::Identity::LoginName, valueText(field));
|
||||
if (user.isValid() && user.id() != _userId)
|
||||
error = "Already exists";
|
||||
else
|
||||
return Wt::WFormModel::validateField(field);
|
||||
}
|
||||
else if (field == PasswordField)
|
||||
{
|
||||
// Password is mandatory if we create the user
|
||||
if (!valueText(PasswordField).empty())
|
||||
{
|
||||
// Evaluate the strength of the password
|
||||
Wt::Auth::AbstractPasswordService::StrengthValidatorResult res
|
||||
= Database::Handler::getPasswordService().strengthValidator()->evaluateStrength(valueText(PasswordField),
|
||||
valueText(NameField),
|
||||
valueText(EmailField).toUTF8());
|
||||
|
||||
if (!res.isValid())
|
||||
error = res.message();
|
||||
}
|
||||
else
|
||||
return Wt::WFormModel::validateField(field);
|
||||
}
|
||||
else if (field == PasswordConfirmField)
|
||||
{
|
||||
if (validation(PasswordField).state() == Wt::WValidator::Valid)
|
||||
{
|
||||
if (valueText(PasswordField) != valueText(PasswordConfirmField))
|
||||
error = Wt::WString::tr("Wt.Auth.passwords-dont-match");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply validators
|
||||
return Wt::WFormModel::validateField(field);
|
||||
}
|
||||
|
||||
setValidation(field, Wt::WValidator::Result( error.empty() ? Wt::WValidator::Valid : Wt::WValidator::Invalid, error));
|
||||
|
||||
return validation(field).state() == Wt::WValidator::Valid;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Database::Handler& _db;
|
||||
std::string _userId;
|
||||
};
|
||||
|
||||
const Wt::WFormModel::Field AccountFormModel::NameField = "name";
|
||||
const Wt::WFormModel::Field AccountFormModel::EmailField = "email";
|
||||
const Wt::WFormModel::Field AccountFormModel::PasswordField = "password";
|
||||
const Wt::WFormModel::Field AccountFormModel::PasswordConfirmField = "password-confirm";
|
||||
|
||||
AccountFormView::AccountFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent)
|
||||
: Wt::WTemplateFormView(parent)
|
||||
{
|
||||
|
||||
_model = new AccountFormModel(sessionData, userId, this);
|
||||
|
||||
setTemplateText(tr("userAccountForm-template"));
|
||||
addFunction("id", &WTemplate::Functions::id);
|
||||
addFunction("block", &WTemplate::Functions::id);
|
||||
|
||||
_applyInfo = new Wt::WText();
|
||||
_applyInfo->setInline(false);
|
||||
_applyInfo->hide();
|
||||
bindWidget("apply-info", _applyInfo);
|
||||
|
||||
// Name
|
||||
Wt::WLineEdit* accountEdit = new Wt::WLineEdit();
|
||||
setFormWidget(AccountFormModel::NameField, accountEdit);
|
||||
accountEdit->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Email
|
||||
Wt::WLineEdit* emailEdit = new Wt::WLineEdit();
|
||||
setFormWidget(AccountFormModel::EmailField, emailEdit);
|
||||
emailEdit->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Password
|
||||
Wt::WLineEdit* passwordEdit = new Wt::WLineEdit();
|
||||
setFormWidget(AccountFormModel::PasswordField, passwordEdit );
|
||||
passwordEdit->setEchoMode(Wt::WLineEdit::Password);
|
||||
passwordEdit->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Password confirmation
|
||||
Wt::WLineEdit* passwordConfirmEdit = new Wt::WLineEdit();
|
||||
setFormWidget(AccountFormModel::PasswordConfirmField, passwordConfirmEdit);
|
||||
passwordConfirmEdit->setEchoMode(Wt::WLineEdit::Password);
|
||||
passwordConfirmEdit->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Title & Buttons
|
||||
bindString("title", "Account settings");
|
||||
|
||||
Wt::WPushButton *saveButton = new Wt::WPushButton("Apply");
|
||||
saveButton->setStyleClass("btn-primary");
|
||||
bindWidget("save-button", saveButton);
|
||||
saveButton->clicked().connect(this, &AccountFormView::processSave);
|
||||
|
||||
Wt::WPushButton *cancelButton = new Wt::WPushButton("Discard");
|
||||
bindWidget("cancel-button", cancelButton);
|
||||
cancelButton->clicked().connect(this, &AccountFormView::processCancel);
|
||||
|
||||
updateView(_model);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
AccountFormView::processCancel()
|
||||
{
|
||||
_applyInfo->show();
|
||||
|
||||
_applyInfo->setText( Wt::WString::fromUTF8("Parameters reverted!"));
|
||||
_applyInfo->setStyleClass("alert alert-info");
|
||||
_model->loadData();
|
||||
|
||||
_model->validate();
|
||||
updateView(_model);
|
||||
}
|
||||
|
||||
void
|
||||
AccountFormView::processSave()
|
||||
{
|
||||
updateModel(_model);
|
||||
|
||||
_applyInfo->show();
|
||||
if (_model->validate())
|
||||
{
|
||||
Wt::WString error;
|
||||
// commit model into DB
|
||||
if (_model->saveData(error) )
|
||||
{
|
||||
_applyInfo->setText( Wt::WString::fromUTF8("New parameters successfully applied!"));
|
||||
_applyInfo->setStyleClass("alert alert-success");
|
||||
}
|
||||
else
|
||||
{
|
||||
_applyInfo->setText( Wt::WString::fromUTF8("Cannot apply new parameters: ") + error);
|
||||
_applyInfo->setStyleClass("alert alert-danger");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_applyInfo->setText( Wt::WString::fromUTF8("Cannot apply new parameters!"));
|
||||
_applyInfo->setStyleClass("alert alert-danger");
|
||||
}
|
||||
updateView(_model);
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
} // namespace UserInterface
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef UI_SETTINGS_ACCOUNT_FORM_VIEW_HPP
|
||||
#define UI_SETTINGS_ACCOUNT_FORM_VIEW_HPP
|
||||
|
||||
#include <Wt/WContainerWidget>
|
||||
#include <Wt/WTemplateFormView>
|
||||
#include <Wt/WText>
|
||||
|
||||
#include "common/SessionData.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
namespace Settings {
|
||||
|
||||
class AccountFormModel;
|
||||
|
||||
class AccountFormView : public Wt::WTemplateFormView
|
||||
{
|
||||
public:
|
||||
AccountFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent = 0);
|
||||
|
||||
private:
|
||||
void processCancel(); // reload from DB
|
||||
void processSave(); // commit into DB
|
||||
|
||||
AccountFormModel* _model;
|
||||
Wt::WText* _applyInfo;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Settings
|
||||
} // namespace UserInterface
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,178 @@
|
||||
#include <vector>
|
||||
|
||||
#include <Wt/WStringListModel>
|
||||
#include <Wt/WFormModel>
|
||||
#include <Wt/WComboBox>
|
||||
#include <Wt/WPushButton>
|
||||
|
||||
#include "common/Validators.hpp"
|
||||
|
||||
#include "SettingsAudioFormView.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
namespace Settings {
|
||||
|
||||
class AudioFormModel : public Wt::WFormModel
|
||||
{
|
||||
public:
|
||||
|
||||
// Associate each field with a unique string literal.
|
||||
static const Field BitrateField;
|
||||
|
||||
AudioFormModel(SessionData& sessionData, std::string userId, Wt::WObject *parent = 0)
|
||||
: Wt::WFormModel(parent),
|
||||
_db(sessionData.getDatabaseHandler()),
|
||||
_userId(userId)
|
||||
{
|
||||
initializeModels();
|
||||
|
||||
addField(BitrateField);
|
||||
|
||||
setValidator(BitrateField, new Wt::WValidator(true)); // mandatory
|
||||
|
||||
// populate the model with initial data
|
||||
loadData();
|
||||
}
|
||||
|
||||
Wt::WAbstractItemModel *bitrateModel() { return _bitrateModel; }
|
||||
|
||||
void loadData()
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
|
||||
Database::User::pointer user = Database::User::getById( _db.getSession(), _userId);
|
||||
|
||||
if (user)
|
||||
setValue(BitrateField, std::min(user->getMaxAudioBitrate(), user->getAudioBitrate()) / 1000); // in kps
|
||||
else
|
||||
setValue(BitrateField, Wt::WString());
|
||||
}
|
||||
|
||||
bool saveData(Wt::WString& error)
|
||||
{
|
||||
// DBO transaction active here
|
||||
try {
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
|
||||
Database::User::pointer user = Database::User::getById( _db.getSession(), _userId);
|
||||
// user may have been deleted by someone else
|
||||
if (user)
|
||||
{
|
||||
user.modify()->setAudioBitrate( Wt::asNumber(value(BitrateField)) * 1000); // in kbps
|
||||
}
|
||||
|
||||
}
|
||||
catch(Wt::Dbo::Exception& exception)
|
||||
{
|
||||
std::cerr << "Dbo exception: " << exception.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void initializeModels()
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
|
||||
Database::User::pointer user = Database::User::getById(_db.getSession(), _userId);
|
||||
|
||||
_bitrateModel = new Wt::WStringListModel();
|
||||
BOOST_FOREACH(std::size_t bitrate, Database::User::audioBitrates)
|
||||
{
|
||||
if (user && bitrate <= user->getMaxAudioBitrate())
|
||||
_bitrateModel->addString( Wt::WString("{1}").arg( bitrate / 1000 ) ); // in kbps
|
||||
}
|
||||
}
|
||||
|
||||
Database::Handler& _db;
|
||||
std::string _userId;
|
||||
Wt::WStringListModel* _bitrateModel;
|
||||
};
|
||||
|
||||
const Wt::WFormModel::Field AudioFormModel::BitrateField = "bitrate";
|
||||
|
||||
AudioFormView::AudioFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent)
|
||||
: Wt::WTemplateFormView(parent)
|
||||
{
|
||||
|
||||
_model = new AudioFormModel(sessionData, userId, this);
|
||||
|
||||
setTemplateText(tr("audioForm-template"));
|
||||
addFunction("id", &WTemplate::Functions::id);
|
||||
addFunction("block", &WTemplate::Functions::id);
|
||||
|
||||
_applyInfo = new Wt::WText();
|
||||
_applyInfo->setInline(false);
|
||||
_applyInfo->hide();
|
||||
bindWidget("apply-info", _applyInfo);
|
||||
|
||||
// Bitrate
|
||||
Wt::WComboBox *bitrateCB = new Wt::WComboBox();
|
||||
setFormWidget(AudioFormModel::BitrateField, bitrateCB);
|
||||
bitrateCB->setStyleClass("span2");
|
||||
bitrateCB->setModel(_model->bitrateModel());
|
||||
bitrateCB->changed().connect(_applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Title & Buttons
|
||||
bindString("title", "Audio settings");
|
||||
|
||||
Wt::WPushButton *saveButton = new Wt::WPushButton("Apply");
|
||||
saveButton->setStyleClass("btn-primary");
|
||||
bindWidget("save-button", saveButton);
|
||||
saveButton->clicked().connect(this, &AudioFormView::processSave);
|
||||
|
||||
Wt::WPushButton *cancelButton = new Wt::WPushButton("Discard");
|
||||
bindWidget("cancel-button", cancelButton);
|
||||
cancelButton->clicked().connect(this, &AudioFormView::processCancel);
|
||||
|
||||
|
||||
updateView(_model);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
AudioFormView::processCancel()
|
||||
{
|
||||
_applyInfo->show();
|
||||
|
||||
_applyInfo->setText( Wt::WString::fromUTF8("Parameters reverted!"));
|
||||
_applyInfo->setStyleClass("alert alert-info");
|
||||
_model->loadData();
|
||||
|
||||
_model->validate();
|
||||
updateView(_model);
|
||||
}
|
||||
|
||||
void
|
||||
AudioFormView::processSave()
|
||||
{
|
||||
updateModel(_model);
|
||||
|
||||
_applyInfo->show();
|
||||
if (_model->validate())
|
||||
{
|
||||
Wt::WString error;
|
||||
// commit model into DB
|
||||
if (_model->saveData(error) )
|
||||
{
|
||||
_applyInfo->setText( Wt::WString::fromUTF8("New parameters successfully applied!"));
|
||||
_applyInfo->setStyleClass("alert alert-success");
|
||||
}
|
||||
else
|
||||
{
|
||||
_applyInfo->setText( Wt::WString::fromUTF8("Cannot apply new parameters: ") + error);
|
||||
_applyInfo->setStyleClass("alert alert-danger");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_applyInfo->setText( Wt::WString::fromUTF8("Cannot apply new parameters!"));
|
||||
_applyInfo->setStyleClass("alert alert-danger");
|
||||
}
|
||||
updateView(_model);
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
} // namespace UserInterface
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef UI_SETTINGS_AUDIO_FORM_VIEW_HPP
|
||||
#define UI_SETTINGS_AUDIO_ACCOUNT_FORM_VIEW_HPP
|
||||
|
||||
#include <Wt/WContainerWidget>
|
||||
#include <Wt/WTemplateFormView>
|
||||
#include <Wt/WText>
|
||||
|
||||
#include "common/SessionData.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
namespace Settings {
|
||||
|
||||
class AudioFormModel;
|
||||
|
||||
class AudioFormView : public Wt::WTemplateFormView
|
||||
{
|
||||
public:
|
||||
AudioFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent = 0);
|
||||
|
||||
private:
|
||||
void processCancel(); // reload from DB
|
||||
void processSave(); // commit into DB
|
||||
|
||||
AudioFormModel* _model;
|
||||
Wt::WText* _applyInfo;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Settings
|
||||
} // namespace UserInterface
|
||||
|
||||
#endif
|
||||
@@ -250,25 +250,35 @@ DatabaseFormView::DatabaseFormView(SessionData& sessionData, Wt::WContainerWidge
|
||||
addFunction("id", &WTemplate::Functions::id);
|
||||
addFunction("block", &WTemplate::Functions::id);
|
||||
|
||||
applyInfo = new Wt::WText();
|
||||
applyInfo->setInline(false);
|
||||
applyInfo->hide();
|
||||
bindWidget("apply-info", applyInfo);
|
||||
|
||||
// Path
|
||||
setFormWidget(DatabaseFormModel::PathField, new Wt::WLineEdit());
|
||||
Wt::WLineEdit *pathEdit = new Wt::WLineEdit();
|
||||
setFormWidget(DatabaseFormModel::PathField, pathEdit);
|
||||
pathEdit->changed().connect(applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Update Period
|
||||
Wt::WComboBox *updatePeriodCB = new Wt::WComboBox();
|
||||
setFormWidget(DatabaseFormModel::UpdatePeriodField, updatePeriodCB);
|
||||
updatePeriodCB->setModel(model->updatePeriodModel());
|
||||
updatePeriodCB->changed().connect(applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Update Start Time
|
||||
Wt::WComboBox *updateStartTimeCB = new Wt::WComboBox();
|
||||
setFormWidget(DatabaseFormModel::UpdateStartTimeField, updateStartTimeCB);
|
||||
updateStartTimeCB->setModel(model->updateStartTimeModel());
|
||||
updateStartTimeCB->changed().connect(applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Request Immediate scan
|
||||
setFormWidget(DatabaseFormModel::UpdateRequestImmediateField, new Wt::WCheckBox());
|
||||
Wt::WCheckBox *immScan = new Wt::WCheckBox();
|
||||
setFormWidget(DatabaseFormModel::UpdateRequestImmediateField, immScan);
|
||||
immScan->changed().connect(applyInfo, &Wt::WWidget::hide);
|
||||
|
||||
// Title & Buttons
|
||||
Wt::WString title = Wt::WString("Media directories settings");
|
||||
bindString("title", title);
|
||||
bindString("title", "Media directories settings");
|
||||
|
||||
Wt::WPushButton *saveButton = new Wt::WPushButton("Apply");
|
||||
bindWidget("apply-button", saveButton);
|
||||
@@ -277,11 +287,6 @@ DatabaseFormView::DatabaseFormView(SessionData& sessionData, Wt::WContainerWidge
|
||||
Wt::WPushButton *discardButton = new Wt::WPushButton("Discard");
|
||||
bindWidget("discard-button", discardButton);
|
||||
|
||||
applyInfo = new Wt::WText();
|
||||
applyInfo->setInline(false);
|
||||
applyInfo->hide();
|
||||
bindWidget("apply-info", applyInfo);
|
||||
|
||||
saveButton->clicked().connect(this, &DatabaseFormView::processSave);
|
||||
discardButton->clicked().connect(this, &DatabaseFormView::processDiscard);
|
||||
|
||||
@@ -325,15 +330,13 @@ DatabaseFormView::processSave()
|
||||
|
||||
applyInfo->setText( Wt::WString::fromUTF8("New parameters successfully applied!"));
|
||||
applyInfo->setStyleClass("alert alert-success");
|
||||
|
||||
// Udate the view: Delete any validation message in the view, etc.
|
||||
updateView(model);
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
applyInfo->setText( Wt::WString::fromUTF8("Cannot apply new parameters!"));
|
||||
applyInfo->setStyleClass("alert alert-danger");
|
||||
updateView(model);
|
||||
}
|
||||
// Udate the view: Delete any validation message in the view, etc.
|
||||
updateView(model);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,20 +2,17 @@
|
||||
|
||||
#include <Wt/WStringListModel>
|
||||
#include <Wt/WFormModel>
|
||||
#include <Wt/WLengthValidator>
|
||||
#include <Wt/WLineEdit>
|
||||
#include <Wt/WCheckBox>
|
||||
#include <Wt/WComboBox>
|
||||
#include <Wt/WPushButton>
|
||||
#include <Wt/Auth/Identity>
|
||||
#include <Wt/Auth/PasswordStrengthValidator>
|
||||
#include <Wt/Auth/AbstractPasswordService>
|
||||
#include <Wt/Auth/PasswordVerifier>
|
||||
|
||||
#include "common/EmailValidator.hpp"
|
||||
#include "common/Validators.hpp"
|
||||
|
||||
#include "SettingsUserFormView.hpp"
|
||||
|
||||
|
||||
namespace UserInterface {
|
||||
namespace Settings {
|
||||
|
||||
@@ -34,7 +31,7 @@ class UserFormModel : public Wt::WFormModel
|
||||
|
||||
UserFormModel(SessionData& sessionData, std::string userId, Wt::WObject *parent = 0)
|
||||
: Wt::WFormModel(parent),
|
||||
_sessionData(sessionData),
|
||||
_db(sessionData.getDatabaseHandler()),
|
||||
_userId(userId)
|
||||
{
|
||||
initializeModels();
|
||||
@@ -48,9 +45,7 @@ class UserFormModel : public Wt::WFormModel
|
||||
addField(VideoBitrateLimitField);
|
||||
|
||||
setValidator(NameField, createNameValidator());
|
||||
Wt::WValidator *emailValidator = createEmailValidator();
|
||||
emailValidator->setMandatory(true);
|
||||
setValidator(EmailField, emailValidator);
|
||||
setValidator(EmailField, createEmailValidator());
|
||||
// If creating a user, passwords are mandatory
|
||||
if (_userId.empty())
|
||||
{
|
||||
@@ -72,67 +67,60 @@ class UserFormModel : public Wt::WFormModel
|
||||
|
||||
if (!userId.empty())
|
||||
{
|
||||
Database::Handler& db = _sessionData.getDatabaseHandler();
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
Wt::Auth::User authUser = db.getUserDatabase().findWithId( userId );
|
||||
Database::User::pointer user = db.getUser(authUser);
|
||||
|
||||
Wt::Auth::User currentUser = _sessionData.getDatabaseHandler().getLogin().user();
|
||||
|
||||
if (user && user->isAdmin())
|
||||
{
|
||||
setValue(AdminField, true);
|
||||
|
||||
// We can cannot remove admin rights to ourselves
|
||||
if (currentUser == authUser)
|
||||
setReadOnly(AdminField, true);
|
||||
|
||||
// if the user is admin, no need to limit it
|
||||
setReadOnly(AudioBitrateLimitField, true);
|
||||
setValidator(AudioBitrateLimitField, nullptr);
|
||||
|
||||
setReadOnly(VideoBitrateLimitField, true);
|
||||
setValidator(VideoBitrateLimitField, nullptr);
|
||||
}
|
||||
Wt::Auth::User authUser = _db.getUserDatabase().findWithId( userId );
|
||||
Database::User::pointer user = _db.getUser(authUser);
|
||||
|
||||
Wt::Auth::User currentUser = _db.getLogin().user();
|
||||
|
||||
if (user && authUser.isValid())
|
||||
{
|
||||
if (user->isAdmin())
|
||||
{
|
||||
setValue(AdminField, true);
|
||||
|
||||
// We can cannot remove admin rights to ourselves
|
||||
if (currentUser == authUser)
|
||||
setReadOnly(AdminField, true);
|
||||
|
||||
// if the user is admin, no need to limit it
|
||||
setReadOnly(AudioBitrateLimitField, true);
|
||||
setValidator(AudioBitrateLimitField, nullptr);
|
||||
|
||||
setReadOnly(VideoBitrateLimitField, true);
|
||||
setValidator(VideoBitrateLimitField, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
setValue(AudioBitrateLimitField, user->getMaxAudioBitrate() / 1000); // in kbps
|
||||
setValue(VideoBitrateLimitField, user->getMaxVideoBitrate() / 1000); // in kbps
|
||||
}
|
||||
|
||||
setValue(NameField, authUser.identity(Wt::Auth::Identity::LoginName));
|
||||
if (!authUser.email().empty())
|
||||
setValue(EmailField, authUser.email());
|
||||
else
|
||||
setValue(EmailField, authUser.unverifiedEmail());
|
||||
}
|
||||
|
||||
if (user)
|
||||
{
|
||||
setValue(AudioBitrateLimitField, user->getMaxAudioBitrate() / 1000); // in kbps
|
||||
setValue(VideoBitrateLimitField, user->getMaxVideoBitrate() / 1000); // in kbps
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool saveData()
|
||||
{
|
||||
// DBO transaction active here
|
||||
try {
|
||||
Database::Handler& db = _sessionData.getDatabaseHandler();
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
|
||||
if (_userId.empty())
|
||||
{
|
||||
// Create user
|
||||
Wt::Auth::User authUser = db.getUserDatabase().registerNew();
|
||||
Database::User::pointer user = db.getUser(authUser);
|
||||
Wt::Auth::User authUser = _db.getUserDatabase().registerNew();
|
||||
Database::User::pointer user = _db.getUser(authUser);
|
||||
|
||||
// Account
|
||||
authUser.setIdentity(Wt::Auth::Identity::LoginName, valueText(NameField));
|
||||
authUser.setEmail(valueText(EmailField).toUTF8());
|
||||
db.getPasswordService().updatePassword(authUser, valueText(PasswordField));
|
||||
Database::Handler::getPasswordService().updatePassword(authUser, valueText(PasswordField));
|
||||
|
||||
// Access
|
||||
{
|
||||
@@ -153,10 +141,9 @@ class UserFormModel : public Wt::WFormModel
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Update user
|
||||
Wt::Auth::User authUser = db.getUserDatabase().findWithId(_userId);
|
||||
Database::User::pointer user = db.getUser( authUser );
|
||||
Wt::Auth::User authUser = _db.getUserDatabase().findWithId(_userId);
|
||||
Database::User::pointer user = _db.getUser( authUser );
|
||||
|
||||
// user may have been deleted by someone else
|
||||
if (!authUser.isValid()) {
|
||||
@@ -175,7 +162,7 @@ class UserFormModel : public Wt::WFormModel
|
||||
|
||||
// Password
|
||||
if (!valueText(PasswordField).empty())
|
||||
db.getPasswordService().updatePassword(authUser, valueText(PasswordField));
|
||||
Database::Handler::getPasswordService().updatePassword(authUser, valueText(PasswordField));
|
||||
|
||||
// Access
|
||||
if (!isReadOnly(AdminField))
|
||||
@@ -207,15 +194,13 @@ class UserFormModel : public Wt::WFormModel
|
||||
|
||||
bool validateField(Field field)
|
||||
{
|
||||
// DBO transaction active here
|
||||
|
||||
Wt::WString error;
|
||||
|
||||
if (field == NameField)
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession());
|
||||
Wt::Dbo::Transaction transaction(_db.getSession());
|
||||
// Must be unique since used as LoginIdentity
|
||||
Wt::Auth::User user = _sessionData.getDatabaseHandler().getUserDatabase().findWithIdentity(Wt::Auth::Identity::LoginName, valueText(field));
|
||||
Wt::Auth::User user = _db.getUserDatabase().findWithIdentity(Wt::Auth::Identity::LoginName, valueText(field));
|
||||
if (user.isValid() && user.id() != _userId)
|
||||
error = "Already exists";
|
||||
else
|
||||
@@ -227,17 +212,10 @@ class UserFormModel : public Wt::WFormModel
|
||||
if (!valueText(PasswordField).empty())
|
||||
{
|
||||
// Evaluate the strength of the password
|
||||
Wt::Auth::PasswordStrengthValidator validator;
|
||||
|
||||
// Reduce some constraints...
|
||||
validator.setMinimumLength( Wt::Auth::PasswordStrengthValidator::TwoCharClass, 11);
|
||||
validator.setMinimumLength( Wt::Auth::PasswordStrengthValidator::ThreeCharClass, 8 );
|
||||
validator.setMinimumLength( Wt::Auth::PasswordStrengthValidator::FourCharClass, 6 );
|
||||
|
||||
Wt::Auth::AbstractPasswordService::StrengthValidatorResult res
|
||||
= validator.evaluateStrength(valueText(PasswordField),
|
||||
valueText(NameField),
|
||||
valueText(EmailField).toUTF8());
|
||||
= Database::Handler::getPasswordService().strengthValidator()->evaluateStrength(valueText(PasswordField),
|
||||
valueText(NameField),
|
||||
valueText(EmailField).toUTF8());
|
||||
|
||||
if (!res.isValid())
|
||||
error = res.message();
|
||||
@@ -267,58 +245,21 @@ class UserFormModel : public Wt::WFormModel
|
||||
|
||||
private:
|
||||
|
||||
static Wt::WValidator *createNameValidator() {
|
||||
Wt::WLengthValidator *v = new Wt::WLengthValidator();
|
||||
v->setMandatory(true);
|
||||
v->setMinimumLength(3);
|
||||
v->setMaximumLength(::Database::User::MaxNameLength);
|
||||
return v;
|
||||
}
|
||||
|
||||
void initializeModels()
|
||||
{
|
||||
|
||||
// AUDIO
|
||||
// TODO move defaults somewhere else?
|
||||
static const std::vector<std::size_t>
|
||||
audioBitrateLimits =
|
||||
{
|
||||
64,
|
||||
96,
|
||||
128,
|
||||
160,
|
||||
192,
|
||||
224,
|
||||
256,
|
||||
320,
|
||||
512
|
||||
};
|
||||
|
||||
_audioBitrateModel = new Wt::WStringListModel();
|
||||
for (std::size_t i = 0; i < audioBitrateLimits.size(); ++i)
|
||||
_audioBitrateModel->addString( Wt::WString("{1}").arg( audioBitrateLimits[i] ) );
|
||||
|
||||
BOOST_FOREACH(std::size_t bitrate, Database::User::audioBitrates)
|
||||
_audioBitrateModel->addString( Wt::WString("{1}").arg( bitrate / 1000 ) ); // in kbps
|
||||
|
||||
// VIDEO
|
||||
// TODO move defaults somewhere else?
|
||||
static const std::vector<std::size_t>
|
||||
videoBitrateLimits =
|
||||
{
|
||||
256,
|
||||
512,
|
||||
1024,
|
||||
2048,
|
||||
4096,
|
||||
8192
|
||||
};
|
||||
|
||||
_videoBitrateModel = new Wt::WStringListModel();
|
||||
for (std::size_t i = 0; i < videoBitrateLimits.size(); ++i)
|
||||
_videoBitrateModel->addString( Wt::WString("{1}").arg( videoBitrateLimits[i] ) );
|
||||
BOOST_FOREACH(std::size_t bitrate, Database::User::videoBitrates)
|
||||
_videoBitrateModel->addString( Wt::WString("{1}").arg( bitrate / 1000 ) ); // in kbps
|
||||
|
||||
}
|
||||
|
||||
SessionData& _sessionData;
|
||||
Database::Handler& _db;
|
||||
std::string _userId;
|
||||
Wt::WStringListModel* _audioBitrateModel;
|
||||
Wt::WStringListModel* _videoBitrateModel;
|
||||
@@ -334,8 +275,7 @@ const Wt::WFormModel::Field UserFormModel::VideoBitrateLimitField = "video-bitra
|
||||
|
||||
|
||||
UserFormView::UserFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent)
|
||||
: Wt::WTemplateFormView(parent),
|
||||
_sessionData(sessionData)
|
||||
: Wt::WTemplateFormView(parent)
|
||||
{
|
||||
|
||||
_model = new UserFormModel(sessionData, userId, this);
|
||||
@@ -360,9 +300,10 @@ UserFormView::UserFormView(SessionData& sessionData, std::string userId, Wt::WCo
|
||||
setFormWidget(UserFormModel::PasswordConfirmField, passwordConfirmEdit);
|
||||
passwordConfirmEdit->setEchoMode(Wt::WLineEdit::Password);
|
||||
|
||||
bindString("access", "Access");
|
||||
|
||||
// Admin Field
|
||||
Wt::WCheckBox *admin = new Wt::WCheckBox();
|
||||
setFormWidget(UserFormModel::AdminField, admin);
|
||||
setFormWidget(UserFormModel::AdminField, new Wt::WCheckBox());
|
||||
|
||||
// AudioBitrate
|
||||
Wt::WComboBox *audioBitrateCB = new Wt::WComboBox();
|
||||
@@ -418,7 +359,7 @@ UserFormView::UserFormView(SessionData& sessionData, std::string userId, Wt::WCo
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
UserFormView::processCancel()
|
||||
{
|
||||
// parent widget will delete this widget
|
||||
|
||||
@@ -15,6 +15,7 @@ class UserFormModel;
|
||||
class UserFormView : public Wt::WTemplateFormView
|
||||
{
|
||||
public:
|
||||
|
||||
UserFormView(SessionData& sessionData, std::string userId, Wt::WContainerWidget *parent = 0);
|
||||
|
||||
// Signal emitted once the form is completed
|
||||
@@ -24,8 +25,6 @@ class UserFormView : public Wt::WTemplateFormView
|
||||
|
||||
Wt::Signal<bool> _sigCompleted;
|
||||
|
||||
SessionData& _sessionData;
|
||||
|
||||
void processSave();
|
||||
void processCancel();
|
||||
|
||||
|
||||
@@ -67,11 +67,7 @@ Users::refresh(void)
|
||||
for (std::size_t i = 0; i < users.size(); ++i)
|
||||
{
|
||||
|
||||
std::string userId;
|
||||
{
|
||||
std::ostringstream oss; oss << users[i].id();
|
||||
userId = oss.str();
|
||||
}
|
||||
std::string userId = Database::User::getId(users[i]);
|
||||
|
||||
Wt::Auth::User authUser;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user