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

//! AccountManager manages the overall state of Fuchsia accounts and personae on
//! a Fuchsia device, installation of the AuthProviders that are used to obtain
//! authentication tokens for these accounts, and access to TokenManagers for
//! these accounts.
//!
//! The AccountManager is the most powerful interface in the authentication
//! system and is intended only for use by the most trusted parts of the system.

#![deny(missing_docs)]

mod account_event_emitter;
mod account_handler_connection;
mod account_handler_context;
mod account_manager;
mod account_map;
mod authenticator_connection;
mod fake_account_handler_connection;
pub mod inspect;
mod prototype;
mod stored_account_list;

use crate::account_handler_connection::AccountHandlerConnectionImpl;
use crate::account_manager::AccountManager;
use anyhow::{Context as _, Error};
use fidl_fuchsia_auth::AuthProviderConfig;
use fuchsia_async as fasync;
use fuchsia_component::fuchsia_single_component_package_url;
use fuchsia_component::server::ServiceFs;
use fuchsia_inspect::Inspector;
use futures::prelude::*;
use lazy_static::lazy_static;
use log::{error, info};
use std::path::PathBuf;
use std::sync::Arc;

/// This command line flag (prefixed with `--`) results in a set of hermetic auth providers.
const DEV_AUTH_PROVIDERS_FLAG: &str = "dev-auth-providers";

/// This command line flag (prefixed with `--`) results in a set of hermetic auth mechanisms.
const DEV_AUTH_MECHANISMS_FLAG: &str = "dev-auth-mechanisms";

/// This command line flag (prefixed with `--`) starts account manager with the prototype
/// account transfer interfaces enabled.
const PROTOTYPE_TRANSFER_FLAG: &str = "prototype-account-transfer";

/// Default data directory for the AccountManager.
const DATA_DIR: &str = "/data";

lazy_static! {
    /// (Temporary) Configuration for a fixed set of authentication mechanisms,
    /// used until file-based configuration is available.
    static ref DEFAULT_AUTHENTICATION_MECHANISM_IDS: Vec<String> = vec![];

    /// Configuration for a set of fake authentication mechanisms used for
    /// testing.
    static ref DEV_AUTHENTICATION_MECHANISM_IDS: Vec<String> = vec![
        concat!("fuchsia-pkg://fuchsia.com/dev_authenticator",
                "#meta/dev_authenticator_always_succeed.cmx").to_string(),
        concat!("fuchsia-pkg://fuchsia.com/dev_authenticator",
                "#meta/dev_authenticator_always_fail_authentication.cmx").to_string(),
    ];

    /// (Temporary) Configuration for a fixed set of auth providers used until file-based
    /// configuration is available.
    static ref DEFAULT_AUTH_PROVIDERS_CONFIG: Vec<AuthProviderConfig> = {
        vec![AuthProviderConfig {
            auth_provider_type: "google".to_string(),
            url: fuchsia_single_component_package_url!("google_auth_provider").to_string(),
            params: None
        }]
    };

    /// Configuration for a set of fake auth providers used for testing.
    static ref DEV_AUTH_PROVIDERS_CONFIG: Vec<AuthProviderConfig> = {
        vec![AuthProviderConfig {
            auth_provider_type: "dev_auth_provider".to_string(),
            url: fuchsia_single_component_package_url!("dev_auth_provider")
            .to_string(),
            params: None
        }]
    };
}

fn main() -> Result<(), Error> {
    // Parse CLI args
    let mut opts = getopts::Options::new();
    opts.optflag(
        "",
        DEV_AUTH_PROVIDERS_FLAG,
        "use dev auth providers instead of the default set, for tests",
    );
    opts.optflag(
        "",
        DEV_AUTH_MECHANISMS_FLAG,
        "use dev authenticators instead of the default set, for tests",
    );
    opts.optflag("", PROTOTYPE_TRANSFER_FLAG, "Publish prototype account transfer interfaces.");

    let args: Vec<String> = std::env::args().collect();
    let options = opts.parse(args)?;
    let auth_provider_config: &Vec<_> = if options.opt_present(DEV_AUTH_PROVIDERS_FLAG) {
        &DEV_AUTH_PROVIDERS_CONFIG
    } else {
        &DEFAULT_AUTH_PROVIDERS_CONFIG
    };
    let auth_mechanism_ids: &Vec<_> = if options.opt_present(DEV_AUTH_MECHANISMS_FLAG) {
        &DEV_AUTHENTICATION_MECHANISM_IDS
    } else {
        &DEFAULT_AUTHENTICATION_MECHANISM_IDS
    };

    fuchsia_syslog::init_with_tags(&["auth"]).expect("Can't init logger");
    info!("Starting account manager");

    let mut executor = fasync::Executor::new().context("Error creating executor")?;

    let mut fs = ServiceFs::new();
    let inspector = Inspector::new();
    inspector.serve(&mut fs)?;

    let account_manager = Arc::new(
        AccountManager::<AccountHandlerConnectionImpl>::new(
            PathBuf::from(DATA_DIR),
            &auth_provider_config,
            &auth_mechanism_ids,
            &inspector,
        )
        .map_err(|e| {
            error!("Error initializing AccountManager: {:?}", e);
            e
        })?,
    );

    fs.dir("svc").add_fidl_service(move |stream| {
        let account_manager_clone = Arc::clone(&account_manager);
        fasync::Task::spawn(async move {
            account_manager_clone
                .handle_requests_from_stream(stream)
                .await
                .unwrap_or_else(|e| error!("Error handling AccountManager channel: {:?}", e))
        })
        .detach();
    });

    if options.opt_present(PROTOTYPE_TRANSFER_FLAG) {
        prototype::publish_account_transfer_control(&mut fs);
        prototype::publish_account_manager_peer_to_overnet()
            .unwrap_or_else(|e| error!("Error publishing AccountManagerPeer: {:?}", e));
    }

    fs.take_and_serve_directory_handle()?;

    executor.run_singlethreaded(fs.collect::<()>());
    info!("Stopping account manager");
    Ok(())
}
