// 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.

library fuchsia.auth.account.internal;

using fuchsia.auth;
using fuchsia.auth.account;

// The control channel for an AccountHandler component.
//
// This interface is intended only for use by the AccountManager component that
// starts instances of AccountHandler. We define which account the handler
// should be handling one time via this channel rather than via startup flags to
// provide additional flexibility given the range of scenarios:
// * The account is completely new
// * The account is being added to the current device for the first time
// * Account information is already present on the local disk and is readable
// * Account information is already present on the local disk but is not yet
//   readable because the disk is not yet decrypted.
[Discoverable]
protocol AccountHandlerControl {
    // Creates a completely new Fuchsia account.
    //
    // |context| An |AccountHandlerContext| that can supply account and
    //           authentication services and contextual state.
    // |id| The new account's local identifier.
    //
    // Returns: |status| A |Status| indicating whether the operation was
    //                   successful
    CreateAccount(
        AccountHandlerContext context,
        fuchsia.auth.account.LocalAccountId id)
        -> (fuchsia.auth.account.Status status);

    // Loads information about a Fuchsia account that was previously provisioned
    // on the current device.
    //
    // |context| An |AccountHandlerContext| that can supply account and
    //           authentication services and contextual state.
    // |id| The account's local identifier.
    //
    // Returns: |status| A |Status| indicating whether the operation was
    //                   successful
    LoadAccount(
        AccountHandlerContext context,
        fuchsia.auth.account.LocalAccountId id)
        -> (fuchsia.auth.account.Status status);

    // Deletes all persistent information about the Fuchsia account handled by
    // this handler, including all credentials and global identifiers. After a
    // successful call to RemoveAccount, all other open interfaces for this
    // account handler will be closed and any subsequent calls on the current
    // interface will fail.
    //
    // Returns: |status| A |Status| indicating whether the operation was
    //                   successful
    RemoveAccount() -> (fuchsia.auth.account.Status status);

    // TODO(jsankey): Add methods to cover adding an existing account and
    // handling an account where the disk is not yet decrypted.

    // Connects an interface to read properties of and perform operations on
    // the account handled by this handler. The account must have previously
    // been initialized using CreateAccount or LoadAccount, otherwise the call
    // will fail with a status of NOT_FOUND.
    //
    // |context_provider| An |AuthenticationContextProvider| capable of
    //                    supplying UI contexts used for interactive
    //                    authentication on this account
    // |account| The server end of an |Account| channel
    //
    // Returns: |status| A |Status| indicating whether the operation was
    //                   successful
    GetAccount(
        fuchsia.auth.AuthenticationContextProvider auth_context_provider,
        request<fuchsia.auth.account.Account> account)
        -> (fuchsia.auth.account.Status status);

    // Signals that the AccountHandler should tear itself down. After the
    // receiver responds by closing its handle, the caller may terminate the
    // component if it hasn't already exited.
    Terminate();
};

// An interface that supplies the account and authentication services that
// an AccountHandler needs to perform its role in the system.
//
// In the v2 Component architecture this service will be supplied into the
// namespace of AccountHandler by the component that launches it (i.e. the
// AccountManager).  Until then an AccountHandlerContext is supplied explicitly
// in the initialization calls on the AccountHandlerControl interface.
protocol AccountHandlerContext {
    // Connects an interface to a particular AuthProvider, launching it if
    // necessary.
    //
    // |auth_provider_type| An OAuth identity provider matching a configuration
    //                      set in an AuthProviderConfig.auth_provider_type
    // |auth_provider| The server end of an |AuthProvider| channel
    //
    // Returns: |status| A |Status| indicating whether the operation was
    //                   successful
    GetAuthProvider(string auth_provider_type,
                    request<fuchsia.auth.AuthProvider> auth_provider)
        -> (fuchsia.auth.account.Status status);
};
