/** * * @file RestfulController.h * @author An Tao * * Copyright 2018, An Tao. All rights reserved. * https://github.com/an-tao/drogon * Use of this source code is governed by a MIT license * that can be found in the License file. * * Drogon * */ #pragma once #include #include #include #include #include #include #include #include namespace drogon { /** * @brief this class is a helper class for the implementation of restful api * controllers generated by the drogon_ctl command. */ class DROGON_EXPORT RestfulController : trantor::NonCopyable { public: void enableMasquerading(const std::vector &pMasqueradingVector) { masquerading_ = true; masqueradingVector_ = pMasqueradingVector; for (size_t i = 0; i < masqueradingVector_.size(); ++i) { masqueradingMap_.insert( std::pair{masqueradingVector_[i], i}); } } void disableMasquerading() { masquerading_ = false; masqueradingVector_ = columnsVector_; for (size_t i = 0; i < masqueradingVector_.size(); ++i) { masqueradingMap_.insert( std::pair{masqueradingVector_[i], i}); } } void registerAJsonValidator( const std::string &fieldName, const std::function &validator) { validators_.emplace_back(fieldName, validator); } void registerAJsonValidator( const std::string &fieldName, std::function &&validator) { validators_.emplace_back(fieldName, std::move(validator)); } /** * @brief make a criteria object for searching by ORM. * * @param pJson the json object presenting search criterias. * The json object must be an array of depth 3. * for example: * [ * [ * ["color","=","red"], //AND * ["price","<",1000] * ], //OR * [ * ["color","=","white"], //AND * ["price","<",800], //AND * ["brand","!=",null] * ] * ] * @return orm::Criteria */ orm::Criteria makeCriteria(const Json::Value &pJson) noexcept(false); protected: RestfulController(const std::vector &columnsVector) : columnsVector_(columnsVector) { } std::vector fieldsSelector(const std::set &fields) { std::vector ret; for (auto &field : masqueradingVector_) { if (!field.empty() && fields.find(field) != fields.end()) { ret.emplace_back(field); } else { ret.emplace_back(std::string{}); } } return ret; } template Json::Value makeJson(const HttpRequestPtr &req, const T &obj) { auto &queryParams = req->parameters(); auto iter = queryParams.find("fields"); if (masquerading_) { if (iter != queryParams.end()) { auto fields = utils::splitStringToSet(iter->second, ","); return obj.toMasqueradedJson(fieldsSelector(fields)); } else { return obj.toMasqueradedJson(masqueradingVector_); } } else { if (iter != queryParams.end()) { auto fields = utils::splitString(iter->second, ","); return obj.toMasqueradedJson(fields); } else { return obj.toJson(); } } } bool doCustomValidations(const Json::Value &pJson, std::string &err) { for (auto &validator : validators_) { if (pJson.isMember(validator.first)) { if (!validator.second(pJson[validator.first], err)) { return false; } } } return true; } bool isMasquerading() const { return masquerading_; } const std::vector &masqueradingVector() const { return masqueradingVector_; } private: bool masquerading_{true}; std::vector masqueradingVector_; std::vector< std::pair>> validators_; std::unordered_map masqueradingMap_; const std::vector columnsVector_; }; } // namespace drogon