// Copyright (c) 2012 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 "login_manager/device_local_account_policy_service.h"

#include <stdint.h>

#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
#include <base/memory/scoped_ptr.h>
#include <base/message_loop/message_loop_proxy.h>
#include <base/stl_util.h>
#include <base/strings/string_util.h>
#include <chromeos/cryptohome.h>

#include "bindings/chrome_device_policy.pb.h"
#include "login_manager/dbus_error_types.h"
#include "login_manager/policy_key.h"
#include "login_manager/policy_service.h"
#include "login_manager/policy_store.h"

namespace em = enterprise_management;

namespace login_manager {

const base::FilePath::CharType DeviceLocalAccountPolicyService::kPolicyDir[] =
    FILE_PATH_LITERAL("policy");

const base::FilePath::CharType
    DeviceLocalAccountPolicyService::kPolicyFileName[] =
        FILE_PATH_LITERAL("policy");

DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
    const base::FilePath& device_local_account_dir,
    PolicyKey* owner_key,
    const scoped_refptr<base::MessageLoopProxy>& main_loop)
    : device_local_account_dir_(device_local_account_dir),
      owner_key_(owner_key),
      main_loop_(main_loop) {
}

DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
  STLDeleteValues(&policy_map_);
}

bool DeviceLocalAccountPolicyService::Store(
    const std::string& account_id,
    const uint8_t* policy_data,
    uint32_t policy_data_size,
    PolicyService::Completion completion) {
  PolicyService* service = GetPolicyService(account_id);
  if (!service) {
    PolicyService::Error error(dbus_error::kInvalidAccount,
                               "Invalid device-local account");
    completion.Run(error);
    return false;
  }

  // NB: Passing 0 for flags disallows all key changes.
  return service->Store(policy_data, policy_data_size, completion, 0);
}

bool DeviceLocalAccountPolicyService::Retrieve(
    const std::string& account_id,
    std::vector<uint8_t>* policy_data) {
  PolicyService* service = GetPolicyService(account_id);
  if (!service)
    return false;

  return service->Retrieve(policy_data);
}

void DeviceLocalAccountPolicyService::UpdateDeviceSettings(
    const em::ChromeDeviceSettingsProto& device_settings) {
  // Update the policy map.
  typedef google::protobuf::RepeatedPtrField<em::DeviceLocalAccountInfoProto>
      DeviceLocalAccountList;
  std::map<std::string, PolicyService*> new_policy_map;
  const DeviceLocalAccountList& list(
      device_settings.device_local_accounts().account());
  for (DeviceLocalAccountList::const_iterator account(list.begin());
       account != list.end();
       ++account) {
    std::string account_key;
    if (account->has_account_id()) {
      account_key = GetAccountKey(account->account_id());
    } else if (!account->has_type() &&
               account->has_deprecated_public_session_id()) {
      account_key = GetAccountKey(account->deprecated_public_session_id());
    }
    if (!account_key.empty()) {
      new_policy_map[account_key] = policy_map_[account_key];
      policy_map_[account_key] = NULL;
    }
  }
  policy_map_.swap(new_policy_map);
  STLDeleteValues(&new_policy_map);

  MigrateUppercaseDirs();

  // Purge all existing on-disk accounts that are no longer defined.
  base::FileEnumerator enumerator(
      device_local_account_dir_, false, base::FileEnumerator::DIRECTORIES);
  base::FilePath subdir;
  while (!(subdir = enumerator.Next()).empty()) {
    if (IsValidAccountKey(subdir.BaseName().value()) &&
        policy_map_.find(subdir.BaseName().value()) == policy_map_.end()) {
      LOG(INFO) << "Purging " << subdir.value();
      if (!base::DeleteFile(subdir, true))
        LOG(ERROR) << "Failed to delete " << subdir.value();
    }
  }
}

bool DeviceLocalAccountPolicyService::MigrateUppercaseDirs(void) {
  base::FileEnumerator enumerator(
      device_local_account_dir_, false, base::FileEnumerator::DIRECTORIES);
  base::FilePath subdir;

  while (!(subdir = enumerator.Next()).empty()) {
    std::string upper = subdir.BaseName().value();
    std::string lower = base::StringToLowerASCII(upper);
    if (IsValidAccountKey(lower) && lower != upper) {
      base::FilePath subdir_to(subdir.DirName().Append(lower));
      LOG(INFO) << "Migrating " << upper << " to " << lower;
      if (!base::ReplaceFile(subdir, subdir_to, NULL))
        LOG(ERROR) << "Failed to migrate " << subdir.value();
    }
  }

  return true;
}

PolicyService* DeviceLocalAccountPolicyService::GetPolicyService(
    const std::string& account_id) {
  const std::string key = GetAccountKey(account_id);
  std::map<std::string, PolicyService*>::iterator entry = policy_map_.find(key);
  if (entry == policy_map_.end())
    return NULL;

  // Lazily create and initialize the policy service instance.
  if (!entry->second) {
    const base::FilePath policy_path =
        device_local_account_dir_
        .AppendASCII(key)
        .Append(kPolicyDir)
        .Append(kPolicyFileName);
    if (!base::CreateDirectory(policy_path.DirName())) {
      LOG(ERROR) << "Failed to create directory for " << policy_path.value();
      return NULL;
    }

    scoped_ptr<PolicyStore> store(new PolicyStore(policy_path));
    if (!store->LoadOrCreate()) {
      // This is non-fatal, the policy may not have been stored yet.
      LOG(WARNING) << "Failed to load policy for device-local account "
                   << account_id;
    }
    entry->second = new PolicyService(store.Pass(), owner_key_, main_loop_);
  }

  return entry->second;
}

std::string DeviceLocalAccountPolicyService::GetAccountKey(
    const std::string& account_id) {
  return chromeos::cryptohome::home::SanitizeUserName(account_id);
}

bool DeviceLocalAccountPolicyService::IsValidAccountKey(
    const std::string& str) {
  return chromeos::cryptohome::home::IsSanitizedUserName(str);
}

}  // namespace login_manager
