From 1a19a11081e56aff745ca0ba625187fabc54fb94 Mon Sep 17 00:00:00 2001 From: Christian Wieninger Date: Tue, 8 Sep 2009 19:50:00 +0200 Subject: new files for user management --- pages/edit_user.ecpp | 176 +++++++++++++++++++++++++++++++++++++++++++++ pages/users.ecpp | 80 +++++++++++++++++++++ users.cpp | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++ users.h | 69 ++++++++++++++++++ 4 files changed, 525 insertions(+) create mode 100644 pages/edit_user.ecpp create mode 100644 pages/users.ecpp create mode 100644 users.cpp create mode 100644 users.h diff --git a/pages/edit_user.ecpp b/pages/edit_user.ecpp new file mode 100644 index 0000000..2ae510a --- /dev/null +++ b/pages/edit_user.ecpp @@ -0,0 +1,176 @@ +<%pre> +#include "exception.h" +#include "tools.h" +#include "users.h" +#include "livefeatures.h" +#include "setup.h" + +using namespace std; +using namespace vdrlive; + + +<%args> + // input parameters + string userid; + // form parameters + string username; + string password; + bool ur_editsetup = false; + bool ur_addtimers = false; + bool ur_deltimers = false; + bool ur_delrecs = false; + bool ur_useremote = false; + bool ur_startreplay = false; + bool ur_switchchnl = false; + bool ur_addstimers = false; + bool ur_delstimers = false; + +<%session scope="global"> +bool logged_in(false); + +<%request scope="page"> +cUser* editUser; + +<%include>page_init.eh +<%cpp> + if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + +#define CHECKIF(x) reply.out() << ( (x) ? "checked=\"checked\"" : "" ); + + editUser = NULL; + + if (request.getMethod() == "POST") { + if (!userid.empty()) { + editUser = Users.GetByUserId( userid ); + if ( editUser == 0 ) + throw HtmlError( tr("Couldn't find user. Maybe you mistyped your request?") ); + editUser->SetName(username); + if (password != std::string(editUser->GetPasswordLength(), '*')) + editUser->SetPassword(password); + } + else + { + if (Users.GetByUserName( username )) + throw HtmlError( tr("This user name is already in use!") ); + editUser = new cUser(Users.GetNewId(), username, password); + Users.Add(editUser); + } + editUser->SetUserrights(0); + if (ur_editsetup) editUser->SetRight(UR_EDITSETUP); + if (ur_addtimers) editUser->SetRight(UR_EDITTIMERS); + if (ur_deltimers) editUser->SetRight(UR_DELTIMERS); + if (ur_delrecs) editUser->SetRight(UR_DELRECS); + if (ur_useremote) editUser->SetRight(UR_USEREMOTE); + if (ur_startreplay) editUser->SetRight(UR_STARTREPLAY); + if (ur_switchchnl) editUser->SetRight(UR_SWITCHCHNL); + if (ur_addstimers) editUser->SetRight(UR_EDITSTIMERS); + if (ur_delstimers) editUser->SetRight(UR_DELSTIMERS); + + Users.Save(); + + return reply.redirect("users.html"); + } + + pageTitle = !userid.empty() ? tr("Edit user") : tr("New user"); + + if ( !userid.empty() ) { + cUser* User = Users.GetByUserId( userid ); + if ( User == 0 ) + throw HtmlError( tr("Couldn't find user. Maybe you mistyped your request?") ); + + username = User->Name(); + password = std::string(User->GetPasswordLength(), '*'); + ur_editsetup = User->HasRightTo(UR_EDITSETUP); + ur_addtimers = User->HasRightTo(UR_EDITTIMERS); + ur_deltimers = User->HasRightTo(UR_DELTIMERS); + ur_delrecs = User->HasRightTo(UR_DELRECS); + ur_useremote = User->HasRightTo(UR_USEREMOTE); + ur_startreplay = User->HasRightTo(UR_STARTREPLAY); + ur_switchchnl = User->HasRightTo(UR_SWITCHCHNL); + ur_addstimers = User->HasRightTo(UR_EDITSTIMERS); + ur_delstimers = User->HasRightTo(UR_DELSTIMERS); + editUser = User; + } + else + { + ur_editsetup = true; + ur_addtimers = true; + ur_deltimers = true; + ur_delrecs = true; + ur_useremote = true; + ur_startreplay = true; + ur_switchchnl = true; + ur_addstimers = true; + ur_delstimers = true; + } + +<& pageelems.doc_type &> + + + VDR Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> + + + <& pageelems.logo &> + <& menu active=("users") &> +
+
+ + + + + + + + + + + + + + + + + + + + + + +
<$ pageTitle $>
<$ tr("Name" ) $>:
<$ tr("Password" ) $>:
<$ tr("User rights") $>:
+ /> +
+ /> +
+ /> +
+ /> +
+ /> +
+ /> +
+ /> +
+<%cpp> + if (LiveFeatures< features::epgsearch >().Recent()) { + + /> +
+ /> +
+<%cpp> + } + +
+
+ + +
+
+
+
+ + +<%include>page_exit.eh diff --git a/pages/users.ecpp b/pages/users.ecpp new file mode 100644 index 0000000..f884e91 --- /dev/null +++ b/pages/users.ecpp @@ -0,0 +1,80 @@ +<%pre> +#include +#include +#include "users.h" +#include "setup.h" + +using namespace vdrlive; +using namespace std; + + +<%args> + // input parameters + string userid; + string action; + +<%session scope="global"> +bool logged_in(false); + +<%include>page_init.eh +<%cpp> +if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html"); + +<%cpp> + pageTitle = tr("Users"); + if ( !userid.empty() ) { + if (action == "delete") + { + Users.Del(Users.GetByUserId( userid )); + Users.Save(); + } + } + +<& pageelems.doc_type &> + + + VDR-Live - <$ pageTitle $> + <& pageelems.stylesheets &> + <& pageelems.ajax_js &> + + + <& pageelems.logo &> + <& menu active=("users") component=("users.user_actions")> +
+ + + + + + + +<%cpp> + cUser* user = Users.First(); + while (user) + { + bool bottom = (Users.Next(user) == NULL); + if (user) + { + + + + + + +<%cpp> + } + user = Users.Next(user); + } + +
+
<$ pageTitle $>
+
<$ tr("Name") $>
+
">
<$ user->Name() $>
">" alt="" <& tooltip.hint text=(tr("Edit user")) &>>">" alt="" <& tooltip.hint text=(tr("Delete user")) &>>
+
+ + +<%include>page_exit.eh + +<%def user_actions> +<$ tr("New user") $> + diff --git a/users.cpp b/users.cpp new file mode 100644 index 0000000..d68ec1c --- /dev/null +++ b/users.cpp @@ -0,0 +1,200 @@ +/* + * users.cpp: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: users.cpp,v 1.0 2009/08/27 13:00:00 winni Exp $ + */ + +#include "users.h" +#include +#include +#include "tools.h" +#include "setup.h" + +namespace vdrlive { + +using namespace std; + +std::string cUsers::logged_in_user; + +// -- cUser ----------------------------------------------------------------- +cUser::cUser(int ID, const std::string& Name, const std::string& Password) + : m_ID(ID), m_Name(Name) +{ + SetPassword(Password); +} + +void cUser::SetPassword(const std::string Password) +{ + ostringstream passwordStr; + passwordStr << Password.size() << "|" << MD5Hash(Password); + m_PasswordMD5 = passwordStr.str(); +} + +int cUser::GetPasswordLength() const +{ + // format is : + vector< string > parts = StringSplit( m_PasswordMD5, '|' ); + return (parts.size() > 0) ? lexical_cast< int >( parts[0] ) : 0; +} + +std::string const cUser::GetMD5HashPassword() const +{ + // format is : + vector< string > parts = StringSplit( m_PasswordMD5, '|' ); + return (parts.size() > 1) ? parts[1] : ""; +} + +bool cUser::Parse(const char *s) +{ + char *line; + char *pos; + char *pos_next; + int parameter = 1; + int valuelen; +#define MAXVALUELEN (10 * MaxFileName) + + char value[MAXVALUELEN]; + + pos = line = strdup(s); + pos_next = pos + strlen(pos); + if (*pos_next == '\n') *pos_next = 0; + while (*pos) { + while (*pos == ' ') pos++; + if (*pos) { + if (*pos != ':') { + pos_next = strchr(pos, ':'); + if (!pos_next) + pos_next = pos + strlen(pos); + valuelen = pos_next - pos + 1; + if (valuelen > MAXVALUELEN) + { + esyslog("entry '%s' is too long. Will be truncated!", pos); + valuelen = MAXVALUELEN; + } + strn0cpy(value, pos, valuelen); + pos = pos_next; + + switch (parameter) { + case 1: m_ID = lexical_cast< int >(value); + break; + case 2: m_Name = value; + break; + case 3: m_PasswordMD5 = value; + break; + case 4: + m_Userrights = lexical_cast< int >(value); + break; + default: + break; + } //switch + } + parameter++; + } + if (*pos) pos++; + } //while + + free(line); + return (parameter >= 4) ? true : false; +} + +const char *cUser::ToText(void) +{ + char* buffer = NULL; + asprintf(&buffer, "%d:%s:%s:%d", m_ID, m_Name.c_str(), m_PasswordMD5.c_str(), m_Userrights); + return buffer; +} + +bool cUser::Save(FILE *f) +{ + return fprintf(f, "%s\n", ToText()) > 0; +} + +bool cUser::HasRightTo(eUserRights right) +{ + return ((m_Userrights & (1 << (right-1))) != 0); +} + +bool cUser::CurrentUserHasRightTo(eUserRights right) +{ + if (!LiveSetup().UseAuth()) return true; + cUser* user = cUsers::GetByUserName(cUsers::logged_in_user); + return (cUsers::logged_in_user == LiveSetup().GetAdminLogin() || (user && (user->m_Userrights & (1 << (right-1))) != 0)); +} + +void cUser::SetRight(eUserRights right) +{ + isyslog("set right '%d' in '%d'", right, m_Userrights); + m_Userrights |= (1 << (right-1)); + isyslog("now rights are '%d'", m_Userrights); +} + +bool cUsers::Delete(const std::string& Name) +{ + cUser* user = Users.First(); + while (user) + { + if (user->Name() == Name) + { + Users.Del(user); + Users.Save(); + return true; + } + user = Users.Next(user); + } + return false; +} + +cUser* cUsers::GetByUserId(const std::string& Id) +{ + cUser* user = Users.First(); + while (user) + { + if (user->Id() == atoi(Id.c_str())) + return user; + user = Users.Next(user); + } + return NULL; +} + +cUser* cUsers::GetByUserName(const std::string& Name) +{ + cUser* user = Users.First(); + while (user) + { + if (user->Name() == Name) + return user; + user = Users.Next(user); + } + return NULL; +} + +int cUsers::GetNewId() +{ + int iMaxId = -1; + cUser* user = Users.First(); + while (user) + { + if (iMaxId < user->Id()) + iMaxId = user->Id(); + user = Users.Next(user); + } + return iMaxId + 1; +} + +bool cUsers::ValidUserLogin(const std::string& login, const std::string& password) +{ + cUser* user = GetByUserName(login); + if (user && MD5Hash(password) == user->GetMD5HashPassword()) + return true; + return false; +} + +bool cUsers::ValidLogin(const std::string& login, const std::string& password) +{ + return ((login == LiveSetup().GetAdminLogin() && MD5Hash(password) == LiveSetup().GetMD5HashAdminPassword()) || + ValidUserLogin(login, password)); +} + +} diff --git a/users.h b/users.h new file mode 100644 index 0000000..b845352 --- /dev/null +++ b/users.h @@ -0,0 +1,69 @@ +#ifndef VDR_LIVE_USERS_H +#define VDR_LIVE_USERS_H + +#include +#include +#include +#include +#include + +namespace vdrlive { + +enum eUserRights +{ + UR_EDITSETUP=1, + UR_EDITTIMERS, + UR_DELTIMERS, + UR_DELRECS, + UR_USEREMOTE, + UR_STARTREPLAY, + UR_SWITCHCHNL, + UR_EDITSTIMERS, + UR_DELSTIMERS +}; + +// --- cUser -------------------------------------------------------- +class cUser : public cListObject { + int m_ID; + std::string m_Name; + std::string m_PasswordMD5; + int m_Userrights; +public: + cUser() : m_ID(-1), m_Userrights(0) {} + cUser(int ID, const std::string& Name, const std::string& Password); + int Id() const { return m_ID; } + std::string Name() const { return m_Name; } + std::string PasswordMD5() const { return m_PasswordMD5; } + int Userrights() const { return m_Userrights; } + int GetPasswordLength() const; + std::string const GetMD5HashPassword() const; + void SetId(int Id) { m_ID = Id; } + void SetName(const std::string Name) { m_Name = Name; } + void SetPassword(const std::string Password); + void SetUserrights(int Userrights) { m_Userrights = Userrights; } + bool HasRightTo(eUserRights right); + static bool CurrentUserHasRightTo(eUserRights right); + void SetRight(eUserRights right); + bool Parse(const char *s); + const char *ToText(void); + bool Save(FILE *f); +}; + +// --- cUsers -------------------------------------------------------- +class cUsers : public cConfig { + public: + bool ValidUserLogin(const std::string& login, const std::string& password); + bool ValidLogin(const std::string& login, const std::string& password); + bool Delete(const std::string& Name); + static cUser* GetByUserId(const std::string& Id); + static cUser* GetByUserName(const std::string& Name); + int GetNewId(); + + static std::string logged_in_user; +}; + +extern cUsers Users; + +} + +#endif -- cgit v1.2.3