plugin.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. // -*- Mode: c++ -*-
  18. #ifndef PLUGIN_H
  19. #define PLUGIN_H
  20. // define to see which exception is thrown from a plugin
  21. //#define EXCEPTION_DEBUG
  22. #include <kopano/zcdefs.h>
  23. #include <kopano/ECDefs.h>
  24. #include <kopano/pcuser.hpp>
  25. #include <list>
  26. #include <map>
  27. #include <memory>
  28. #include <string>
  29. #include <stdexcept>
  30. #include <iostream>
  31. #include <sstream>
  32. #include <kopano/ECLogger.h>
  33. #include <kopano/ECPluginSharedData.h>
  34. using namespace std;
  35. namespace KC {
  36. /**
  37. * @defgroup userplugin Server user plugin
  38. * @{
  39. */
  40. class ECStatsCollector;
  41. #define LOG_PLUGIN_DEBUG(_msg, ...) \
  42. ec_log(EC_LOGLEVEL_DEBUG | EC_LOGLEVEL_PLUGIN, "plugin: " _msg, ##__VA_ARGS__)
  43. /**
  44. * The objectsignature combines the object id with the
  45. * signature of that object. With the signature ECUserManagement
  46. * can determine if the object has been changed since the last
  47. * sync. This way ECUserManagement can cache things like the
  48. * object details without constantly accessing the plugin.
  49. */
  50. class objectsignature_t _kc_final {
  51. public:
  52. /**
  53. * Constructor for combining objectid and signature
  54. *
  55. * @param[in] i
  56. * The unique objectid
  57. * @param[in] s
  58. * The object signature
  59. */
  60. objectsignature_t(const objectid_t &i, const std::string &s) : id(i), signature(s) {};
  61. /**
  62. * Default constructor, creates empty objectid with empty signature
  63. */
  64. objectsignature_t(void) = default;
  65. /**
  66. * Object signature equality comparison
  67. *
  68. * @param[in] sig
  69. * Compare the objectsignature_t sig with the current object.
  70. * Only the objectid will be used for equality, the signature
  71. * will be ignored.
  72. * @return TRUE if the objects are equal
  73. */
  74. bool operator==(const objectsignature_t &sig) const { return id == sig.id; };
  75. /**
  76. * Object signature less-then comparison
  77. *
  78. * @param[in] sig
  79. * Compare the objectsignature_t sig with the current object.
  80. * Only the objectid will be used for the less-then comparison,
  81. * the signature will be ignored.
  82. * @return TRUE if the current object is less then the sig object
  83. */
  84. bool operator< (const objectsignature_t &sig) { return id.id < sig.id.id; };
  85. /**
  86. * externid with objectclass
  87. */
  88. objectid_t id;
  89. /**
  90. * Signature.
  91. * The exact contents of the signature depends on the plugin,
  92. * when checking for changes only check if the signature is different.
  93. */
  94. std::string signature;
  95. };
  96. typedef list<objectsignature_t> signatures_t;
  97. typedef list<unsigned int> abprops_t;
  98. class ECConfig;
  99. /**
  100. * Main user plugin interface
  101. *
  102. * The user plugin interface defines methods for user management.
  103. * All functions should return std_unique<> to prevent expensive copy operations
  104. * for large amount of data.
  105. */
  106. class UserPlugin {
  107. public:
  108. /**
  109. * @param[in] pluginlock
  110. * The plugin mutex
  111. * @param[in] shareddata
  112. * The singleton shared plugin data.
  113. * @throw std::exception
  114. */
  115. UserPlugin(std::mutex &pluginlock, ECPluginSharedData *shareddata) :
  116. m_plugin_lock(pluginlock), m_config(NULL),
  117. m_lpStatsCollector(shareddata->GetStatsCollector()),
  118. m_bHosted(shareddata->IsHosted()),
  119. m_bDistributed(shareddata->IsDistributed())
  120. {}
  121. virtual ~UserPlugin(void) _kc_impdtor;
  122. /**
  123. * Initialize plugin
  124. *
  125. * @throw std::exception
  126. */
  127. virtual void InitPlugin() = 0;
  128. /**
  129. * Resolve name and company to objectsignature
  130. *
  131. * @param[in] objclass
  132. * The objectclass of the name which should be resolved.
  133. * The objectclass can be partially unknown (OBJECTCLASS_UNKNOWN, MAILUSER_UNKNOWN, ...)
  134. * @param[in] name
  135. * The name which should be resolved
  136. * @param[in] company
  137. * The company beneath which the name should be searched
  138. * This objectid can be empty.
  139. * @return The object signature of the resolved object
  140. * @throw std::exception
  141. */
  142. virtual objectsignature_t resolveName(objectclass_t objclass, const string &name, const objectid_t &company) = 0;
  143. /**
  144. * Authenticate user with username and password
  145. *
  146. * @param[in] username
  147. * The username of the user to be authenticated
  148. * @param[in] password
  149. * The password of the user to be authenticated
  150. * @param[in] company
  151. * The objectid of the company to which the user belongs.
  152. * This objectid can be empty.
  153. * @return The objectsignature of the authenticated user
  154. * @throw std::exception
  155. */
  156. virtual objectsignature_t authenticateUser(const string &username, const string &password, const objectid_t &company) = 0;
  157. /**
  158. * Request a list of objects for a particular company and specified objectclass.
  159. *
  160. * @param[in] company
  161. * The company beneath which the objects should be listed.
  162. * This objectid can be empty.
  163. * @param[in] objclass
  164. * The objectclass of the objects which should be returned.
  165. * The objectclass can be partially unknown (OBJECTCLASS_UNKNOWN, MAILUSER_UNKNOWN, ...)
  166. * @return The list of object signatures of all objects which were found
  167. * @throw std::exception
  168. */
  169. virtual std::unique_ptr<signatures_t> getAllObjects(const objectid_t &company, objectclass_t objclass) = 0;
  170. /**
  171. * Obtain the object details for the given object
  172. *
  173. * @param[in] objectid
  174. * The objectid for which is details are requested
  175. * @return The objectdetails for the given objectid
  176. * @throw std::exception
  177. */
  178. virtual std::unique_ptr<objectdetails_t> getObjectDetails(const objectid_t &objectid) = 0;
  179. /**
  180. * Obtain the object details for the given objects
  181. *
  182. * @param[in] objectids
  183. * The list of object signatures for which the details are requested
  184. * @return A map of objectid with the matching objectdetails
  185. * @throw std::exception
  186. */
  187. virtual std::unique_ptr<std::map<objectid_t, objectdetails_t> > getObjectDetails(const std::list<objectid_t> &objectids) = 0;
  188. /**
  189. * Get all children for a parent for a given relation type.
  190. * For example all users in a group
  191. *
  192. * @param[in] relation
  193. * The relation type which connects the child and parent object
  194. * @param[in] parentobject
  195. * The parent object for which the children are requested
  196. * @return A list of object signatures of the children of the parent.
  197. * @throw std::exception
  198. */
  199. virtual std::unique_ptr<signatures_t> getSubObjectsForObject(userobject_relation_t relation, const objectid_t &parentobject) = 0;
  200. /**
  201. * Request all parents for a childobject for a given relation type.
  202. * For example all groups for a user
  203. *
  204. * @param[in] relation
  205. * The relation type which connects the child and parent object
  206. * @param[in] childobject
  207. * The childobject for which the parents are requested
  208. * @return A list of object signatures of the parents of the child.
  209. * @throw std::exception
  210. */
  211. virtual std::unique_ptr<signatures_t> getParentObjectsForObject(userobject_relation_t relation, const objectid_t &childobject) = 0;
  212. /**
  213. * Search for all objects which match the given string,
  214. * the name and email address should be compared for this search.
  215. *
  216. * @param[in] match
  217. * The string which should be found
  218. * @param[in] ulFlags
  219. * If EMS_AB_ADDRESS_LOOKUP the string must exactly match the name or email address
  220. * otherwise a partial match is allowed.
  221. * @return List of object signatures which match the given string
  222. * @throw std::exception
  223. */
  224. virtual std::unique_ptr<signatures_t> searchObject(const std::string &match, unsigned int ulFlags) = 0;
  225. /**
  226. * Obtain details for the public store
  227. *
  228. * @note This function is only mandatory for multi-server environments
  229. *
  230. * @return The public store details
  231. * @throw std::exception
  232. */
  233. virtual std::unique_ptr<objectdetails_t> getPublicStoreDetails(void) = 0;
  234. /**
  235. * Obtain the objectdetails for a server
  236. *
  237. * @note This function is only mandatory for multi-server environments
  238. *
  239. * @param[in] server
  240. * The externid of the server
  241. * @return The server details
  242. * @throw std::exception
  243. */
  244. virtual std::unique_ptr<serverdetails_t> getServerDetails(const std::string &server) = 0;
  245. /**
  246. * Obtain server list
  247. *
  248. * @return list of servers
  249. * @throw runtime_error LDAP query failure
  250. */
  251. virtual std::unique_ptr<serverlist_t> getServers(void) = 0;
  252. /**
  253. * Update an object with new details
  254. *
  255. * @note It is not mandatory to implement this function
  256. *
  257. * @param[in] id
  258. * The object id of the object which should be updated.
  259. * @param[in] details
  260. * The objectdetails which should be written to the object.
  261. * @param[in] lpRemove
  262. * List of configuration names which should be removed from the object
  263. * @throw std::exception
  264. */
  265. virtual void changeObject(const objectid_t &id, const objectdetails_t &details, const std::list<std::string> *lpRemove) = 0;
  266. /**
  267. * Create object in plugin
  268. *
  269. * @note It is not mandatory to implement this function
  270. *
  271. * @param[in] details
  272. * The object details of the new object.
  273. * @return The objectsignature of the created object.
  274. * @throw std::exception
  275. */
  276. virtual objectsignature_t createObject(const objectdetails_t &details) = 0;
  277. /**
  278. * Delete object from plugin
  279. *
  280. * @note It is not mandatory to implement this function
  281. *
  282. * @param[in] id
  283. * The objectid which should be deleted
  284. * @throw std::exception
  285. */
  286. virtual void deleteObject(const objectid_t &id) = 0;
  287. /**
  288. * Modify id of object in plugin
  289. *
  290. * @note It is not mandatory to implement this function
  291. *
  292. * @param[in] oldId
  293. * The old objectid
  294. * @param[in] newId
  295. * The new objectid
  296. * @throw std::exception
  297. */
  298. virtual void modifyObjectId(const objectid_t &oldId, const objectid_t &newId) = 0;
  299. /**
  300. * Add relation between child and parent. This can be used
  301. * for example to add a user to a group or add
  302. * permission relations on companies.
  303. *
  304. * @note It is not mandatory to implement this function
  305. *
  306. * @param[in] relation
  307. * The relation type which should connect the
  308. * child and parent.
  309. * @param[in] parentobject
  310. * The parent object.
  311. * @param[in] childobject
  312. * The child object.
  313. * @throw std::exception
  314. */
  315. virtual void addSubObjectRelation(userobject_relation_t relation,
  316. const objectid_t &parentobject, const objectid_t &childobject) = 0;
  317. /**
  318. * Delete relation between child and parent, this can be used
  319. * for example to delete a user from a group or delete
  320. * permission relations on companies.
  321. *
  322. * @note It is not mandatory to implement this function
  323. *
  324. * @param[in] relation
  325. * The relation type which connected the
  326. * child and parent.
  327. * @param[in] parentobject
  328. * The parent object.
  329. * @param[in] childobject
  330. * The child object.
  331. * @throw std::exception
  332. */
  333. virtual void deleteSubObjectRelation(userobject_relation_t relation,
  334. const objectid_t &parentobject, const objectid_t &childobject) = 0;
  335. /**
  336. * Get quota information from object.
  337. * There are two quota types, normal quota and userdefault quota,
  338. * the first quota is the quote for the object itself while the userdefault
  339. * quota can only be requested on containers (i.e. groups or companies) and
  340. * is the quota for the members of that container.
  341. *
  342. * @param[in] id
  343. * The objectid from which the quota should be read
  344. * @param[in] bGetUserDefault
  345. * Boolean to indicate if the userdefault quota must be requested.
  346. * @throw std::exception
  347. */
  348. virtual std::unique_ptr<quotadetails_t> getQuota(const objectid_t &id, bool bGetUserDefault) = 0;
  349. /**
  350. * Set quota information on object
  351. *
  352. * @note It is not mandatory to implement this function
  353. *
  354. * @param[in] id
  355. * The objectid which should be updated
  356. * @param[in] quotadetails
  357. * The quota information which should be written to the object
  358. * @throw std::exception
  359. */
  360. virtual void setQuota(const objectid_t &id, const quotadetails_t &quotadetails) = 0;
  361. /**
  362. * Get extra properties which are set in the object details for the addressbook
  363. *
  364. * @note It is not mandatory to implement this function
  365. *
  366. * @return a list of properties
  367. * @throw std::exception
  368. */
  369. virtual std::unique_ptr<abprops_t> getExtraAddressbookProperties(void) = 0;
  370. /**
  371. * Reset entire plugin - use with care - this deletes (almost) all entries in the user database
  372. *
  373. * @param except The exception of all objects, which should NOT be deleted (usually the userid
  374. * of the caller)
  375. *
  376. */
  377. virtual void removeAllObjects(objectid_t except) = 0;
  378. protected:
  379. std::mutex &m_plugin_lock;
  380. /**
  381. * Pointer to local configuration manager.
  382. */
  383. ECConfig *m_config;
  384. /**
  385. * Pointer to statscollector
  386. */
  387. ECStatsCollector *m_lpStatsCollector;
  388. /**
  389. * Boolean to indicate if multi-company features are enabled
  390. */
  391. bool m_bHosted;
  392. /**
  393. * Boolean to indicate if multi-server features are enabled
  394. */
  395. bool m_bDistributed;
  396. };
  397. /**
  398. * Exception which is thrown when no object was found during a search
  399. */
  400. class _kc_export_throw objectnotfound _kc_final : public std::runtime_error {
  401. public:
  402. /**
  403. * @param[in] arg
  404. * The description why the exception was thrown
  405. */
  406. objectnotfound(const string &arg) : runtime_error(arg) {
  407. #ifdef EXCEPTION_DEBUG
  408. cerr << "objectnotfound exception: " << arg << endl;
  409. #endif
  410. }
  411. };
  412. /**
  413. * Exception which is thrown when too many objects where returned in
  414. * a search.
  415. */
  416. class _kc_export_throw toomanyobjects _kc_final : public std::runtime_error {
  417. public:
  418. /**
  419. * @param[in] arg
  420. * The description why the exception was thrown
  421. */
  422. toomanyobjects(const string &arg) : runtime_error(arg) {
  423. #ifdef EXCEPTION_DEBUG
  424. cerr << "toomanyobjects exception: " << arg << endl;
  425. #endif
  426. }
  427. };
  428. /**
  429. * Exception which is thrown when an object is being created
  430. * while it already existed.
  431. */
  432. class _kc_export_throw collision_error _kc_final : public std::runtime_error {
  433. public:
  434. /**
  435. * @param[in] arg
  436. * The description why the exception was thrown
  437. */
  438. collision_error(const string &arg) : runtime_error(arg) {
  439. #ifdef EXCEPTION_DEBUG
  440. cerr << "collision_error exception: " << arg << endl;
  441. #endif
  442. }
  443. };
  444. /**
  445. * Exception which is thrown when a problem has been found with
  446. * the data read from the plugin backend.
  447. */
  448. class _kc_export_throw data_error _kc_final : public std::runtime_error {
  449. public:
  450. /**
  451. * @param[in] arg
  452. * The description why the exception was thrown
  453. */
  454. data_error(const string &arg) : runtime_error(arg) {
  455. #ifdef EXCEPTION_DEBUG
  456. cerr << "data_error exception: " << arg << endl;
  457. #endif
  458. }
  459. };
  460. /**
  461. * Exception which is thrown when the function was not
  462. * implemented by the plugin.
  463. */
  464. class _kc_export_throw notimplemented _kc_final : public std::runtime_error {
  465. public:
  466. /**
  467. * @param[in] arg
  468. * The description why the exception was thrown
  469. */
  470. notimplemented(const string &arg) : runtime_error(arg) {
  471. #ifdef EXCEPTION_DEBUG
  472. cerr << "notimplemented exception: " << arg << endl;
  473. #endif
  474. }
  475. };
  476. /**
  477. * Exception which is thrown when a function is called for
  478. * an unsupported feature. This can be because a multi-company
  479. * or multi-server function is called while this feature is
  480. * disabled.
  481. */
  482. class _kc_export_throw notsupported _kc_final : public std::runtime_error {
  483. public:
  484. /**
  485. * @param[in] arg
  486. * The description why the exception was thrown
  487. */
  488. notsupported(const string &arg) : runtime_error(arg) {
  489. #ifdef EXCEPTION_DEBUG
  490. cerr << "notsupported exception: " << arg << endl;
  491. #endif
  492. }
  493. };
  494. /**
  495. * Exception which is thrown when a user could not be logged in
  496. */
  497. class _kc_export_throw login_error _kc_final : public std::runtime_error {
  498. public:
  499. /**
  500. * @param[in] arg
  501. * The description why the exception was thrown
  502. */
  503. login_error(const string &arg) : runtime_error(arg) {
  504. #ifdef EXCEPTION_DEBUG
  505. cerr << "login_error exception: " << arg << endl;
  506. #endif
  507. }
  508. };
  509. /**
  510. * Exception which is thrown when LDAP returns errors
  511. */
  512. class _kc_export_throw ldap_error _kc_final : public std::runtime_error {
  513. int m_ldaperror;
  514. public:
  515. /**
  516. * @param[in] arg
  517. * The description why the exception was thrown
  518. * @param[in] ldaperror
  519. The ldap error code why the exception was thrown
  520. */
  521. ldap_error(const string &arg, int ldaperror=0) : runtime_error(arg) {
  522. m_ldaperror = ldaperror;
  523. #ifdef EXCEPTION_DEBUG
  524. cerr << "ldap_error exception: " << arg << endl;
  525. #endif
  526. }
  527. int GetLDAPError() {return m_ldaperror;}
  528. };
  529. /**
  530. * Convert string to objecttype as specified by template Tout
  531. *
  532. * @param[in] s
  533. * The string which should be converted.
  534. * The type depends on template Tin.
  535. * @return The objecttype Tout which was converted from string
  536. */
  537. template <class Tin, class Tout>
  538. static inline Tout fromstring(const Tin &s) {
  539. istringstream i(s);
  540. Tout res;
  541. i >> res;
  542. return res;
  543. }
  544. /**
  545. * Convert input to string using ostringstream
  546. *
  547. * @param[in] i
  548. * Input which should be converted to string
  549. * The type depends on template Tin.
  550. * @return The string representation of i
  551. */
  552. template <class Tin>
  553. static inline string tostring(const Tin i) {
  554. ostringstream o;
  555. o << i;
  556. return o.str();
  557. }
  558. /** @} */
  559. } /* namespace */
  560. #endif