Current section
Files
Jump to
Current section
Files
lib/sql_membership_provider/profile.ex
defmodule SqlMembershipProvider.Profile do
@moduledoc """
Struct for representing a user's profile information that may contain arbitrary properties
"""
use TypedEctoSchema
import Ecto.Query, only: [from: 2]
@primary_key {:user_id, :binary_id, null: false}
@field_source_mapper fn name -> name |> Atom.to_string() |> Macro.camelize() end
typed_schema "aspnet_Profile" do
field(:property_names, :string, null: false)
field(:property_values_string, :string, null: false)
# FIXME: TDS throws error trying to retrieve an "image" type column
# field(:property_values_binary, :binary)
field(:last_updated_date, :utc_datetime, null: false)
belongs_to(:user, SqlMembershipProvider.User,
define_field: false,
primary_key: true,
references: :user_id
)
end
@doc """
Fetch a profile by user id.
"""
@spec find_by_user_id(String.t()) :: Ecto.Query.t()
def find_by_user_id(user_id) when is_binary(user_id) do
from(
p in SqlMembershipProvider.Profile,
where: p.user_id == ^user_id
)
end
@doc """
Parse a profile's property fields into a map.
"""
@spec properties(SqlMembershipProvider.Profile.t()) :: map()
def properties(
profile = %SqlMembershipProvider.Profile{
property_names: property_names
}
) do
property_names
|> String.split(":")
|> Enum.chunk_every(4)
|> Enum.map(&List.to_tuple/1)
|> Enum.filter(fn
{_key, _type, _start, _length} -> true
_ -> false
end)
|> Enum.map(fn property -> extract_property(property, profile) end)
|> Enum.into(%{})
end
defp extract_property({key, _type, _start, "-1"}, _profile) do
{key, nil}
end
# properties found in property_values_binary
defp extract_property({key, "B", _start, _length}, _profile) do
# we probably can't deserialize the binary proerties
{key, nil}
end
# properties found in property_values_string
defp extract_property({key, "S", start, length}, %SqlMembershipProvider.Profile{
property_values_string: property_values_string
}) do
start = String.to_integer(start)
length = String.to_integer(length)
value =
String.codepoints(property_values_string)
|> Enum.slice(start, length)
|> Enum.join("")
{key, value}
end
end