1 /// 2 /// User data, privileges, details and preferences implementation. 3 /// @file user.h - pianod project 4 /// @author Perette Barella 5 /// @date Initial: 2012-03-20. Split from users.c: 2014-11-20. 6 /// @copyright Copyright 2012-2020 Devious Fish. All rights reserved. 7 /// 8 9 #pragma once 10 11 #include <config.h> 12 13 #include <string> 14 #include <unordered_map> 15 16 #include <parsnip.h> 17 18 #include "logging.h" 19 #include "fundamentals.h" 20 #include "enumeratedarray.h" 21 #include "datastore.h" 22 23 /// User types in ascending ranks/level of authority 24 enum class Rank { 25 None, ///< User is unauthorized to do anything except log in. 26 Listener, ///< User can query and view song-related data, but not change selections. 27 Standard, ///< User can query, choose playlist, request music, change volume. 28 Administrator ///< User has full authorization, except for accessing others' private data. 29 }; 30 31 /// User privilege flags, corresponding to an array position. 32 enum class Privilege { 33 Service, ///< User may add or remove sources. (Automatic for admin rank.) 34 Queue, ///< User may queue or cancel songs. (Automatic for standard rank.) 35 Influence, ///< User's playlist preferences influence autotuning selections. 36 Tuner, ///< User may set other users' presence, for autotuning. 37 Shadow, ///< Attribute: User was created automatically, shadowing a user account. 38 Present, ///< Attribute: Consider user present, even if not logged in. 39 Count 40 }; 41 42 /// Postfix increment operator to allow Privilege iteration. 43 static inline Privilege operator++(Privilege &p, int) { 44 Privilege prior = p; 45 p = static_cast<Privilege>(int (prior) + 1); 46 return prior; 47 } 48 49 50 class PianodService; 51 52 /// Data about each user 53 class User { 54 friend class UserManager; 55 static bool shadow_mode; 56 static time_t write_time; 57 private: 58 typedef enum user_write_priority_t { 59 CRITICAL = 1, ///< User removal, privilege change, etc. 60 IMPORTANT = 10, ///< User creation 61 NOMINAL = 60, ///< Sources, preferences, data attachments, etc. 62 TRIVIAL = 300 ///< Ratings 63 } WritePriority; 64 std::string name; ///< User's login name 65 std::string password; ///< Encrypted password 66 Rank rank = Rank::None; ///< Assigned rank. 67 EnumeratedArray<Privilege, bool> privileges; ///< Assigned privileges. 68 // Note: effective privileges may be different, an effect of rank. 69 70 using UserDataPair = std::pair <std::string, UserData::DataStore *>; 71 using UserDataMap = std::unordered_map <std::string, UserData::DataStore *>; 72 UserDataMap data; ///< Data sets attached to the user 73 74 static void scheduleWrite (WritePriority priority); 75 public: 76 User (const std::string &username, const std::string &pass, bool encrypt = false); 77 User (const User &) = delete; 78 User &operator=(const User &) = delete; 79 User (User &&) = default; 80 User &operator=(User &&) = default; 81 ~User (); username(void)82 inline const std::string &username (void) const { return name; }; 83 void setPassword (const char *pass); 84 bool authenticate (const char *trypass) const; authenticate(const std::string & trypass)85 bool authenticate (const std::string &trypass) const { return authenticate (trypass.c_str()); }; 86 bool changePassword (const char *old, const char *pass); 87 #ifdef SHADOW_CAPABLE 88 bool assumeShadowPassword (const char *old, const char *pass); 89 #endif 90 // Rank stuff 91 void assignRank (Rank newrank); 92 bool assignRank (const char *newrank); 93 bool haveRank (const Rank rank) const; getRank(void)94 inline Rank getRank (void) const { return rank; }; 95 const char *getRankName (void) const; 96 // Privilege stuff 97 void setPrivilege (const Privilege priv, bool setting); 98 bool havePrivilege (const Privilege priv) const; 99 // Other statusy things 100 bool online (const PianodService &service) const; 101 bool attachData (UserData::DataStore *); updateData(void)102 inline void updateData (void) { scheduleWrite (TRIVIAL); }; 103 UserData::DataStore *getData (const std::string &datatype, const std::string &dataid = "") const; 104 void removeData (const std::string &datatype, const std::string &dataid = ""); 105 protected: 106 inline bool operator < (const User &other) { 107 return name.compare (other.name); 108 } 109 inline bool operator < (const std::string &other) { 110 return name.compare (other); 111 } 112 Parsnip::SerialData persist () const; 113 114 // Static methods & Variables 115 public: 116 static Rank visitor_rank; ///< Rank for users that have not authenticated. 117 static void shadow (bool mode); shadow()118 static bool shadow () { return (shadow_mode); }; 119 static const Privilege getPrivilege (const std::string &privilege); 120 static const Rank getRank (const std::string &rank); 121 static const char *getRankName (Rank rank); 122 static const char *getPrivilegeName (Privilege privilege); getVisitorRank()123 static inline Rank getVisitorRank () { 124 return visitor_rank; 125 } 126 static bool setVisitorRank (const std::string &rank); 127 static User *getStartscriptUser (void); 128 private: 129 static bool reconstituteUserData (User &user, const Parsnip::SerialData &data); 130 static User reconstitute_user (const Parsnip::SerialData &data); 131 }; 132 133 class PianodConnection; 134 void send_privileges (PianodConnection &conn, const User *user); 135 136 namespace Football { 137 class ServiceBase; 138 } 139 140 extern void register_user_commands (Football::ServiceBase *service); 141 142