IDM API Design and Layout
-------------------------

To think about this, we need to look at what the eventual structure of the CLI will look like as
it roughly maps to the same operations.

The cli layout will be (roughly, not actual final product):

::

    - raw
    | - search
    | - create
    | - modify
    | - delete
    - recycle_bin
    | - list
    | - display (view, get)
    | - search
    | - revive (is restore better)
    - self
    | - display
    | - set_credential (--appid/primary, --password, --totp, --webauthn, or combinations?)
    | - reset_radius_password
    | - add_credential_claim
    | - remove_credential_claim
    | - set_name
    | - set_displayname
    | - set_legalname
    | - add_sshpublickey
    | - remove_sshpublickey
    | - modify (with --arg, could we get this from schema)
    | - get_radius_android
    | - get_radius_ios_macos
    | - get_radius_config
    - account
    | - list
    | - display
    | - create
    | - delete
    | - modify
    | - reset_credential
    | - add_credential_claim
    | - remove_credential_claim
    | - set_name
    | - set_displayname
    | - set_legalname
    | - enroll_sshpublickey
    | - remove_sshpublickey
    | - lock
    | - unlock
    | - expire_at
    - group
    | - list
    | - display
    | - create
    | - delete
    | - modify
    | - add_members
    | - remove_members
    - claims
    | - list
    | - display
    | - create
    | - delete
    | - modify
    | - set_credential_policy
    - access_profiles
    | - list
    | - display
    | - create
    | - delete
    | - modify
    | - enable
    | - disable
    - schema
    | - class
    |   - list
    |   - get
    |   - create
    |   - add_may_attribute
    |   - add_must_attribute
    | - attribute
    |   - list
    |   - get
    |   - create
    |   - query_class (--may, --must)
    - radius
    | - TBD

To support this, I think we need to break the api resources down in a similar pattern. We'd need
to think about how this looks with rest ...

raw
===

This is the server's internal CRUD (well, CSMD) protocol exposed at a low level
for batch operations if required. We could simply have /raw take a list of
the CUD/CMD ops for a real batching system ...

::

    /v1/raw/search
        POST -> search request
    /v1/raw/create
        POST -> create request
    /v1/raw/modify
        POST -> modify request
    /v1/raw/delete
        POST -> modify request
    /v1/auth
        POST -> Auth requests

account
=======

::

    /v1/account/
        GET -> list all account ids
        POST -> create new account
    /v1/account/{id}
        GET -> display account
        PUT -> overwrite account attrs
        PATCH -> update via diff
        DELETE -> delete this account
    /v1/account/{id}/_attr/{attr}
        GET -> display this attr
        PUT -> overwrite this attr value list
        POST -> append this list to attr
        DELETE -> purge this attr
    /v1/account/{id}/_lock
        POST -> lock this account until time (or null for permanent)
        DELETE -> unlock this account
    /v1/account/{id}/_credential
        GET -> list the credentials
        DELETE ->
    /v1/account/{id}/_credential/{id}/_lock
        POST -> lock this credential until time (or null for permanent)
        DELETE -> unlock this account
    /v1/account/{id}/_radius
        GET -> get the accounts radius credentials
        (note: more methods to come to update/reset this credential
    /v1/account/{id}/_radius/_token
        GET -> let's the radius server get all required details for radius to work


self
====

Modify and perform actions on self - generally this is an extension of capability
from account and person, but combined to one.

::

    /v1/self
        GET -> view self (aka whoami)
        PUT -> overwrite self content
        PATCH -> update self via diff
    /v1/self/_attr/{attr}
        GET -> view self attribute.
        PUT -> overwrite attr
        POST -> append list of attr
        DELETE -> purge attr
    /v1/self/_credential
        (note: more to come re setting/updating credentials, see account)
    /v1/self/_radius
        GET -> list radius cred
        (note: more to come re setting/updating this credential)
    /v1/self/_radius/_config
        POST -> create new config link w_ secret key?
    /v1/self/_radius/_config/{secret_key}
        GET -> get radius config json (no auth needed, secret_key is OTP)
    /v1/self/_radius/_config/{secret_key}/apple
        GET -> get radius config profile for apple (secret_key is OTP)
    /v1/self/_radius/_config/{secret_key}/android
        GET -> get radius config profile for android (secret_key is OTP)

group
=====

::

    /v1/group
        GET -> list all group ids
        POST -> create new group
    /v1/group/{id}
        GET -> get this group id
        PUT -> overwrite group content
        PATCH -> update via diff
        DELETE -> whole entry
    /v1/group/{id}/_attr/{attr}
        GET -> get this groups attr
        PUT -> overwrite this group attr value list
        POST -> append this list to group attr
        DELETE -> purge this attr (if body empty) or the elements listed in the body

schema
======

Schema defines how we structure and store attributes, so we need a way to query
this and see what it contains.

::

    /v1/schema
        GET -> list all class and attr types

::

    /v1/schema/classtype
        GET -> list schema class names
        POST -> create new class
    /v1/schema/classtype/{id}
        GET -> list schema class
        PUT -> overwrite schema content
        PATCH -> update via diff
    /v1/schema/classtype/{id}/_attr/{attr}
        GET -> list value of attr
        PUT -> overwrite attr value
        POST -> append list of values to attr
        DELETE -> purge attr

::

    /v1/schema/attributetype
        GET -> list schema class names
        POST -> create new class
    /v1/schema/attributetype/{id}
        GET -> list schema class
        PUT -> overwrite schema content
        PATCH -> update via diff
    /v1/schema/attributetype/{id}/_attr/{attr}
        GET -> list value of attr
        PUT -> overwrite attr value
        POST -> append list of values to attr
        DELETE -> purge attr

claims
======

TBD

recycle_bin
===========

List and restore from the recycle bin if possible.

::

    /v1/recycle_bin/
        GET -> list
    /v1/recycle_bin/{id}
        GET -> view recycled type
    /v1/recycle_bin/{id}/_restore
        POST -> restore this id.

access_profile
==============

::

    /v1/access_profiles
        GET -> list
        POST -> create new acp
    /v1/access_profiles/{id}
        GET -> display acp
        PUT -> overwrite acp
        PATCH -> update via diff
        DELETE -> delete this acp
    /v1/access_profiles/{id}/_attr
        GET -> list value of attr
        PUT -> overwrite attr value
        POST -> append list of values to attr
        DELETE -> purge attr


References
==========

Great resource on api design
https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design

Has a great section on filtering strings that we should implement
https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md


Azure AD api as inspiration.
https://docs.microsoft.com/en-au/previous-versions/azure/ad/graph/api/functions-and-actions#changePassword

https://docs.microsoft.com/en-au/previous-versions/azure/ad/graph/api/users-operations

https://docs.microsoft.com/en-au/previous-versions/azure/ad/graph/api/groups-operations

https://github.com/mozilla-services/fernet-rs/blob/master/src/lib.rs

Other Notes
===========

What about a sudo/temporal claim assignment for pw change instead?
-- temporal claim that requires re-auth to add?
-- similar for self-write?

claims:
- enforce cred policy
- may not always be granted
- need a reauth+claim request interface
- claims must be able to be scoped by time
- uat signed/tamper proof
  - similar when bearer.

- pw reset links must expire
  - url should be a bearer signed containing expiry

  - similar for radius profile view, should have a limited time scope on url.



