user_manager.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. #include "user_manager.h"
  2. #include "jwt_auth.h"
  3. #include <nlohmann/json.hpp>
  4. #include <fstream>
  5. #include <filesystem>
  6. #include <sstream>
  7. #include <iomanip>
  8. #include <algorithm>
  9. #include <regex>
  10. #include <crypt.h>
  11. #include <unistd.h>
  12. #include <pwd.h>
  13. #include <shadow.h>
  14. #include <sys/types.h>
  15. #include <openssl/sha.h>
  16. using json = nlohmann::json;
  17. // Define static permission constants
  18. const std::string UserManager::Permissions::READ = "read";
  19. const std::string UserManager::Permissions::GENERATE = "generate";
  20. const std::string UserManager::Permissions::QUEUE_MANAGE = "queue_manage";
  21. const std::string UserManager::Permissions::MODEL_MANAGE = "model_manage";
  22. const std::string UserManager::Permissions::USER_MANAGE = "user_manage";
  23. const std::string UserManager::Permissions::ADMIN = "admin";
  24. UserManager::UserManager(const std::string& dataDir,
  25. AuthMethod authMethod,
  26. bool enableUnixAuth)
  27. : m_dataDir(dataDir)
  28. , m_authMethod(authMethod)
  29. , m_unixAuthEnabled(enableUnixAuth)
  30. {
  31. }
  32. UserManager::~UserManager() {
  33. shutdown();
  34. }
  35. bool UserManager::initialize() {
  36. try {
  37. // Create data directory if it doesn't exist
  38. std::filesystem::create_directories(m_dataDir);
  39. // Load existing user data
  40. if (!loadUserData()) {
  41. // Create default admin user if no users exist
  42. if (m_users.empty()) {
  43. auto [success, adminId] = createUser("admin", "admin123", "admin@localhost", UserRole::ADMIN, "system");
  44. if (!success) {
  45. return false;
  46. }
  47. }
  48. }
  49. // Load existing API key data
  50. loadApiKeyData();
  51. return true;
  52. } catch (const std::exception& e) {
  53. return false;
  54. }
  55. }
  56. void UserManager::shutdown() {
  57. // Save data before shutdown
  58. saveUserData();
  59. saveApiKeyData();
  60. }
  61. AuthResult UserManager::authenticateUser(const std::string& username, const std::string& password) {
  62. AuthResult result;
  63. result.success = false;
  64. try {
  65. // Find user by username
  66. auto it = m_users.find(username);
  67. if (it == m_users.end()) {
  68. result.errorMessage = "User not found";
  69. result.errorCode = "USER_NOT_FOUND";
  70. return result;
  71. }
  72. const UserInfo& user = it->second;
  73. // Check if user is active
  74. if (!user.active) {
  75. result.errorMessage = "User account is disabled";
  76. result.errorCode = "ACCOUNT_DISABLED";
  77. return result;
  78. }
  79. // Verify password
  80. if (!verifyPassword(password, user.passwordHash)) {
  81. result.errorMessage = "Invalid password";
  82. result.errorCode = "INVALID_PASSWORD";
  83. return result;
  84. }
  85. // Authentication successful
  86. result.success = true;
  87. result.userId = user.id;
  88. result.username = user.username;
  89. result.role = user.role;
  90. result.permissions = user.permissions;
  91. // Update last login time
  92. m_users[username].lastLoginAt = getCurrentTimestamp();
  93. saveUserData();
  94. } catch (const std::exception& e) {
  95. result.errorMessage = "Authentication failed: " + std::string(e.what());
  96. result.errorCode = "AUTH_ERROR";
  97. }
  98. return result;
  99. }
  100. AuthResult UserManager::authenticateUnix(const std::string& username) {
  101. AuthResult result;
  102. result.success = false;
  103. if (!m_unixAuthEnabled) {
  104. result.errorMessage = "Unix authentication is disabled";
  105. result.errorCode = "UNIX_AUTH_DISABLED";
  106. return result;
  107. }
  108. try {
  109. // Get user information from system
  110. struct passwd* pw = getpwnam(username.c_str());
  111. if (!pw) {
  112. result.errorMessage = "Unix user not found";
  113. result.errorCode = "UNIX_USER_NOT_FOUND";
  114. return result;
  115. }
  116. // Check if user exists in our system or create guest user
  117. UserInfo user;
  118. auto it = m_users.find(username);
  119. if (it != m_users.end()) {
  120. user = it->second;
  121. } else {
  122. // Create guest user for Unix authentication
  123. user.id = generateUserId();
  124. user.username = username;
  125. user.email = username + "@localhost";
  126. user.role = roleToString(UserRole::USER);
  127. user.permissions = getDefaultPermissions(UserRole::USER);
  128. user.active = true;
  129. user.createdAt = getCurrentTimestamp();
  130. user.createdBy = "system";
  131. m_users[username] = user;
  132. saveUserData();
  133. }
  134. // Authentication successful
  135. result.success = true;
  136. result.userId = user.id;
  137. result.username = user.username;
  138. result.role = user.role;
  139. result.permissions = user.permissions;
  140. } catch (const std::exception& e) {
  141. result.errorMessage = "Unix authentication failed: " + std::string(e.what());
  142. result.errorCode = "UNIX_AUTH_ERROR";
  143. }
  144. return result;
  145. }
  146. AuthResult UserManager::authenticateApiKey(const std::string& apiKey) {
  147. AuthResult result;
  148. result.success = false;
  149. try {
  150. // Hash the API key to compare with stored hashes
  151. std::string keyHash = hashApiKey(apiKey);
  152. auto it = m_apiKeyMap.find(keyHash);
  153. if (it == m_apiKeyMap.end()) {
  154. result.errorMessage = "Invalid API key";
  155. result.errorCode = "INVALID_API_KEY";
  156. return result;
  157. }
  158. const std::string& keyId = it->second;
  159. const ApiKeyInfo& keyInfo = m_apiKeys[keyId];
  160. // Check if key is active
  161. if (!keyInfo.active) {
  162. result.errorMessage = "API key is disabled";
  163. result.errorCode = "API_KEY_DISABLED";
  164. return result;
  165. }
  166. // Check expiration
  167. if (keyInfo.expiresAt > 0 && getCurrentTimestamp() >= keyInfo.expiresAt) {
  168. result.errorMessage = "API key has expired";
  169. result.errorCode = "API_KEY_EXPIRED";
  170. return result;
  171. }
  172. // Get user information
  173. auto userIt = m_users.find(keyInfo.userId);
  174. if (userIt == m_users.end()) {
  175. result.errorMessage = "API key owner not found";
  176. result.errorCode = "USER_NOT_FOUND";
  177. return result;
  178. }
  179. const UserInfo& user = userIt->second;
  180. if (!user.active) {
  181. result.errorMessage = "API key owner account is disabled";
  182. result.errorCode = "ACCOUNT_DISABLED";
  183. return result;
  184. }
  185. // Authentication successful
  186. result.success = true;
  187. result.userId = user.id;
  188. result.username = user.username;
  189. result.role = user.role;
  190. result.permissions = keyInfo.permissions.empty() ? user.permissions : keyInfo.permissions;
  191. // Update last used timestamp
  192. m_apiKeys[keyId].lastUsedAt = getCurrentTimestamp();
  193. saveApiKeyData();
  194. } catch (const std::exception& e) {
  195. result.errorMessage = "API key authentication failed: " + std::string(e.what());
  196. result.errorCode = "API_KEY_AUTH_ERROR";
  197. }
  198. return result;
  199. }
  200. std::pair<bool, std::string> UserManager::createUser(const std::string& username,
  201. const std::string& password,
  202. const std::string& email,
  203. UserRole role,
  204. const std::string& createdBy) {
  205. try {
  206. // Validate inputs
  207. if (!validateUsername(username)) {
  208. return {false, "Invalid username format"};
  209. }
  210. if (!validatePassword(password)) {
  211. return {false, "Password does not meet requirements"};
  212. }
  213. if (!validateEmail(email)) {
  214. return {false, "Invalid email format"};
  215. }
  216. // Check if user already exists
  217. if (m_users.find(username) != m_users.end()) {
  218. return {false, "User already exists"};
  219. }
  220. // Create user
  221. UserInfo user;
  222. user.id = generateUserId();
  223. user.username = username;
  224. user.email = email;
  225. user.passwordHash = hashPassword(password);
  226. user.role = roleToString(role);
  227. user.permissions = getDefaultPermissions(role);
  228. user.active = true;
  229. user.createdAt = getCurrentTimestamp();
  230. user.passwordChangedAt = getCurrentTimestamp();
  231. user.createdBy = createdBy;
  232. m_users[username] = user;
  233. saveUserData();
  234. return {true, user.id};
  235. } catch (const std::exception& e) {
  236. return {false, "Failed to create user: " + std::string(e.what())};
  237. }
  238. }
  239. std::pair<bool, std::string> UserManager::updateUser(const std::string& userId,
  240. const std::map<std::string, std::string>& updates) {
  241. try {
  242. // Find user by ID
  243. std::string username;
  244. for (const auto& pair : m_users) {
  245. if (pair.second.id == userId) {
  246. username = pair.first;
  247. break;
  248. }
  249. }
  250. if (username.empty()) {
  251. return {false, "User not found"};
  252. }
  253. UserInfo& user = m_users[username];
  254. // Update allowed fields
  255. for (const auto& update : updates) {
  256. const std::string& field = update.first;
  257. const std::string& value = update.second;
  258. if (field == "email") {
  259. if (!validateEmail(value)) {
  260. return {false, "Invalid email format"};
  261. }
  262. user.email = value;
  263. } else if (field == "role") {
  264. user.role = value;
  265. user.permissions = getDefaultPermissions(stringToRole(value));
  266. } else if (field == "active") {
  267. user.active = (value == "true" || value == "1");
  268. }
  269. }
  270. saveUserData();
  271. return {true, "User updated successfully"};
  272. } catch (const std::exception& e) {
  273. return {false, "Failed to update user: " + std::string(e.what())};
  274. }
  275. }
  276. std::pair<bool, std::string> UserManager::deleteUser(const std::string& userId,
  277. const std::string& requestingUserId) {
  278. try {
  279. // Find user by ID
  280. std::string username;
  281. for (const auto& pair : m_users) {
  282. if (pair.second.id == userId) {
  283. username = pair.first;
  284. break;
  285. }
  286. }
  287. if (username.empty()) {
  288. return {false, "User not found"};
  289. }
  290. // Check permissions
  291. if (!canManageUser(requestingUserId, userId)) {
  292. return {false, "Insufficient permissions to delete user"};
  293. }
  294. // Delete user's API keys
  295. auto it = m_apiKeys.begin();
  296. while (it != m_apiKeys.end()) {
  297. if (it->second.userId == userId) {
  298. m_apiKeyMap.erase(it->second.keyHash);
  299. it = m_apiKeys.erase(it);
  300. } else {
  301. ++it;
  302. }
  303. }
  304. // Delete user
  305. m_users.erase(username);
  306. saveUserData();
  307. saveApiKeyData();
  308. return {true, "User deleted successfully"};
  309. } catch (const std::exception& e) {
  310. return {false, "Failed to delete user: " + std::string(e.what())};
  311. }
  312. }
  313. std::pair<bool, std::string> UserManager::changePassword(const std::string& userId,
  314. const std::string& oldPassword,
  315. const std::string& newPassword,
  316. const std::string& requestingUserId) {
  317. try {
  318. // Find user by ID
  319. std::string username;
  320. for (const auto& pair : m_users) {
  321. if (pair.second.id == userId) {
  322. username = pair.first;
  323. break;
  324. }
  325. }
  326. if (username.empty()) {
  327. return {false, "User not found"};
  328. }
  329. UserInfo& user = m_users[username];
  330. // Check permissions (admin can change without old password)
  331. if (requestingUserId != userId) {
  332. if (!canManageUser(requestingUserId, userId)) {
  333. return {false, "Insufficient permissions to change password"};
  334. }
  335. } else {
  336. // User changing own password - verify old password
  337. if (!verifyPassword(oldPassword, user.passwordHash)) {
  338. return {false, "Current password is incorrect"};
  339. }
  340. }
  341. // Validate new password
  342. if (!validatePassword(newPassword)) {
  343. return {false, "New password does not meet requirements"};
  344. }
  345. // Update password
  346. user.passwordHash = hashPassword(newPassword);
  347. user.passwordChangedAt = getCurrentTimestamp();
  348. saveUserData();
  349. return {true, "Password changed successfully"};
  350. } catch (const std::exception& e) {
  351. return {false, "Failed to change password: " + std::string(e.what())};
  352. }
  353. }
  354. UserInfo UserManager::getUserInfo(const std::string& userId) {
  355. for (const auto& pair : m_users) {
  356. if (pair.second.id == userId) {
  357. return pair.second;
  358. }
  359. }
  360. return UserInfo{};
  361. }
  362. UserInfo UserManager::getUserInfoByUsername(const std::string& username) {
  363. auto it = m_users.find(username);
  364. if (it != m_users.end()) {
  365. return it->second;
  366. }
  367. return UserInfo{};
  368. }
  369. std::vector<UserInfo> UserManager::listUsers(const std::string& requestingUserId) {
  370. std::vector<UserInfo> users;
  371. // Check if requester is admin
  372. UserInfo requester = getUserInfo(requestingUserId);
  373. bool isAdmin = (requester.role == roleToString(UserRole::ADMIN));
  374. for (const auto& pair : m_users) {
  375. const UserInfo& user = pair.second;
  376. // Non-admins can only see themselves
  377. if (!isAdmin && user.id != requestingUserId) {
  378. continue;
  379. }
  380. // Don't include sensitive information for non-admins
  381. UserInfo userInfo = user;
  382. if (!isAdmin) {
  383. userInfo.passwordHash = "";
  384. userInfo.apiKeys.clear();
  385. }
  386. users.push_back(userInfo);
  387. }
  388. return users;
  389. }
  390. std::pair<bool, std::string> UserManager::createApiKey(const std::string& userId,
  391. const std::string& name,
  392. const std::vector<std::string>& permissions,
  393. int64_t expiresAt,
  394. const std::string& createdBy) {
  395. try {
  396. // Check if user exists
  397. bool userExists = false;
  398. for (const auto& pair : m_users) {
  399. if (pair.second.id == userId) {
  400. userExists = true;
  401. break;
  402. }
  403. }
  404. if (!userExists) {
  405. return {false, "User not found"};
  406. }
  407. // Generate API key
  408. std::string apiKey = JWTAuth::generateApiKey(32);
  409. std::string keyId = generateKeyId();
  410. std::string keyHash = hashApiKey(apiKey);
  411. // Create API key info
  412. ApiKeyInfo keyInfo;
  413. keyInfo.keyId = keyId;
  414. keyInfo.keyHash = keyHash;
  415. keyInfo.name = name;
  416. keyInfo.userId = userId;
  417. keyInfo.permissions = permissions;
  418. keyInfo.active = true;
  419. keyInfo.createdAt = getCurrentTimestamp();
  420. keyInfo.lastUsedAt = 0;
  421. keyInfo.expiresAt = expiresAt;
  422. keyInfo.createdBy = createdBy;
  423. m_apiKeys[keyId] = keyInfo;
  424. m_apiKeyMap[keyHash] = keyId;
  425. saveApiKeyData();
  426. return {true, apiKey};
  427. } catch (const std::exception& e) {
  428. return {false, "Failed to create API key: " + std::string(e.what())};
  429. }
  430. }
  431. std::pair<bool, std::string> UserManager::revokeApiKey(const std::string& keyId,
  432. const std::string& requestingUserId) {
  433. try {
  434. auto it = m_apiKeys.find(keyId);
  435. if (it == m_apiKeys.end()) {
  436. return {false, "API key not found"};
  437. }
  438. const ApiKeyInfo& keyInfo = it->second;
  439. // Check permissions
  440. if (keyInfo.userId != requestingUserId) {
  441. if (!canManageUser(requestingUserId, keyInfo.userId)) {
  442. return {false, "Insufficient permissions to revoke API key"};
  443. }
  444. }
  445. // Remove API key
  446. m_apiKeyMap.erase(keyInfo.keyHash);
  447. m_apiKeys.erase(it);
  448. saveApiKeyData();
  449. return {true, "API key revoked successfully"};
  450. } catch (const std::exception& e) {
  451. return {false, "Failed to revoke API key: " + std::string(e.what())};
  452. }
  453. }
  454. std::vector<ApiKeyInfo> UserManager::listApiKeys(const std::string& userId,
  455. const std::string& requestingUserId) {
  456. std::vector<ApiKeyInfo> apiKeys;
  457. // Check if requester is admin or owner
  458. UserInfo requester = getUserInfo(requestingUserId);
  459. bool isAdmin = (requester.role == roleToString(UserRole::ADMIN));
  460. bool isOwner = (requestingUserId == userId);
  461. for (const auto& pair : m_apiKeys) {
  462. const ApiKeyInfo& keyInfo = pair.second;
  463. // Filter by user ID if specified
  464. if (!userId.empty() && keyInfo.userId != userId) {
  465. continue;
  466. }
  467. // Check permissions
  468. if (!isAdmin && keyInfo.userId != requestingUserId) {
  469. continue;
  470. }
  471. // Don't include hash for non-owners
  472. ApiKeyInfo keyInfoCopy = keyInfo;
  473. if (!isOwner && !isAdmin) {
  474. keyInfoCopy.keyHash = "";
  475. }
  476. apiKeys.push_back(keyInfoCopy);
  477. }
  478. return apiKeys;
  479. }
  480. ApiKeyInfo UserManager::getApiKeyInfo(const std::string& keyId,
  481. const std::string& requestingUserId) {
  482. auto it = m_apiKeys.find(keyId);
  483. if (it == m_apiKeys.end()) {
  484. return ApiKeyInfo{};
  485. }
  486. const ApiKeyInfo& keyInfo = it->second;
  487. // Check permissions
  488. UserInfo requester = getUserInfo(requestingUserId);
  489. bool isAdmin = (requester.role == roleToString(UserRole::ADMIN));
  490. bool isOwner = (keyInfo.userId == requestingUserId);
  491. if (!isAdmin && !isOwner) {
  492. return ApiKeyInfo{};
  493. }
  494. // Don't include hash for non-owners
  495. ApiKeyInfo keyInfoCopy = keyInfo;
  496. if (!isOwner) {
  497. keyInfoCopy.keyHash = "";
  498. }
  499. return keyInfoCopy;
  500. }
  501. void UserManager::updateApiKeyLastUsed(const std::string& keyId) {
  502. auto it = m_apiKeys.find(keyId);
  503. if (it != m_apiKeys.end()) {
  504. it->second.lastUsedAt = getCurrentTimestamp();
  505. saveApiKeyData();
  506. }
  507. }
  508. bool UserManager::hasPermission(const std::string& userId, const std::string& permission) {
  509. UserInfo user = getUserInfo(userId);
  510. if (user.id.empty()) {
  511. return false;
  512. }
  513. return JWTAuth::hasPermission(user.permissions, permission);
  514. }
  515. bool UserManager::hasAnyPermission(const std::string& userId,
  516. const std::vector<std::string>& permissions) {
  517. UserInfo user = getUserInfo(userId);
  518. if (user.id.empty()) {
  519. return false;
  520. }
  521. return JWTAuth::hasAnyPermission(user.permissions, permissions);
  522. }
  523. std::string UserManager::roleToString(UserRole role) {
  524. switch (role) {
  525. case UserRole::GUEST: return "guest";
  526. case UserRole::USER: return "user";
  527. case UserRole::ADMIN: return "admin";
  528. case UserRole::SERVICE: return "service";
  529. default: return "unknown";
  530. }
  531. }
  532. UserManager::UserRole UserManager::stringToRole(const std::string& roleStr) {
  533. if (roleStr == "guest") return UserRole::GUEST;
  534. if (roleStr == "user") return UserRole::USER;
  535. if (roleStr == "admin") return UserRole::ADMIN;
  536. if (roleStr == "service") return UserRole::SERVICE;
  537. return UserRole::USER; // Default
  538. }
  539. std::vector<std::string> UserManager::getDefaultPermissions(UserRole role) {
  540. switch (role) {
  541. case UserRole::GUEST:
  542. return {Permissions::READ};
  543. case UserRole::USER:
  544. return {Permissions::READ, Permissions::GENERATE};
  545. case UserRole::ADMIN:
  546. return {Permissions::READ, Permissions::GENERATE, Permissions::QUEUE_MANAGE,
  547. Permissions::MODEL_MANAGE, Permissions::USER_MANAGE, Permissions::ADMIN};
  548. case UserRole::SERVICE:
  549. return {Permissions::READ, Permissions::GENERATE, Permissions::QUEUE_MANAGE};
  550. default:
  551. return {};
  552. }
  553. }
  554. void UserManager::setAuthMethod(AuthMethod method) {
  555. m_authMethod = method;
  556. }
  557. UserManager::AuthMethod UserManager::getAuthMethod() const {
  558. return m_authMethod;
  559. }
  560. void UserManager::setUnixAuthEnabled(bool enable) {
  561. m_unixAuthEnabled = enable;
  562. }
  563. bool UserManager::isUnixAuthEnabled() const {
  564. return m_unixAuthEnabled;
  565. }
  566. std::map<std::string, int> UserManager::getStatistics() {
  567. std::map<std::string, int> stats;
  568. stats["total_users"] = m_users.size();
  569. stats["active_users"] = 0;
  570. stats["admin_users"] = 0;
  571. stats["total_api_keys"] = m_apiKeys.size();
  572. stats["active_api_keys"] = 0;
  573. stats["expired_api_keys"] = 0;
  574. int64_t currentTime = getCurrentTimestamp();
  575. for (const auto& pair : m_users) {
  576. const UserInfo& user = pair.second;
  577. if (user.active) {
  578. stats["active_users"]++;
  579. }
  580. if (user.role == roleToString(UserRole::ADMIN)) {
  581. stats["admin_users"]++;
  582. }
  583. }
  584. for (const auto& pair : m_apiKeys) {
  585. const ApiKeyInfo& keyInfo = pair.second;
  586. if (keyInfo.active) {
  587. stats["active_api_keys"]++;
  588. }
  589. if (keyInfo.expiresAt > 0 && currentTime >= keyInfo.expiresAt) {
  590. stats["expired_api_keys"]++;
  591. }
  592. }
  593. return stats;
  594. }
  595. std::string UserManager::hashPassword(const std::string& password) {
  596. // Simple SHA256 hash for now (in production, use proper password hashing like bcrypt/argon2)
  597. unsigned char hash[SHA256_DIGEST_LENGTH];
  598. SHA256((unsigned char*)password.c_str(), password.length(), hash);
  599. std::stringstream ss;
  600. for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
  601. ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
  602. }
  603. return "sha256:" + ss.str();
  604. }
  605. bool UserManager::verifyPassword(const std::string& password, const std::string& storedHash) {
  606. // Simple SHA256 verification (in production, use proper password hashing)
  607. if (storedHash.substr(0, 7) != "sha256:") {
  608. return false;
  609. }
  610. unsigned char hash[SHA256_DIGEST_LENGTH];
  611. SHA256((unsigned char*)password.c_str(), password.length(), hash);
  612. std::stringstream ss;
  613. for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
  614. ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
  615. }
  616. return "sha256:" + ss.str() == storedHash;
  617. }
  618. std::string UserManager::hashApiKey(const std::string& apiKey) {
  619. // Use SHA256 for API key hashing
  620. unsigned char hash[SHA256_DIGEST_LENGTH];
  621. SHA256((unsigned char*)apiKey.c_str(), apiKey.length(), hash);
  622. std::stringstream ss;
  623. for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
  624. ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
  625. }
  626. return ss.str();
  627. }
  628. std::string UserManager::generateUserId() {
  629. return "user_" + std::to_string(getCurrentTimestamp()) + "_" +
  630. std::to_string(rand() % 10000);
  631. }
  632. std::string UserManager::generateKeyId() {
  633. return "key_" + std::to_string(getCurrentTimestamp()) + "_" +
  634. std::to_string(rand() % 10000);
  635. }
  636. bool UserManager::saveUserData() {
  637. try {
  638. json usersJson = json::object();
  639. for (const auto& pair : m_users) {
  640. const UserInfo& user = pair.second;
  641. json userJson = {
  642. {"id", user.id},
  643. {"username", user.username},
  644. {"email", user.email},
  645. {"password_hash", user.passwordHash},
  646. {"role", user.role},
  647. {"permissions", user.permissions},
  648. {"api_keys", user.apiKeys},
  649. {"active", user.active},
  650. {"created_at", user.createdAt},
  651. {"last_login_at", user.lastLoginAt},
  652. {"password_changed_at", user.passwordChangedAt},
  653. {"created_by", user.createdBy}
  654. };
  655. usersJson[user.username] = userJson;
  656. }
  657. std::string filename = m_dataDir + "/users.json";
  658. std::ofstream file(filename);
  659. if (!file.is_open()) {
  660. return false;
  661. }
  662. file << usersJson.dump(2);
  663. file.close();
  664. return true;
  665. } catch (const std::exception& e) {
  666. return false;
  667. }
  668. }
  669. bool UserManager::loadUserData() {
  670. try {
  671. std::string filename = m_dataDir + "/users.json";
  672. std::ifstream file(filename);
  673. if (!file.is_open()) {
  674. return false; // File doesn't exist is OK for first run
  675. }
  676. json usersJson;
  677. file >> usersJson;
  678. file.close();
  679. m_users.clear();
  680. for (auto& item : usersJson.items()) {
  681. const std::string& username = item.key();
  682. json& userJson = item.value();
  683. UserInfo user;
  684. user.id = userJson.value("id", "");
  685. user.username = userJson.value("username", username);
  686. user.email = userJson.value("email", "");
  687. user.passwordHash = userJson.value("password_hash", "");
  688. user.role = userJson.value("role", "user");
  689. user.permissions = userJson.value("permissions", std::vector<std::string>{});
  690. user.apiKeys = userJson.value("api_keys", std::vector<std::string>{});
  691. user.active = userJson.value("active", true);
  692. user.createdAt = userJson.value("created_at", 0);
  693. user.lastLoginAt = userJson.value("last_login_at", 0);
  694. user.passwordChangedAt = userJson.value("password_changed_at", 0);
  695. user.createdBy = userJson.value("created_by", "system");
  696. m_users[username] = user;
  697. }
  698. return true;
  699. } catch (const std::exception& e) {
  700. return false;
  701. }
  702. }
  703. bool UserManager::saveApiKeyData() {
  704. try {
  705. json apiKeysJson = json::object();
  706. for (const auto& pair : m_apiKeys) {
  707. const ApiKeyInfo& keyInfo = pair.second;
  708. json keyJson = {
  709. {"key_id", keyInfo.keyId},
  710. {"key_hash", keyInfo.keyHash},
  711. {"name", keyInfo.name},
  712. {"user_id", keyInfo.userId},
  713. {"permissions", keyInfo.permissions},
  714. {"active", keyInfo.active},
  715. {"created_at", keyInfo.createdAt},
  716. {"last_used_at", keyInfo.lastUsedAt},
  717. {"expires_at", keyInfo.expiresAt},
  718. {"created_by", keyInfo.createdBy}
  719. };
  720. apiKeysJson[keyInfo.keyId] = keyJson;
  721. }
  722. std::string filename = m_dataDir + "/api_keys.json";
  723. std::ofstream file(filename);
  724. if (!file.is_open()) {
  725. return false;
  726. }
  727. file << apiKeysJson.dump(2);
  728. file.close();
  729. return true;
  730. } catch (const std::exception& e) {
  731. return false;
  732. }
  733. }
  734. bool UserManager::loadApiKeyData() {
  735. try {
  736. std::string filename = m_dataDir + "/api_keys.json";
  737. std::ifstream file(filename);
  738. if (!file.is_open()) {
  739. return false; // File doesn't exist is OK for first run
  740. }
  741. json apiKeysJson;
  742. file >> apiKeysJson;
  743. file.close();
  744. m_apiKeys.clear();
  745. m_apiKeyMap.clear();
  746. for (auto& item : apiKeysJson.items()) {
  747. const std::string& keyId = item.key();
  748. json& keyJson = item.value();
  749. ApiKeyInfo keyInfo;
  750. keyInfo.keyId = keyJson.value("key_id", keyId);
  751. keyInfo.keyHash = keyJson.value("key_hash", "");
  752. keyInfo.name = keyJson.value("name", "");
  753. keyInfo.userId = keyJson.value("user_id", "");
  754. keyInfo.permissions = keyJson.value("permissions", std::vector<std::string>{});
  755. keyInfo.active = keyJson.value("active", true);
  756. keyInfo.createdAt = keyJson.value("created_at", 0);
  757. keyInfo.lastUsedAt = keyJson.value("last_used_at", 0);
  758. keyInfo.expiresAt = keyJson.value("expires_at", 0);
  759. keyInfo.createdBy = keyJson.value("created_by", "system");
  760. m_apiKeys[keyId] = keyInfo;
  761. m_apiKeyMap[keyInfo.keyHash] = keyId;
  762. }
  763. return true;
  764. } catch (const std::exception& e) {
  765. return false;
  766. }
  767. }
  768. int64_t UserManager::getCurrentTimestamp() {
  769. return std::chrono::duration_cast<std::chrono::seconds>(
  770. std::chrono::system_clock::now().time_since_epoch()).count();
  771. }
  772. bool UserManager::validateUsername(const std::string& username) {
  773. if (username.length() < 3 || username.length() > 32) {
  774. return false;
  775. }
  776. // Username should contain only alphanumeric characters, underscores, and hyphens
  777. std::regex pattern("^[a-zA-Z0-9_-]+$");
  778. return std::regex_match(username, pattern);
  779. }
  780. bool UserManager::validatePassword(const std::string& password) {
  781. if (password.length() < 8 || password.length() > 128) {
  782. return false;
  783. }
  784. // Password should contain at least one letter and one digit
  785. bool hasLetter = false;
  786. bool hasDigit = false;
  787. for (char c : password) {
  788. if (std::isalpha(c)) hasLetter = true;
  789. if (std::isdigit(c)) hasDigit = true;
  790. }
  791. return hasLetter && hasDigit;
  792. }
  793. bool UserManager::validateEmail(const std::string& email) {
  794. if (email.length() < 5 || email.length() > 254) {
  795. return false;
  796. }
  797. // Basic email validation
  798. std::regex pattern("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
  799. return std::regex_match(email, pattern);
  800. }
  801. bool UserManager::canManageUser(const std::string& requestingUserId, const std::string& targetUserId) {
  802. // Users can always manage themselves
  803. if (requestingUserId == targetUserId) {
  804. return true;
  805. }
  806. // Check if requester is admin
  807. UserInfo requester = getUserInfo(requestingUserId);
  808. return requester.role == roleToString(UserRole::ADMIN);
  809. }