Skip to content

Commit

Permalink
Add Zone to Schedule Mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxhy committed Apr 22, 2022
1 parent 7e2b38c commit 225b3f4
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 54 deletions.
2 changes: 2 additions & 0 deletions src/core/UserSecurityContext.cpp
Expand Up @@ -20,6 +20,7 @@
#include "UserSecurityContext.hpp"
#include "core/auth/Group_odb.h"
#include "core/auth/IDoor.hpp"
#include "core/auth/Zone.hpp"
#include "core/auth/User_odb.h"
#include "tools/ScheduleMapping.hpp"
#include "tools/db/DBService.hpp"
Expand Down Expand Up @@ -286,6 +287,7 @@ bool UserSecurityContext::can_read_door(
if (loaded_mapping->has_user_indirect(self()))
return true;
}
// TODO: check zones?
return false;
}

Expand Down
7 changes: 7 additions & 0 deletions src/core/auth/IZone.hpp
Expand Up @@ -20,6 +20,7 @@
#pragma once

#include "core/auth/AuthFwd.hpp"
#include "tools/db/database.hpp"
#include <memory>
#include <string>

Expand Down Expand Up @@ -80,6 +81,12 @@ class IZone : public std::enable_shared_from_this<IZone>
* Retrieve the doors associated with the zones.
*/
virtual std::vector<DoorLPtr> doors() const = 0;

/**
* Retrieve the lazy pointers to the ScheduleMapping objects that
* map this zone.
*/
virtual std::vector<Tools::ScheduleMappingLWPtr> lazy_mapping() const = 0;
};
}
}
11 changes: 11 additions & 0 deletions src/core/auth/Zone.cpp
Expand Up @@ -97,6 +97,17 @@ void Zone::add_child(ZoneLPtr zone)
children_.push_back(zone);
}

std::vector<Leosac::Tools::ScheduleMappingLWPtr> Zone::lazy_mapping() const
{
return schedules_mapping_;
}

void Zone::schedule_mapping_added(
const Leosac::Tools::ScheduleMappingPtr &sched_mapping)
{
schedules_mapping_.push_back(sched_mapping);
}

void Zone::validation_callback(odb::callback_event e, odb::database &) const
{
if (e == odb::callback_event::post_update ||
Expand Down
15 changes: 15 additions & 0 deletions src/core/auth/Zone.hpp
Expand Up @@ -20,6 +20,7 @@
#pragma once

#include "LeosacFwd.hpp"
#include "core/auth/AuthFwd.hpp"
#include "core/auth/IZone.hpp"
#include <odb/callback.hxx>

Expand Down Expand Up @@ -87,6 +88,17 @@ class Zone : public virtual IZone

virtual void add_child(ZoneLPtr zone) override;

virtual std::vector<Tools::ScheduleMappingLWPtr> lazy_mapping() const override;

/**
* A ScheduleMapping object has added this zone as part of its mapping.
*
* This method is called by the ScheduleMapping to give a chance to the
* zone to maintain its inverse vector.
* @param sched_mapping
*/
void schedule_mapping_added(const Tools::ScheduleMappingPtr &sched_mapping);

/**
* Callback function called by ODB before/after database
* operation against a Zone object.
Expand All @@ -113,6 +125,9 @@ class Zone : public virtual IZone
#pragma db value_not_null inverse(children_)
std::vector<ZoneLWPtr> parents_;

#pragma db value_not_null inverse(zones_)
std::vector<Tools::ScheduleMappingLWPtr> schedules_mapping_;

#pragma db version
const size_t version_;

Expand Down
114 changes: 71 additions & 43 deletions src/modules/auth/auth-file/FileAuthSourceMapper.cpp
Expand Up @@ -20,6 +20,7 @@
#include "FileAuthSourceMapper.hpp"
#include "core/auth/Auth.hpp"
#include "core/auth/Door.hpp"
#include "core/auth/Zone.hpp"
#include "core/auth/Group.hpp"
#include "core/auth/Interfaces/IAuthenticationSource.hpp"
#include "core/auth/ProfileMerger.hpp"
Expand Down Expand Up @@ -325,58 +326,68 @@ void FileAuthSourceMapper::map_schedules(
std::list<std::string> user_names;
std::list<std::string> group_names;
std::list<std::string> credential_names;
std::string target_door;
target_door = node.get<std::string>("door", "");
auto door(std::make_shared<Leosac::Auth::Door>());
door->alias(target_door);
doors_.push_back(door);
std::string target_door = node.get<std::string>("door", "");
std::string target_zone = node.get<std::string>("zone", "");

// lets loop over all the info we have
for (const auto &mapping_data : node)
{
if (mapping_data.first == "door")
continue;
if (mapping_data.first == "schedule")
schedule_names.push_back(mapping_data.second.data());
if (mapping_data.first == "user")
user_names.push_back(mapping_data.second.data());
if (mapping_data.first == "group")
group_names.push_back(mapping_data.second.data());
if (mapping_data.first == "credential")
credential_names.push_back(mapping_data.second.data());
if (mapping_data.first == "door")
continue;
if (mapping_data.first == "zone")
continue;
if (mapping_data.first == "schedule")
schedule_names.push_back(mapping_data.second.data());
if (mapping_data.first == "user")
user_names.push_back(mapping_data.second.data());
if (mapping_data.first == "group")
group_names.push_back(mapping_data.second.data());
if (mapping_data.first == "credential")
credential_names.push_back(mapping_data.second.data());
}

// now build object based on what we extracted.
for (const auto &schedule_name : schedule_names)
{
// Each schedule can be mapped once per ScheduleMapping, but can be
// referenced by multiple schedule mapping. What we do here is for each
// schedule in the mapping entry, we create a ScheduleMapping object.
Tools::ScheduleMappingPtr sm(std::make_shared<Tools::ScheduleMapping>());
xml_schedules_.schedules().at(schedule_name)->add_mapping(sm);

if (!door->alias().empty())
sm->add_door(door);

for (const auto &user_name : user_names)
{
UserPtr user = users_[user_name];
sm->add_user(user);
}
// now for groups
for (const auto &group_name : group_names)
{
GroupPtr grp = groups_[group_name];
sm->add_group(grp);
}
for (const auto &cred_id : credential_names)
{
DEBUG("CRED = " << cred_id);
Cred::ICredentialPtr cred = find_cred_by_alias(cred_id);
sm->add_credential(assert_cast<Cred::CredentialPtr>(cred));
}

mappings_.push_back(sm);
// Each schedule can be mapped once per ScheduleMapping, but can be
// referenced by multiple schedule mapping. What we do here is for each
// schedule in the mapping entry, we create a ScheduleMapping object.
Tools::ScheduleMappingPtr sm(std::make_shared<Tools::ScheduleMapping>());
xml_schedules_.schedules().at(schedule_name)->add_mapping(sm);

if (!target_door.empty())
{
auto door(std::make_shared<Leosac::Auth::Door>());
door->alias(target_door);
sm->add_door(door);
}

if (!target_zone.empty())
{
auto zone(std::make_shared<Leosac::Auth::Zone>());
zone->alias(target_zone);
sm->add_zone(zone);
}

for (const auto &user_name : user_names)
{
UserPtr user = users_[user_name];
sm->add_user(user);
}
// now for groups
for (const auto &group_name : group_names)
{
GroupPtr grp = groups_[group_name];
sm->add_group(grp);
}
for (const auto &cred_id : credential_names)
{
DEBUG("CRED = " << cred_id);
Cred::ICredentialPtr cred = find_cred_by_alias(cred_id);
sm->add_credential(assert_cast<Cred::CredentialPtr>(cred));
}

mappings_.push_back(sm);
}
}
}
Expand Down Expand Up @@ -520,6 +531,23 @@ add_schedule_from_mapping_to_profile(Leosac::Tools::ScheduleMappingPtr mapping,
std::static_pointer_cast<const Leosac::Tools::ISchedule>(schedule));
}
}
else if (mapping->zones().size())
{
// If we have zones, add the schedule against each zone's door (AuthTarget)
for (auto lazy_weak_zone : mapping->zones())
{
auto zone_ptr = LEOSAC_ENFORCE(lazy_weak_zone.get_eager().lock(),
"Cannot get Zone from mapping");
for (auto lazy_weak_door : zone_ptr->doors())
{
auto door_ptr = LEOSAC_ENFORCE(lazy_weak_door.get_eager(),
"Cannot get Door from Zone");
profile->addAccessSchedule(
std::make_shared<AuthTarget>(door_ptr->alias()),
std::static_pointer_cast<const Leosac::Tools::ISchedule>(schedule));
}
}
}
else
{
// No specific door, add with nullptr as a target.
Expand Down
7 changes: 0 additions & 7 deletions src/modules/auth/auth-file/FileAuthSourceMapper.hpp
Expand Up @@ -196,13 +196,6 @@ class FileAuthSourceMapper
*/
std::vector<Tools::ScheduleMappingPtr> mappings_;

/**
* We store doors object, but really we only use the name
* property.
* On door object is created for each mapping that specify a door.
*/
std::vector<Leosac::Auth::DoorPtr> doors_;

Tools::XmlNodeNameEnforcer xmlnne_;
};
using FileAuthSourceMapperPtr = std::shared_ptr<FileAuthSourceMapper>;
Expand Down
9 changes: 5 additions & 4 deletions src/modules/auth/auth-file/auth-file.md
Expand Up @@ -14,7 +14,7 @@ The module Auth-File is an **authentication backend** module.
It listens to events generated by **authentication source** module (like `Wiegand`). These events
contains credentials. This module verify the credential and either grant or deny access.
Granting or denying access means sending a message to the application. This module doesn't open a door
or perform action on its own.
or perform action on its own.


@note This module is suitable only for a low number of users / cards / groups.
Expand Down Expand Up @@ -106,7 +106,7 @@ A credentials maps to a user.
1. WiegandCard
2. PINCode
3. WiegandCardPin

All credentials type share 4 optional properties that you can configure per credentials:
1. `id`: The id of the credentials. Used when mapping credentials to schedules. This can be whatever you want,
as long as it is unique.
Expand All @@ -124,7 +124,7 @@ WiegandCard {#mod_auth_cred_wiegandcard}
-----------------------------------------

This credentials is simply a Wiegand card number. It is qualified through a string
representing the card id, and an integer representing the number of meaningful bits in
representing the card id, and an integer representing the number of meaningful bits in
the card id.

Options | Options | Description | Mandatory
Expand Down Expand Up @@ -243,7 +243,7 @@ schedules | | | | We declare our schedule

### Example {#mod_auth_sched_declare_example}

This is a simple example that declares one schedule, named `my_schedule`. It would grants access
This is a simple example that declares one schedule, named `my_schedule`. It would grants access
anytime on monday, and wednesday from 11h to 13h and from 17h to 19h.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.xml
Expand Down Expand Up @@ -281,6 +281,7 @@ schedules_mapping | | | Defines the mapping between sched
---> | ---> | group | To which group are we applying the schedules(s) | NO
---> | ---> | credential | To which credential (identified by its `id`) do we apply the schedule | NO
---> | ---> | door | Name of the auth target the mapping apply to | NO
---> | ---> | zone | Name of the auth target zone the mapping apply to | NO

Note that `schedule`, `user` and `group` can be used multiple times in the same mapping entry.

Expand Down
30 changes: 30 additions & 0 deletions src/tools/ScheduleMapping.cpp
Expand Up @@ -20,6 +20,7 @@
#include "tools/ScheduleMapping.hpp"
#include "AssertCast.hpp"
#include "core/auth/Door.hpp"
#include "core/auth/Zone.hpp"
#include "core/auth/Group.hpp"
#include "core/auth/Group_odb.h"
#include "core/auth/User.hpp"
Expand Down Expand Up @@ -99,6 +100,16 @@ bool ScheduleMapping::has_door(Auth::DoorId did) const
return false;
}

bool ScheduleMapping::has_zone(Auth::ZoneId zid) const
{
for (const auto &lazy_weak_zone : zones_)
{
if (lazy_weak_zone.object_id() == zid)
return true;
}
return false;
}

bool ScheduleMapping::has_user_indirect(Auth::UserPtr user) const
{
// Has user
Expand Down Expand Up @@ -130,6 +141,15 @@ void ScheduleMapping::add_door(const Auth::DoorLPtr &door)
door->schedule_mapping_added(shared_from_this());
}

void ScheduleMapping::add_zone(const Auth::ZoneLPtr &zone)
{
ASSERT_LOG(zone, "Cannot add a null zone to a ScheduleMapping.");

zones_.push_back(zone);
if (zone.get_eager())
zone->schedule_mapping_added(shared_from_this());
}

void ScheduleMapping::add_user(const Auth::UserLPtr &user)
{
ASSERT_LOG(user, "Cannot add a null user to a ScheduleMapping.");
Expand Down Expand Up @@ -177,11 +197,21 @@ const std::vector<Auth::DoorLWPtr> &ScheduleMapping::doors() const
return doors_;
}

const std::vector<Auth::ZoneLWPtr> &ScheduleMapping::zones() const
{
return zones_;
}

void ScheduleMapping::clear_doors()
{
doors_.clear();
}

void ScheduleMapping::clear_zones()
{
zones_.clear();
}

void ScheduleMapping::clear_users()
{
users_.clear();
Expand Down

0 comments on commit 225b3f4

Please sign in to comment.