~singpolyma/biboumi

ref: 0d487f40c51463a15013255990f374fa9c41e590 biboumi/src/xmpp/adhoc_commands_handler.cpp -rw-r--r-- 4.3 KiB
0d487f40 — Emmanuel Gil Peyrot Use Config::is_in_list() to allow for multiple admins 4 years ago
                                                                                
e1a7114c Florent Le Coz
ee4cf5dc louiz’
e1a7114c Florent Le Coz
265b5df6 louiz’
faed8952 louiz’
ee4cf5dc louiz’
e1a7114c Florent Le Coz
19666d2f Florent Le Coz
e1a7114c Florent Le Coz
5a5bb7f6 louiz’
e1a7114c Florent Le Coz
5a5bb7f6 louiz’
e1a7114c Florent Le Coz
0d487f40 Emmanuel Gil Peyrot
e1a7114c Florent Le Coz
5a5bb7f6 louiz’
e1a7114c Florent Le Coz
5a5bb7f6 louiz’
e1a7114c Florent Le Coz
19666d2f Florent Le Coz
e1a7114c Florent Le Coz
faed8952 louiz’
e1a7114c Florent Le Coz
e31ff3e9 louiz’
e1a7114c Florent Le Coz
faed8952 louiz’
e1a7114c Florent Le Coz
5a5bb7f6 louiz’
e1a7114c Florent Le Coz
06271729 louiz’
e1a7114c Florent Le Coz
faed8952 louiz’
e1a7114c Florent Le Coz
5a5bb7f6 louiz’
e1a7114c Florent Le Coz
5a5bb7f6 louiz’
e1a7114c Florent Le Coz
5a2e6116 louiz’
e1a7114c Florent Le Coz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <xmpp/adhoc_commands_handler.hpp>
#include <xmpp/xmpp_component.hpp>

#include <utils/timed_events.hpp>
#include <logger/logger.hpp>
#include <config/config.hpp>
#include <xmpp/jid.hpp>

#include <iostream>

using namespace std::string_literals;

const std::map<const std::string, const AdhocCommand>& AdhocCommandsHandler::get_commands() const
{
  return this->commands;
}

void AdhocCommandsHandler::add_command(std::string name, AdhocCommand command)
{
  const auto found = this->commands.find(name);
  if (found != this->commands.end())
    throw std::runtime_error("Trying to add an ad-hoc command that already exist: " + name);
  this->commands.emplace(std::make_pair(std::move(name), std::move(command)));
}

XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, const std::string& to, XmlNode command_node)
{
  std::string action = command_node.get_tag("action");
  if (action.empty())
    action = "execute";
  command_node.del_tag("action");

  Jid jid(executor_jid);

  const std::string node = command_node.get_tag("node");
  auto command_it = this->commands.find(node);
  if (command_it == this->commands.end())
    {
      XmlSubNode error(command_node, ADHOC_NS":error");
      error["type"] = "cancel";
      XmlSubNode condition(error, STANZA_NS":item-not-found");
    }
  else if (command_it->second.is_admin_only() &&
           !Config::is_in_list("admin", jid.bare()))
    {
      XmlSubNode error(command_node, ADHOC_NS":error");
      error["type"] = "cancel";
      XmlSubNode condition(error, STANZA_NS":forbidden");
    }
  else
    {
      std::string sessionid = command_node.get_tag("sessionid");
      if (sessionid.empty())
        {                       // create a new session, with a new id
          sessionid = XmppComponent::next_id();
          command_node["sessionid"] = sessionid;
          this->sessions.emplace(std::piecewise_construct,
                                 std::forward_as_tuple(sessionid, executor_jid),
                                 std::forward_as_tuple(command_it->second, executor_jid, to));
          TimedEventsManager::instance().add_event(TimedEvent(std::chrono::steady_clock::now() + 3600s,
                                                              std::bind(&AdhocCommandsHandler::remove_session, this, sessionid, executor_jid),
                                                              "adhocsession" + sessionid + executor_jid));
        }
      auto session_it = this->sessions.find(std::make_pair(sessionid, executor_jid));
      if ((session_it != this->sessions.end()) &&
          (action == "execute" || action == "next" || action == "complete"))
        {
          // execute the step
          AdhocSession& session = session_it->second;
          const AdhocStep& step = session.get_next_step();
          step(this->xmpp_component, session, command_node);
          if (session.remaining_steps() == 0 ||
              session.is_terminated())
            {
              this->sessions.erase(session_it);
              command_node["status"] = "completed";
              TimedEventsManager::instance().cancel("adhocsession" + sessionid + executor_jid);
            }
          else
            {
              command_node["status"] = "executing";
              XmlSubNode actions(command_node, "actions");
              XmlSubNode next(actions, "next");
            }
        }
      else if (session_it != this->sessions.end() && action == "cancel")
        {
          this->sessions.erase(session_it);
          command_node["status"] = "canceled";
          TimedEventsManager::instance().cancel("adhocsession" + sessionid + executor_jid);
        }
      else                      // unsupported action
        {
          XmlSubNode error(command_node, ADHOC_NS":error");
          error["type"] = "modify";
          XmlSubNode condition(error, STANZA_NS":bad-request");
        }
    }
  return command_node;
}

void AdhocCommandsHandler::remove_session(const std::string& session_id, const std::string& initiator_jid)
{
  auto session_it = this->sessions.find(std::make_pair(session_id, initiator_jid));
  if (session_it != this->sessions.end())
    {
      this->sessions.erase(session_it);
      return ;
    }
  log_error("Tried to remove ad-hoc session for [", session_id, ", ", initiator_jid, "] but none found");
}