blob: ae5460b3d96adbb0c0cb9e5affca41fd92e478fe [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "biod/cros_fp_session_manager_impl.h"
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <base/base64.h>
#include "biod/biod_storage.h"
#include "biod/cros_fp_record_manager.h"
namespace biod {
using SessionRecord = CrosFpSessionManager::SessionRecord;
CrosFpSessionManagerImpl::CrosFpSessionManagerImpl(
std::unique_ptr<CrosFpRecordManagerInterface> record_manager)
: record_manager_(std::move(record_manager)) {}
const std::optional<std::string>& CrosFpSessionManagerImpl::GetUser() const {
return user_;
}
bool CrosFpSessionManagerImpl::LoadUser(std::string user_id) {
if (user_.has_value()) {
return false;
}
std::vector<Record> records = record_manager_->GetRecordsForUser(user_id);
user_ = std::move(user_id);
for (auto record : std::move(records)) {
std::string tmpl_data_str;
base::Base64Decode(record.data, &tmpl_data_str);
VendorTemplate tmpl(tmpl_data_str.begin(), tmpl_data_str.end());
records_.push_back(CrosFpSessionManagerImpl::SessionRecord{
.record_metadata = std::move(record.metadata),
.tmpl = std::move(tmpl),
});
}
return true;
}
void CrosFpSessionManagerImpl::UnloadUser() {
user_.reset();
records_.clear();
record_manager_->RemoveRecordsFromMemory();
}
bool CrosFpSessionManagerImpl::CreateRecord(
const BiodStorageInterface::RecordMetadata& record,
std::unique_ptr<VendorTemplate> templ) {
if (!user_.has_value() || record.user_id != user_) {
LOG(ERROR) << "Can't create record when there is no active user.";
return false;
}
VendorTemplate vendor_templ = *templ;
if (!record_manager_->CreateRecord(record, std::move(templ))) {
LOG(ERROR) << "Failed to create and persist the record.";
return false;
}
records_.push_back(CrosFpSessionManagerImpl::SessionRecord{
.record_metadata = record,
.tmpl = std::move(vendor_templ),
});
return true;
}
bool CrosFpSessionManagerImpl::UpdateRecord(
const BiodStorageInterface::RecordMetadata& record_metadata,
std::unique_ptr<VendorTemplate> templ) {
const auto& record_id = record_metadata.record_id;
const auto& user_id = record_metadata.user_id;
if (!user_.has_value() || user_id != user_) {
LOG(ERROR) << "Can't update record when there is no active user.";
return false;
}
VendorTemplate vendor_templ = *templ;
if (!record_manager_->UpdateRecord(record_metadata, std::move(templ))) {
LOG(ERROR) << "Failed to update and persist the record.";
return false;
}
std::optional<size_t> match_idx = std::nullopt;
for (size_t i = 0; i < records_.size(); i++) {
if (records_[i].record_metadata.record_id == record_id) {
match_idx = i;
break;
}
}
CHECK(match_idx.has_value());
records_[*match_idx].record_metadata = record_metadata;
records_[*match_idx].tmpl = std::move(vendor_templ);
return true;
}
bool CrosFpSessionManagerImpl::HasRecordId(const std::string& record_id) {
if (!user_.has_value()) {
return false;
}
for (size_t i = 0; i < records_.size(); i++) {
if (records_[i].record_metadata.record_id == record_id) {
return true;
}
}
return false;
}
bool CrosFpSessionManagerImpl::DeleteRecord(const std::string& record_id) {
if (!user_.has_value()) {
LOG(ERROR) << "Can't delete record when there is no active user.";
return false;
}
std::optional<size_t> match_idx = std::nullopt;
for (size_t i = 0; i < records_.size(); i++) {
if (records_[i].record_metadata.record_id == record_id) {
match_idx = i;
break;
}
}
if (!match_idx.has_value()) {
LOG(WARNING) << "Deleting non-existing record.";
return false;
}
// Removing the record from persistent storage has a chance to fail. Perform
// this removal before the in-memory record removal to be sync even in case of
// failure.
if (!record_manager_->DeleteRecord(record_id)) {
LOG(ERROR) << "Failed to delete the record.";
return false;
}
records_.erase(records_.begin() + match_idx.value());
return true;
}
bool CrosFpSessionManagerImpl::DeleteNotLoadedRecord(
const std::string& user_id, const std::string& record_id) {
if (user_.has_value() && user_.value() == user_id) {
LOG(ERROR) << "Can't delete active user's record in DeleteNotLoadedRecord.";
return false;
}
return record_manager_->DeleteNotLoadedRecord(user_id, record_id);
}
std::vector<SessionRecord> CrosFpSessionManagerImpl::GetRecords() {
return records_;
}
std::optional<BiodStorageInterface::RecordMetadata>
CrosFpSessionManagerImpl::GetRecordMetadata(size_t idx) const {
if (idx < records_.size()) {
return records_[idx].record_metadata;
}
return std::nullopt;
}
size_t CrosFpSessionManagerImpl::GetNumOfTemplates() {
return records_.size();
}
} // namespace biod