From b3fb75e51ac47f5731e26d261bb3ccd266de6cff Mon Sep 17 00:00:00 2001
From: Cedric CAFFY <cedric.caffy@cern.ch>
Date: Wed, 4 Mar 2020 12:15:12 +0100
Subject: [PATCH] Implemented Catalogue::modifyVirtualOrganizationName() + unit
 tests

---
 catalogue/Catalogue.hpp             |  8 ++++++
 catalogue/CatalogueRetryWrapper.hpp |  4 +++
 catalogue/CatalogueTest.cpp         | 43 +++++++++++++++++++++++++++++
 catalogue/DummyCatalogue.hpp        |  1 +
 catalogue/RdbmsCatalogue.cpp        | 39 ++++++++++++++++++++++++++
 catalogue/RdbmsCatalogue.hpp        |  8 ++++++
 6 files changed, 103 insertions(+)

diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp
index b0bc95b3c6..483c29b121 100644
--- a/catalogue/Catalogue.hpp
+++ b/catalogue/Catalogue.hpp
@@ -245,6 +245,14 @@ public:
    */
   virtual std::list<common::dataStructures::VirtualOrganization> getVirtualOrganizations() const = 0;
   
+  /**
+   * Modifies the name of the specified Virtual Organization.
+   *
+   * @param currentVoName The current name of the Virtual Organization.
+   * @param newVoName The new name of the Virtual Organization.
+   */
+  virtual void modifyVirtualOrganizationName(const common::dataStructures::SecurityIdentity &admin, const std::string &currentVoName, const std::string &newVoName) = 0;
+  
   /**
    * Creates the specified storage class.
    *
diff --git a/catalogue/CatalogueRetryWrapper.hpp b/catalogue/CatalogueRetryWrapper.hpp
index 2da57cb123..0c405e6a56 100644
--- a/catalogue/CatalogueRetryWrapper.hpp
+++ b/catalogue/CatalogueRetryWrapper.hpp
@@ -127,6 +127,10 @@ public:
   std::list<common::dataStructures::VirtualOrganization> getVirtualOrganizations() const override {
     return retryOnLostConnection(m_log, [&]{return m_catalogue->getVirtualOrganizations();}, m_maxTriesToConnect);
   }
+  
+  void modifyVirtualOrganizationName(const common::dataStructures::SecurityIdentity &admin, const std::string &currentVoName, const std::string &newVoName) override {
+    return retryOnLostConnection(m_log, [&]{return m_catalogue->modifyVirtualOrganizationName(admin,currentVoName,newVoName);}, m_maxTriesToConnect);
+  }
     
   void createStorageClass(const common::dataStructures::SecurityIdentity &admin, const common::dataStructures::StorageClass &storageClass) override {
     return retryOnLostConnection(m_log, [&]{return m_catalogue->createStorageClass(admin, storageClass);}, m_maxTriesToConnect);
diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp
index 0720529395..29f3c16a9c 100644
--- a/catalogue/CatalogueTest.cpp
+++ b/catalogue/CatalogueTest.cpp
@@ -15381,4 +15381,47 @@ TEST_P(cta_catalogue_CatalogueTest, getVirtualOrganizations) {
   ASSERT_EQ(0,vos.size());
 }
 
+TEST_P(cta_catalogue_CatalogueTest, modifyVirtualOrganization) {
+  using namespace cta;
+
+  common::dataStructures::VirtualOrganization vo;
+  vo.name = "vo";
+  vo.comment = "comment";
+  
+  ASSERT_NO_THROW(m_catalogue->createVirtualOrganization(m_admin,vo));
+  
+  std::string newVoName = "NewVoName";
+  
+  ASSERT_NO_THROW(m_catalogue->modifyVirtualOrganizationName(m_admin,vo.name,newVoName));
+  
+  auto vos = m_catalogue->getVirtualOrganizations();
+  
+  auto voFront = vos.front();
+  ASSERT_EQ(newVoName,voFront.name);
+}
+
+TEST_P(cta_catalogue_CatalogueTest, modifyVirtualOrganizationDoesNotExists) {
+  using namespace cta;
+  
+  ASSERT_THROW(m_catalogue->modifyVirtualOrganizationName(m_admin,"DOES_NOT_EXIST","NEW_NAME"),cta::exception::UserError);
+}
+
+TEST_P(cta_catalogue_CatalogueTest, modifyVirtualOrganizationNameThatAlreadyExists) {
+  using namespace cta;
+  
+  std::string voName = "vo";
+  std::string vo2Name = "vo2";
+  
+  common::dataStructures::VirtualOrganization vo;
+  vo.name = voName;
+  vo.comment = "comment";
+  
+  ASSERT_NO_THROW(m_catalogue->createVirtualOrganization(m_admin,vo));
+  
+  vo.name = vo2Name;
+  ASSERT_NO_THROW(m_catalogue->createVirtualOrganization(m_admin,vo));
+  
+  ASSERT_THROW(m_catalogue->modifyVirtualOrganizationName(m_admin,"vo","vo2"),cta::exception::UserError);
+}
+
 } // namespace unitTests
diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp
index 550d21a567..5621dc5dcf 100644
--- a/catalogue/DummyCatalogue.hpp
+++ b/catalogue/DummyCatalogue.hpp
@@ -91,6 +91,7 @@ public:
   void createVirtualOrganization(const common::dataStructures::SecurityIdentity &admin, const common::dataStructures::VirtualOrganization &vo) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void deleteVirtualOrganization(const std::string &voName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   std::list<common::dataStructures::VirtualOrganization> getVirtualOrganizations() const override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  void modifyVirtualOrganizationName(const common::dataStructures::SecurityIdentity &admin, const std::string &currentVoName, const std::string &newVoName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyArchiveRouteComment(const common::dataStructures::SecurityIdentity& admin, const std::string& storageClassName, const uint32_t copyNb, const std::string& comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyArchiveRouteTapePoolName(const common::dataStructures::SecurityIdentity& admin, const std::string& storageClassName, const uint32_t copyNb, const std::string& tapePoolName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyLogicalLibraryName(const common::dataStructures::SecurityIdentity &admin, const std::string &currentName, const std::string &newName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp
index 90c09b1168..8992d6507d 100644
--- a/catalogue/RdbmsCatalogue.cpp
+++ b/catalogue/RdbmsCatalogue.cpp
@@ -485,6 +485,45 @@ std::list<common::dataStructures::VirtualOrganization> RdbmsCatalogue::getVirtua
   }
 }
 
+//------------------------------------------------------------------------------
+// modifyVirtualOrganizationName
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::modifyVirtualOrganizationName(const common::dataStructures::SecurityIdentity& admin, const std::string& currentVoName, const std::string& newVoName) {
+  try {
+    const time_t now = time(nullptr);
+    const char *const sql =
+      "UPDATE VIRTUAL_ORGANIZATION SET "
+        "VIRTUAL_ORGANIZATION_NAME = :NEW_VIRTUAL_ORGANIZATION_NAME,"
+        "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME,"
+        "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME,"
+        "LAST_UPDATE_TIME = :LAST_UPDATE_TIME "
+      "WHERE "
+        "VIRTUAL_ORGANIZATION_NAME = :CURRENT_VIRTUAL_ORGANIZATION_NAME";
+    auto conn = m_connPool.getConn();
+    if(newVoName != currentVoName){
+      if(virtualOrganizationExists(conn,newVoName)){
+        throw exception::UserError(std::string("Cannot modify the virtual organization name ") + currentVoName +". The new name : " + newVoName+" already exists in the database.");
+      }
+    }
+    auto stmt = conn.createStmt(sql);
+    stmt.bindString(":NEW_VIRTUAL_ORGANIZATION_NAME", newVoName);
+    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
+    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
+    stmt.bindUint64(":LAST_UPDATE_TIME", now);
+    stmt.bindString(":CURRENT_VIRTUAL_ORGANIZATION_NAME", currentVoName);
+    stmt.executeNonQuery();
+
+    if(0 == stmt.getNbAffectedRows()) {
+      throw exception::UserError(std::string("Cannot modify virtual organization : ") + currentVoName +
+        " because it does not exist");
+    }
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
 
 //------------------------------------------------------------------------------
 // createStorageClass
diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp
index fe7a17dddc..b1eed37ee4 100644
--- a/catalogue/RdbmsCatalogue.hpp
+++ b/catalogue/RdbmsCatalogue.hpp
@@ -230,6 +230,14 @@ public:
    * @return the list of all the Virtual Organizations
    */
   std::list<common::dataStructures::VirtualOrganization> getVirtualOrganizations() const override;
+  
+  /**
+   * Modifies the name of the specified Virtual Organization.
+   *
+   * @param currentVoName The current name of the Virtual Organization.
+   * @param newVoName The new name of the Virtual Organization.
+   */
+  void modifyVirtualOrganizationName(const common::dataStructures::SecurityIdentity &admin, const std::string &currentVoName, const std::string &newVoName) override;
 
   /**
    * Creates the specified storage class.
-- 
GitLab