// 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.identity.account;

using fuchsia.identity.authentication;
using fuchsia.io;

/// A protocol to receive events when the authentication state of an account
/// changes.
///
/// AuthListeners may be registered through the `AuthTarget` protocol and this
/// registration also defines the types of authentication state changes that
/// should be sent to the listener.
///
/// All methods include an empty response to follow the "Throttle push using
/// acknowledgements" FIDL design pattern.
closed protocol AuthListener {
    /// A method that is called when the AccountListener is first connected.
    strict OnInitialize(struct {
        auth_state AuthState;
    }) -> ();

    /// A method that is called when the authentication state of the account
    /// changes.
    strict OnAuthStateChanged(struct {
        auth_state AuthState;
    }) -> ();
};

/// A protocol that is extended by other protocols defining an entity
/// (referred to as the "target") with an authentication state, such as an
/// account or persona.
///
/// AuthTarget defines a set of methods to monitor the current authentication
/// state of an entity and to request changes in that authentication state.
closed protocol AuthTarget {
    /// Returns the current `AuthState` of the target.
    ///
    /// Returns: `auth_state` The target's current authentication state.
    strict GetAuthState() -> (struct {
        auth_state AuthState;
    }) error Error;

    /// Connects a channel that will receive changes in the authentication
    /// state of the target.
    ///
    /// `listener` [required] The client end of an `AuthListener` channel
    /// `initial_state` If true, the listener will receive the initial auth
    ///                 state in addition to any changes.
    /// `granularity` An `AuthChangeGranularity` expressing the magnitude of
    ///               change in authentication state that will lead to
    ///               AuthStateChange events.
    strict RegisterAuthListener(resource table {
        1: listener client_end:AuthListener;
        2: initial_state bool;
        3: granularity AuthChangeGranularity;
    }) -> () error Error;

    // TODO(https://fxbug.dev/42133912): Add methods that request in increase in the
    //                      authentication state or authentication for a
    //                      particular event.
};

/// A protocol that exposes information about the personae for a system account
/// and provides methods to manipulate these. It also exposes a writable data
/// directory.
///
/// An Account provides access to sensitive long term identifiers and is only
/// intended only for use by a small number of trusted system components.
closed protocol Account {
    compose AuthTarget;

    // Note: an AccountID accessor method may be added if and when the
    // first valid use case arrives.

    /// Returns the account's lifetime.
    strict GetLifetime() -> (struct {
        lifetime Lifetime;
    });

    /// Returns a vector of all the personae defined for the account.
    /// NOTE: Currently all accounts have exactly one persona.
    strict GetPersonaIds() -> (struct {
        persona_ids vector<PersonaId>:MAX_PERSONAE_PER_ACCOUNT;
    });

    /// Connects a channel to read properties of and access tokens for
    /// the default persona for the account.
    ///
    /// `persona` The server end of a `Persona` channel
    ///
    /// Returns: `id` The identifier for the default persona
    strict GetDefaultPersona(resource struct {
        persona server_end:Persona;
    }) -> (struct {
        id PersonaId;
    }) error Error;

    /// Connects a channel to read properties of and access tokens for
    /// one of the personae for the account.
    ///
    /// `id` The persona's identifier as returned by GetPersonaIds()
    /// `persona` The server end of a `Persona` channel
    strict GetPersona(resource struct {
        id PersonaId;
        persona server_end:Persona;
    }) -> () error Error;

    // TODO(https://fxbug.dev/42134023): Add methods to create, delete, and manage personae.

    /// Returns all authentication mechanism enrollments.
    strict GetAuthMechanismEnrollments() -> (struct {
        enrollments vector<AuthMechanismEnrollmentMetadata>:MAX_AUTH_MECHANISM_ENROLLMENTS;
    }) error Error;

    /// Create a new enrollment of the provided authentication mechanism,
    /// and add it to the account.
    ///
    /// `interaction` An `Interaction` channel enabling the user to enroll a new
    ///               authentication mechanism or complete authentication
    ///               challenges using an existing mechanism if these are
    ///               necessary.
    ///
    /// Returns: The `AuthMechanismEnrollmentId` of the created enrollment.
    strict CreateAuthMechanismEnrollment(resource struct {
        interaction server_end:fuchsia.identity.authentication.Interaction;
    }) -> (struct {
        enrollment_id AuthMechanismEnrollmentId;
    }) error Error;

    /// Remove an authentication mechanism enrollment for the account.
    ///
    /// `enrollment_id` The id of the enrollment to remove.
    strict RemoveAuthMechanismEnrollment(struct {
        enrollment_id AuthMechanismEnrollmentId;
    }) -> () error Error;

    /// Locks all access to an account and its storage. After a successful call,
    /// all Account and Persona channels for this account will be terminated.
    strict StorageLock() -> () error Error;

    /// Locks interaction with an account. After a successful call, the account
    /// AuthStateSummary will be set to `INTERACTION_LOCKED`.
    ///
    /// Fails with FailedPrecondition if authentication is not enabled for the
    /// account.
    strict InteractionLock() -> () error Error;

    /// Connects a channel to access a data directory of the account. The
    /// directory is writable, and is initially empty for a newly created
    /// account. The directory is persisted according to the lifetime of the
    /// account and is never modified by the account system.
    ///
    /// NOTE: This method should only be called by the root session
    /// component instance. Multiple component instance clients are not yet
    /// supported.
    ///
    /// `data_directory` The server end of a `fuchsia.io.Directory` channel
    // TODO(https://fxbug.dev/42122362): Support multiple component instance clients.
    strict GetDataDirectory(resource struct {
        data_directory server_end:fuchsia.io.Directory;
    }) -> () error Error;
};

/// A protocol that exposes basic information about a persona and access to the
/// authentication tokens that are visible through it.
///
/// Note a Persona purposefully does not provide access to a long term
/// identifier for the persona. This is to support components in the system that
/// work with short lived identifiers (e.g. SessionManager), but note that long
/// term identifiers can usually still be derived via the TokenManger protocol.
closed protocol Persona {
    compose AuthTarget;

    /// Returns the lifetime of this persona.
    strict GetLifetime() -> (struct {
        lifetime Lifetime;
    });
};
