m_identity (zotonic_core v1.0.0-rc.17)

The m_identity model manages usernames and other user identities. mod_authentication uses it to store and check salted passwords, but also provides a safe storage for user tokens of any kind, as used by mod_facebook.

Note that a user does not have to be of the person category per se, in Zotonic anything can have identities attached to it.

The following m_identity model properties are available in templates:

PropertyDescriptionExample value
is_userCheck if a page id is a user. Return a bool. Usage: m.identity[page_id].is_usertrue
usernameFetch the username, if any, of a user. Returns a binary or undefined. Usage: m.identity[page_id].username<<"admin">>

Available Model API Paths

MethodPath patternDescription
get/lookup/+type/+key/...Return all filtered identity records matching normalized identity key +key for identity type +type (propb and secret fields are stripped; admin only).
get/generate_password/...Return a newly generated random password string (z_ids:password/0).
get/is_email_verifiedReturn whether the current user’s primary email_raw has a matching verified email identity record. No further lookups.
get/is_email_verified/+userid/...Return whether user +userid has a verified identity record for its primary email_raw address (editable by caller).
get/+id/is_user/...Return whether resource +id has at least one identity of a user-defining type (auth_identity_types, default includes username_pw; requires visibility).
get/+id/username/...Return the current username identity key for resource +id (requires edit permission on +id).
get/+id/user_info/...Return user info map for +id with user_id, username, visited, modified, and is_expired; returns empty/default values when no username_pw identity exists (requires edit permission).
get/+id/logon_history/...Return login history rows (user_agent, ip_address, created) ordered by newest first for user +id (self or admin).
get/+id/all_types/...Return all identity type values present for user/resource +id; returns [] when caller cannot edit +id.
get/+id/allReturn all identities for user/resource +id as filtered identity records (admin only). No further lookups.
get/+id/all/email/...Return all filtered email identities for user +id; ensures the resource primary email is represented as an identity when valid (requires edit permission).
get/+id/all/+type/...Return filtered identity records of type +type for user/resource +id (admin only).
get/get/+idnid/...Return one filtered identity record by identity id +idnid (admin only).
get/verify/+idnid/+verifykey/...Return identity record +idnid only when +verifykey matches the stored verify_key using constant-time comparison; otherwise return undefined.
get/+id/+type/...Return identity record for type +type on user/resource +id (admin only; enoent when missing).

/+name marks a variable path segment. A trailing /... means extra path segments are accepted for further lookups.

See also

Access control, mod_authentication or mod_facebook.

Summary

Functions

Types

bcrypt_hash()

-type bcrypt_hash() :: {bcrypt, binary()}.

hash()

-type hash() :: bcrypt_hash() | sha1_salted_hash().

identity()

-type identity() :: proplists:proplist().

key()

-type key() :: atom() | binary() | string().

password()

-type password() :: iodata().

sha1_salted_hash()

-type sha1_salted_hash() :: {hash, binary(), binary()}.

type()

-type type() :: atom() | binary() | string().

Functions

check_username_pw(Username, Password, Context)

-spec check_username_pw(Username, Password, Context) -> Result
                           when
                               Username :: binary() | string(),
                               Password :: binary() | string(),
                               Context :: z:context(),
                               Result :: {ok, m_rsc:resource_id()} | {error, term()}.

check_username_pw(Username, Password, QueryArgs, Context)

-spec check_username_pw(Username, Password, QueryArgs, Context) -> Result
                           when
                               Username :: binary() | string(),
                               Password :: binary() | string(),
                               QueryArgs :: list() | map(),
                               Context :: z:context(),
                               Result :: {ok, m_rsc:resource_id()} | {error, term()}.

cleanup_logon_history(Context)

delete(IdnId, Context)

-spec delete(IdnId, Context) -> {ok, 0 | 1} | {error, eacces | term()}
                when IdnId :: integer(), Context :: z:context().

delete_by_type(Resource, Type, Context)

-spec delete_by_type(Resource, Type, Context) -> ok
                        when Resource :: m_rsc:resource(), Type :: type(), Context :: z:context().

delete_by_type_and_key(Resource, Type, Key, Context)

-spec delete_by_type_and_key(Resource, Type, Key, Context) -> ok
                                when
                                    Resource :: m_rsc:resource(),
                                    Type :: type(),
                                    Key :: key(),
                                    Context :: z:context().

delete_by_type_and_keyprefix(Resource, Type, KeyPrefix, Context)

-spec delete_by_type_and_keyprefix(Resource, Type, KeyPrefix, Context) -> ok
                                      when
                                          Resource :: m_rsc:resource(),
                                          Type :: type(),
                                          KeyPrefix :: key(),
                                          Context :: z:context().

delete_username(UserId, Context)

-spec delete_username(UserId, Context) -> ok | {error, Reason}
                         when
                             UserId :: m_rsc:resource() | undefined,
                             Context :: z:context(),
                             Reason :: eacces | enoent.

ensure_username_pw(UserId, Context)

-spec ensure_username_pw(UserId, Context) -> ok | {error, term()}
                            when UserId :: m_rsc:resource(), Context :: z:context().

ensure_username_pw(UserId, Username, Context)

-spec ensure_username_pw(UserId, Username, Context) -> ok | {error, term()}
                            when
                                UserId :: m_rsc:resource(),
                                Username :: binary() | undefined,
                                Context :: z:context().

flush(RscId, Context)

-spec flush(RscId, Context) -> ok when RscId :: m_rsc:resource_id(), Context :: z:context().

generate_username(RscId, Context)

-spec generate_username(RscId, Context) -> Username
                           when RscId :: m_rsc:resource(), Context :: z:context(), Username :: binary().

get(IdnId, Context)

-spec get(IdnId, Context) -> Identity | undefined
             when IdnId :: non_neg_integer(), Context :: z:context(), Identity :: proplists:proplist().

get_rsc(RscId, Context)

-spec get_rsc(RscId, Context) -> Identities
                 when
                     RscId :: m_rsc:resource(),
                     Context :: z:context(),
                     Identities :: [proplists:proplist()].

get_rsc(RscId, Type, Context)

-spec get_rsc(RscId, Type, Context) -> Identity | undefined
                 when
                     RscId :: m_rsc:resource_id(),
                     Type :: type(),
                     Context :: z:context(),
                     Identity :: proplists:proplist().

get_rsc_by_type(RscId, Type, Context)

-spec get_rsc_by_type(RscId, Type, Context) -> Identities
                         when
                             RscId :: m_rsc:resource(),
                             Type :: type(),
                             Context :: z:context(),
                             Identities :: [proplists:proplist()].

get_rsc_by_type_key(RscId, Type, Key, Context)

-spec get_rsc_by_type_key(RscId, Type, Key, Context) -> Identities
                             when
                                 RscId :: m_rsc:resource(),
                                 Type :: type(),
                                 Key :: key(),
                                 Context :: z:context(),
                                 Identities :: [proplists:proplist()].

get_rsc_by_type_keyprefix(RscId, Type, KeyPrefix, Context)

-spec get_rsc_by_type_keyprefix(RscId, Type, KeyPrefix, Context) -> Identities
                                   when
                                       RscId :: m_rsc:resource(),
                                       Type :: type(),
                                       KeyPrefix :: key(),
                                       Context :: z:context(),
                                       Identities :: [proplists:proplist()].

get_user_info(Context)

-spec get_user_info(Context) -> UserInfo when Context :: z:context(), UserInfo :: #{binary() => term()}.

get_user_info(RscId, Context)

-spec get_user_info(RscId, Context) -> UserInfo
                       when
                           RscId :: m_rsc:resource(),
                           Context :: z:context(),
                           UserInfo :: #{binary() => term()}.

get_username(Context)

-spec get_username(Context) -> Username | undefined when Context :: z:context(), Username :: binary().

get_username(RscId, Context)

-spec get_username(RscId, Context) -> Username | undefined
                      when RscId :: m_rsc:resource(), Context :: z:context(), Username :: binary().

hash(Pw)

-spec hash(password()) -> bcrypt_hash().

hash_is_equal/2

-spec hash_is_equal(password(), hash()) -> boolean().

insert(Rsc, Type, Key, Context)

-spec insert(Rsc, Type, Key, Context) -> {ok, IdnId} | {error, Reason}
                when
                    Rsc :: m_rsc:resource(),
                    Type :: type(),
                    Key :: key(),
                    Context :: z:context(),
                    IdnId :: pos_integer(),
                    Reason :: invalid_key.

insert(Rsc, Type, Key, Props, Context)

-spec insert(Rsc, Type, Key, Props, Context) -> {ok, IdnId} | {error, Reason}
                when
                    Rsc :: m_rsc:resource(),
                    Type :: type(),
                    Key :: key(),
                    Props :: proplists:proplist(),
                    Context :: z:context(),
                    IdnId :: pos_integer(),
                    Reason :: invalid_key.

insert_single(Rsc, Type, Key, Context)

-spec insert_single(m_rsc:resource(), type(), key(), z:context()) ->
                       {ok, pos_integer()} | {error, invalid_key}.

insert_single(Rsc, Type, Key, Props, Context)

insert_unique(RscId, Type, Key, Context)

insert_unique(RscId, Type, Key, Props, Context)

is_email_verified(Context)

is_email_verified(UserId, Context)

is_equal(Extern, Secret)

-spec is_equal(Extern :: binary(), Secret :: binary()) -> boolean().

is_peer_allowed(Context)

is_peer_allowed_admin(Context)

is_reserved_name/1

is_user(RscId, Context)

-spec is_user(RscId, Context) -> boolean() when RscId :: m_rsc:resource(), Context :: z:context().

is_username_local(Value, Context)

-spec is_username_local(Value, Context) -> boolean()
                           when Value :: binary() | string() | undefined, Context :: z:context().

is_valid_key/3

-spec is_valid_key(type(), undefined | key(), z:context()) -> boolean().

is_verified(RscId, Context)

-spec is_verified(m_rsc:resource_id(), z:context()) -> boolean().

logon_history/2

-spec logon_history(m_rsc:resource_id(), z:context()) ->
                       {ok, [{UserAgent, IpAddress, Created}]} | {error, eacces}
                       when UserAgent :: binary(), IpAddress :: binary(), Created :: calendar:datetime().

lookup_by_type_and_key(Type, Key, Context)

-spec lookup_by_type_and_key(type(), key(), z:context()) -> identity() | undefined.

lookup_by_type_and_key_multi(Type, Key, Context)

-spec lookup_by_type_and_key_multi(type(), key(), z:context()) -> [identity()].

lookup_by_username(Key, Context)

-spec lookup_by_username(key(), z:context()) -> identity() | undefined.

lookup_by_verify_key(Key, Context)

-spec lookup_by_verify_key(key(), z:context()) -> identity() | undefined.

lookup_users_by_type_and_key(Type, Key, Context)

-spec lookup_users_by_type_and_key(type(), key(), z:context()) -> [identity()].

lookup_users_by_verified_type_and_key(Type, Key, Context)

-spec lookup_users_by_verified_type_and_key(type(), key(), z:context()) -> [identity()].

m_get/3

merge(WinnerId, LoserId, Context)

-spec merge(WinnerId, LoserId, Context) -> ok | {error, term()}
               when WinnerId :: m_rsc:resource(), LoserId :: m_rsc:resource(), Context :: z:context().

needs_rehash/1

-spec needs_rehash(hash()) -> boolean().

normalize_key/2

-spec normalize_key(type(), key() | undefined) -> key() | undefined.

reset_password(UserId, Context)

-spec reset_password(UserId, Context) -> ok | {error, Reason}
                        when
                            UserId :: m_rsc:resource(),
                            Context :: z:context(),
                            Reason :: enoent | eacces | nouser.

set_by_type(RscId, Type, Key, Context)

-spec set_by_type(RscId, Type, Key, Context) -> ok
                     when
                         RscId :: m_rsc:resource_id(),
                         Type :: type(),
                         Key :: key(),
                         Context :: z:context().

set_by_type(RscId, Type, Key, PropB, Context)

-spec set_by_type(RscId, Type, Key, PropB, Context) -> ok
                     when
                         RscId :: m_rsc:resource_id(),
                         Type :: type(),
                         Key :: key(),
                         PropB :: term(),
                         Context :: z:context().

set_expired(UserId, DateTime, Context)

-spec set_expired(UserId, DateTime, Context) -> ok | {error, enoent}
                     when
                         UserId :: m_rsc:resource_id(),
                         DateTime :: undefined | boolean() | calendar:datetime(),
                         Context :: z:context().

set_identity_expired(IdnId, DateTime, Context)

-spec set_identity_expired(IdnId, DateTime, Context) -> ok | {error, enoent}
                              when
                                  IdnId :: pos_integer(),
                                  DateTime :: undefined | boolean() | calendar:datetime(),
                                  Context :: z:context().

set_propb(IdnId, PropB, Context)

-spec set_propb(IdnId, PropB, Context) -> ok | {error, enoent}
                   when IdnId :: pos_integer(), PropB :: undefined | term(), Context :: z:context().

set_username(UserId, Username, Context)

-spec set_username(UserId, Username, Context) -> ok | {error, Reason}
                      when
                          UserId :: m_rsc:resource() | undefined,
                          Username :: binary() | string(),
                          Context :: z:context(),
                          Reason :: eacces | enoent | eexist.

set_username_pw(UserId, Username, Password, Context)

-spec set_username_pw(UserId, Username, Password, Context) -> ok | {error, Reason}
                         when
                             UserId :: m_rsc:resource() | undefined,
                             Username :: binary() | string(),
                             Password :: binary() | string(),
                             Context :: z:context(),
                             Reason :: eacces | enoent | eexist | password_match | term().

set_verified(IdnId, Context)

-spec set_verified(IdnId, Context) -> ok | {error, notfound}
                      when IdnId :: pos_integer(), Context :: z:context().

set_verified/4

-spec set_verified(m_rsc:resource_id(), type(), key(), z:context()) -> ok | {error, term()}.

set_verify_key(IdnId, Context)

-spec set_verify_key(IdnId, Context) -> {ok, VerifyKey} | {error, enoent}
                        when IdnId :: pos_integer(), Context :: z:context(), VerifyKey :: binary().

set_visited/2

-spec set_visited(m_rsc:resource_id(), z:context()) -> ok | {error, enoent}.

user_types(Context)

-spec user_types(Context) -> [Type] when Context :: z:context(), Type :: atom().

verify_primary_email(RscId, Context)

-spec verify_primary_email(RscId, Context) -> {ok, Status} | {error, Reason}
                              when
                                  RscId :: m_rsc:resource(),
                                  Context :: z:context(),
                                  Status :: sent | verified,
                                  Reason :: term().