// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "biod/biod_storage.h"

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <sstream>
#include <utility>

#include <base/base64.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/important_file_writer.h>
#include <base/guid.h>
#include <base/json/json_reader.h>
#include <base/json/json_string_value_serializer.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <base/values.h>
#include <brillo/scoped_umask.h>

#include "biod/biometrics_manager_record.h"
#include "biod/utils.h"

namespace biod {

using base::FilePath;

namespace {
constexpr char kDaemonStorePath[] = "/run/daemon-store";
constexpr char kRecordFileName[] = "Record";
constexpr char kBiod[] = "biod";

// Members of the JSON file.
constexpr char kBioManagerMember[] = "biomanager";
constexpr char kData[] = "data";
constexpr char kLabel[] = "label";
constexpr char kRecordId[] = "record_id";
constexpr char kValidationVal[] = "match_validation_value";
constexpr char kVersionMember[] = "version";
}  // namespace

BiodStorage::BiodStorage(const std::string& biometrics_manager_name)
    : root_path_(kDaemonStorePath),
      biometrics_manager_name_(biometrics_manager_name),
      allow_access_(false) {}

void BiodStorage::SetRootPathForTesting(const base::FilePath& root_path) {
  root_path_ = root_path;
}

bool BiodStorage::WriteRecord(
    const BiodStorageInterface::RecordMetadata& record_metadata,
    base::Value data) {
  if (!allow_access_) {
    LOG(ERROR) << "Access to the storage mounts not allowed.";
    return false;
  }

  if (!record_metadata.IsValidUTF8()) {
    LOG(ERROR) << "Record contains invalid UTF8.";
    return false;
  }

  const std::string& record_id(record_metadata.record_id);
  base::Value record_value(base::Value::Type::DICTIONARY);
  record_value.SetStringKey(kLabel, record_metadata.label);
  record_value.SetStringKey(kRecordId, record_id);
  record_value.SetStringKey(kValidationVal,
                            record_metadata.GetValidationValBase64());
  record_value.SetIntKey(kVersionMember, kRecordFormatVersion);
  record_value.SetKey(kData, std::move(data));
  record_value.SetStringKey(kBioManagerMember, biometrics_manager_name_);

  std::string json_string;
  JSONStringValueSerializer json_serializer(&json_string);
  if (!json_serializer.Serialize(record_value)) {
    LOG(ERROR) << "Failed to serialize record " << LogSafeID(record_id)
               << " to JSON.";
    return false;
  }

  FilePath record_storage_filename = GetRecordFilename(record_metadata);
  if (record_storage_filename.empty()) {
    LOG(ERROR) << "Unable to get filename for record.";
    return false;
  }

  {
    brillo::ScopedUmask owner_only_umask(~(0700));

    if (!base::CreateDirectory(record_storage_filename.DirName())) {
      PLOG(ERROR) << "Cannot create directory for user "
                  << LogSafeID(record_metadata.user_id) << ".";
      return false;
    }
  }

  {
    brillo::ScopedUmask owner_only_umask(~(0600));

    if (!base::ImportantFileWriter::WriteFileAtomically(record_storage_filename,
                                                        json_string)) {
      LOG(ERROR) << "Failed to write JSON file for record "
                 << LogSafeID(record_metadata.record_id) << ".";
      return false;
    }
  }

  LOG(INFO) << "Done writing record " << LogSafeID(record_id)
            << " to file successfully. ";
  return true;
}

std::unique_ptr<std::vector<uint8_t>>
BiodStorage::ReadValidationValueFromRecord(const base::Value& record_dictionary,
                                           const FilePath& record_path) {
  std::string validation_val_str;

  const std::string* validation_val_str_ptr =
      record_dictionary.FindStringKey(kValidationVal);
  if (!validation_val_str_ptr) {
    LOG(WARNING) << "Cannot read validation value from " << record_path.value()
                 << ".";
    return nullptr;
  }
  validation_val_str = *validation_val_str_ptr;
  if (!base::Base64Decode(validation_val_str, &validation_val_str)) {
    LOG(ERROR) << "Unable to base64 decode validation value from "
               << record_path.value() << ".";
    return nullptr;
  }

  return std::make_unique<std::vector<uint8_t>>(validation_val_str.begin(),
                                                validation_val_str.end());
}

std::vector<BiodStorageInterface::Record> BiodStorage::ReadRecords(
    const std::unordered_set<std::string>& user_ids) {
  std::vector<BiodStorageInterface::Record> ret;
  for (const auto& user_id : user_ids) {
    auto result = ReadRecordsForSingleUser(user_id);
    ret.insert(ret.end(), std::make_move_iterator(result.begin()),
               std::make_move_iterator(result.end()));
  }
  return ret;
}

std::vector<BiodStorageInterface::Record> BiodStorage::ReadRecordsForSingleUser(
    const std::string& user_id) {
  std::vector<BiodStorageInterface::Record> ret;

  if (!allow_access_) {
    LOG(ERROR) << "Access to the storage mounts not yet allowed.";
    return ret;
  }

  FilePath biod_path =
      root_path_.Append(kBiod).Append(user_id).Append(biometrics_manager_name_);
  base::FileEnumerator enum_records(biod_path, false,
                                    base::FileEnumerator::FILES, "Record*");
  for (FilePath record_path = enum_records.Next(); !record_path.empty();
       record_path = enum_records.Next()) {
    auto record = ReadRecordFromPath(record_path);
    // In this function we are enumerating files, so if Optional returned
    // by ReadRecordFromPath is empty, then there is something wrong with biod.
    CHECK(record);
    record->metadata.user_id = user_id;

    ret.emplace_back(std::move(*record));
  }
  return ret;
}

base::Optional<BiodStorageInterface::Record> BiodStorage::ReadSingleRecord(
    const std::string& user_id, const std::string& record_id) {
  if (!allow_access_) {
    LOG(ERROR) << "Access to the storage mounts not yet allowed.";
    return base::nullopt;
  }

  base::FilePath record_path = root_path_.Append(kBiod)
                                   .Append(user_id)
                                   .Append(biometrics_manager_name_)
                                   .Append(kRecordFileName + record_id);

  auto record = ReadRecordFromPath(record_path);
  if (record) {
    record->metadata.user_id = user_id;
  }

  return record;
}

base::Optional<BiodStorageInterface::Record> BiodStorage::ReadRecordFromPath(
    const base::FilePath& record_path) {
  std::string json_string;

  if (!base::ReadFileToString(record_path, &json_string)) {
    LOG(ERROR) << "Failed to read the string from " << record_path.value()
               << ".";
    // Biod can't find this file.
    return base::nullopt;
  }

  // File was found. Return Record (valid or invalid) to indicate that it
  // exists.
  BiodStorageInterface::Record record;
  record.valid = false;

  // Get RecordId from path. In case of mismatch this RecordId is more
  // important because it allows upper layers to remove invalid record
  // properly.
  std::string record_id_path = record_path.BaseName().value();
  record_id_path.erase(0, sizeof(kRecordFileName) - 1);
  record.metadata.record_id = record_id_path;

  auto record_value = base::JSONReader::ReadAndReturnValueWithError(
      json_string, base::JSON_ALLOW_TRAILING_COMMAS);

  if (!record_value.value) {
    LOG_IF(ERROR, !record_value.error_message.empty())
        << "JSON error message: " << record_value.error_message << ".";
    return record;
  }

  if (!record_value.value->is_dict()) {
    LOG(ERROR) << "Value " << record_path.value() << " is not a dictionary.";
    return record;
  }
  base::Value record_dictionary = std::move(*record_value.value);

  const std::string* record_id = record_dictionary.FindStringKey(kRecordId);

  if (!record_id) {
    LOG(ERROR) << "Cannot read record id from " << record_path.value() << ".";
    return record;
  }
  // If RecordId from path is different than stored in the file then
  // record is not valid.
  if (record.metadata.record_id != *record_id) {
    LOG(ERROR) << "RecordId from path " << LogSafeID(record.metadata.record_id)
               << " is different than RecordId stored in file "
               << LogSafeID(*record_id);
    return record;
  }

  const std::string* label = record_dictionary.FindStringKey(kLabel);

  if (!label) {
    LOG(ERROR) << "Cannot read label from " << record_path.value() << ".";
    return record;
  }
  record.metadata.label = *label;

  base::Optional<int> record_format_version =
      record_dictionary.FindIntKey(kVersionMember);
  if (!record_format_version.has_value()) {
    LOG(ERROR) << "Cannot read record format version from "
               << record_path.value() << ".";
    return record;
  }
  record.metadata.record_format_version = *record_format_version;

  if (*record_format_version < 0 ||
      *record_format_version > kRecordFormatVersion) {
    LOG(ERROR) << "Invalid format version from record " << record_path.value()
               << ".";
    return record;
  }

  std::unique_ptr<std::vector<uint8_t>> validation_val =
      ReadValidationValueFromRecord(record_dictionary, record_path);
  // Validation value was introduced in format version 2, so it might not be
  // present in older records.
  if (!validation_val) {
    if (*record_format_version >= kRecordFormatVersion) {
      return record;
    }
    // If format version is older than 2, then it is valid old record (without
    // validation value).
    validation_val = std::make_unique<std::vector<uint8_t>>();
  }
  record.metadata.validation_val = *validation_val;

  const base::Value* data = record_dictionary.FindKey(kData);

  if (!data) {
    LOG(ERROR) << "Cannot read data from " << record_path.value() << ".";
    return record;
  }
  record.data = data->GetString();

  record.valid = true;
  return record;
}

bool BiodStorage::DeleteRecord(const std::string& user_id,
                               const std::string& record_id) {
  if (!allow_access_) {
    LOG(ERROR) << "Access to the storage mounts not yet allowed.";
    return false;
  }

  FilePath record_storage_filename = root_path_.Append(kBiod)
                                         .Append(user_id)
                                         .Append(biometrics_manager_name_)
                                         .Append(kRecordFileName + record_id);

  if (!base::PathExists(record_storage_filename)) {
    LOG(INFO) << "Trying to delete record " << LogSafeID(record_id)
              << " which does not exist on disk.";
    return true;
  }
  if (!base::DeleteFile(record_storage_filename)) {
    LOG(ERROR) << "Fail to delete record " << LogSafeID(record_id)
               << " from disk.";
    return false;
  }
  LOG(INFO) << "Done deleting record " << LogSafeID(record_id) << " from disk.";
  return true;
}

std::string BiodStorage::GenerateNewRecordId() {
  std::string record_id(base::GenerateGUID());
  // dbus member names only allow '_'
  std::replace(record_id.begin(), record_id.end(), '-', '_');
  return record_id;
}

base::FilePath BiodStorage::GetRecordFilename(
    const BiodStorageInterface::RecordMetadata& record_metadata) {
  std::vector<FilePath> paths = {
      FilePath(kBiod), FilePath(record_metadata.user_id),
      FilePath(biometrics_manager_name_),
      FilePath(kRecordFileName + record_metadata.record_id)};

  FilePath record_storage_filename = root_path_;
  for (const auto& path : paths) {
    if (path.IsAbsolute()) {
      LOG(ERROR) << "Path component must not be absolute: '" << path << "'";
      return base::FilePath();
    }
    record_storage_filename = record_storage_filename.Append(path);
  }

  return record_storage_filename;
}

}  // namespace biod
