allow to claim extensions

This commit is contained in:
Ember 'n0emis' Keske 2022-07-20 23:39:58 +02:00
parent 4382942ad8
commit 2f1347f341
No known key found for this signature in database
GPG Key ID: 00FAF748B777CF10
7 changed files with 53 additions and 11 deletions

View File

@ -333,6 +333,8 @@ cdr_finalize=UPDATE users SET inuse=(CASE WHEN inuse>0 THEN inuse-1 ELSE 0 END)
Just choose one of your RFPs as your OMM. Just choose one of your RFPs as your OMM.
Find out the MAC address and fill it in the according fields in the kea config before. Find out the MAC address and fill it in the according fields in the kea config before.
To be able to have secure sip connections between the OMM and yate, generate a 16-characters long hexadecimal sip-secret.
Create a privileged user account and add the credentials to `fieldpoc_config.json`: Create a privileged user account and add the credentials to `fieldpoc_config.json`:
``` ```
@ -341,6 +343,7 @@ Create a privileged user account and add the credentials to `fieldpoc_config.jso
"host": "10.222.222.11", "host": "10.222.222.11",
"username": "omm", "username": "omm",
"password": "<password>" "password": "<password>"
"sipsecret": "<secret>"
} }
} }
``` ```

View File

@ -45,8 +45,12 @@ help Show this info
handlers Show currently running handlers handlers Show currently running handlers
sync Start syncing sync Start syncing
queues Show queue stats queues Show queue stats
reload Reload extension config file
claim <ext> <token> claim dect extension
exit Disconnect exit Disconnect
""".encode("utf-8")) """.encode("utf-8"))
elif data == "":
continue
elif data == "quit" or data == "exit": elif data == "quit" or data == "exit":
self.request.sendall("disconnecting\n".encode("utf-8")) self.request.sendall("disconnecting\n".encode("utf-8"))
return return
@ -56,6 +60,14 @@ exit Disconnect
self.fp.queue_all({"type": "sync"}) self.fp.queue_all({"type": "sync"})
elif data == "queues": elif data == "queues":
self.request.sendall(("\n".join(["{} {}".format(name, queue.qsize()) for name, queue in self.fp.queues.items()]) + "\n").encode("utf-8")) self.request.sendall(("\n".join(["{} {}".format(name, queue.qsize()) for name, queue in self.fp.queues.items()]) + "\n").encode("utf-8"))
elif data == "reload":
self.fp.reload_config()
elif data.startswith("claim"):
data = data.split(" ")
if len(data) == 3:
self.fp.queue_all({"type": "claim", "extension": data[1], "token": data[2]})
else:
self.request.sendall("error: You have to specify calling extension and token\n".encode("utf-8"))
else: else:
self.request.sendall("Unknown command, type 'help'\n".encode("utf-8")) self.request.sendall("Unknown command, type 'help'\n".encode("utf-8"))

View File

@ -3,6 +3,7 @@
import logging import logging
import mitel_ommclient2 import mitel_ommclient2
import time import time
import hashlib
logger = logging.getLogger("fieldpoc.dect") logger = logging.getLogger("fieldpoc.dect")
@ -45,7 +46,7 @@ class Dect:
return "{}{:0>4}".format(self.temp_num_prefix, current_temp_extension) return "{}{:0>4}".format(self.temp_num_prefix, current_temp_extension)
def get_sip_password_for_number(self, num): def get_sip_password_for_number(self, num):
return num return hashlib.sha256(bytes.fromhex((self.fp.config.dect.sipsecret + str(num))[-16:])).hexdigest()[:16]
def create_and_bind_user(self, d, num): def create_and_bind_user(self, d, num):
u = self.c.create_user(num) u = self.c.create_user(num)
@ -79,10 +80,12 @@ class Dect:
e = extensions_by_num.get(user.num) e = extensions_by_num.get(user.num)
if not e: if not e:
# user in omm, but not as dect in nerd # user in omm, but not as dect in nerd
# TODO: delete in omm
if user.num.startswith(next(self.fp.extensions.extensions_by_type("temp")).num): if user.num.startswith(next(self.fp.extensions.extensions_by_type("temp")).num):
users_by_ext[user.num] = user users_by_ext[user.num] = user
users_by_uid[user.uid] = user users_by_uid[user.uid] = user
else:
pass
# TODO: delete in omm
continue continue
elif e._c['name'] != user.name: elif e._c['name'] != user.name:
self.c.set_user_name(user.uid, e._c['name']) self.c.set_user_name(user.uid, e._c['name'])
@ -135,4 +138,19 @@ class Dect:
if created_tmp_ext: if created_tmp_ext:
self.fp.queues['routing'].put({"type": "sync"}) self.fp.queues['routing'].put({"type": "sync"})
elif msg.get("type") == "claim":
e = None
for ext in self.fp.extensions.extensions_by_type("dect"):
if ext._c.get('dect_claim_token') and ext._c['dect_claim_token'] == msg.get("token")[4:]:
e = ext
break
if e:
user = next(self.c.find_users(lambda u: u.num == msg.get("extension")))
if self.fp.temp_extensions.get(user.num):
self.fp.temp_extensions.pop(user.num)
self.c.set_user_num(user.uid, e.num)
self.c.set_user_sipauth(user.uid, e.num, self.get_sip_password_for_number(e.num))
self.c.set_user_name(user.uid, e._c['name'])
self.c.connection.close() self.c.connection.close()

View File

@ -76,6 +76,10 @@ class FieldPOC:
logger.info("started components") logger.info("started components")
def reload_config(self):
self._load_extensions()
self.queue_all({"type": "sync"})
def _load_config(self): def _load_config(self):
self.config = config.Config(json.loads(self.config_file_path.read_text())) self.config = config.Config(json.loads(self.config_file_path.read_text()))

View File

@ -313,6 +313,10 @@ class BackendNerd(diffsync.DiffSync):
top_level = ["yate", "extension", "user", "forkrank", "forkrankmember"] top_level = ["yate", "extension", "user", "forkrank", "forkrankmember"]
def __init__(self, fp, *args, **kwargs):
self.fp = fp
super().__init__(*args, **kwargs)
def load(self, data): def load(self, data):
#yate_dect = self.yate( #yate_dect = self.yate(
# guru3_identifier="dect", hostname="dect", voip_listener="local" # guru3_identifier="dect", hostname="dect", voip_listener="local"
@ -366,7 +370,7 @@ class BackendNerd(diffsync.DiffSync):
user = self.user( user = self.user(
username=key, username=key,
displayname=value["name"], displayname=value["name"],
password=value.get("sip_password", key), password=value.get("sip_password", self.fp._dect.get_sip_password_for_number(key)),
user_type=user_type[value["type"]], user_type=user_type[value["type"]],
trunk=value["trunk"], trunk=value["trunk"],
static_target=value.get("static_target", ""), static_target=value.get("static_target", ""),
@ -487,7 +491,7 @@ class Routing:
logger.info("syncing") logger.info("syncing")
state_fieldpoc = BackendNerd() state_fieldpoc = BackendNerd(self.fp)
extensions = self.fp.extensions._c.copy() extensions = self.fp.extensions._c.copy()
extensions['extensions'].update(self.fp.temp_extensions) extensions['extensions'].update(self.fp.temp_extensions)
state_fieldpoc.load(extensions) state_fieldpoc.load(extensions)

View File

@ -7,6 +7,7 @@
"host": "10.222.222.11", "host": "10.222.222.11",
"username": "omm", "username": "omm",
"password": "xxx" "password": "xxx"
"sipsecret": "51df84aace052b0e75b8c1da5a6da9e2"
}, },
"yate": { "yate": {
"host": "127.0.0.1", "host": "127.0.0.1",

View File

@ -97,12 +97,12 @@
"dialout_allowed": true, "dialout_allowed": true,
"type": "temp" "type": "temp"
}, },
"9999": { "9997": {
"name": "DECT Claim Extensions", "name": "DECT Claim Extensions",
"type": "static", "type": "static",
"dialout_allowed": false, "dialout_allowed": false,
"trunk": true, "trunk": true,
"static_target": "external/nodata//opt/nerdsync/claim.py" "static_target": "external/nodata//run/current-system/sw/bin/dect_claim"
} }
} }
} }