+ def info_changeset(struct, params \\ %{}) do
+ struct
+ |> cast(params, [:info])
+ |> validate_required([:info])
+ end
+
+ def user_info(%User{} = user) do
+ %{
+ following_count: length(user.following),
+ note_count: user.info["note_count"] || 0,
+ follower_count: user.info["follower_count"] || 0
+ }
+ end
+
+ @email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
+ def remote_user_creation(params) do
+ changes = %User{}
+ |> cast(params, [:bio, :name, :ap_id, :nickname, :info, :avatar])
+ |> validate_required([:name, :ap_id, :nickname])
+ |> unique_constraint(:nickname)
+ |> validate_format(:nickname, @email_regex)
+ |> validate_length(:bio, max: 5000)
+ |> validate_length(:name, max: 100)
+ |> put_change(:local, false)
+ if changes.valid? do
+ followers = User.ap_followers(%User{nickname: changes.changes[:nickname]})
+ changes
+ |> put_change(:follower_address, followers)
+ else
+ changes
+ end
+ end
+
+ def update_changeset(struct, params \\ %{}) do
+ changeset = struct
+ |> cast(params, [:bio, :name])
+ |> unique_constraint(:nickname)
+ |> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/)
+ |> validate_length(:bio, min: 1, max: 1000)
+ |> validate_length(:name, min: 1, max: 100)
+ end
+
+ def register_changeset(struct, params \\ %{}) do
+ changeset = struct
+ |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation])
+ |> validate_required([:bio, :email, :name, :nickname, :password, :password_confirmation])
+ |> validate_confirmation(:password)
+ |> unique_constraint(:email)
+ |> unique_constraint(:nickname)
+ |> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/)
+ |> validate_format(:email, @email_regex)
+ |> validate_length(:bio, min: 1, max: 1000)
+ |> validate_length(:name, min: 1, max: 100)
+
+ if changeset.valid? do
+ hashed = Pbkdf2.hashpwsalt(changeset.changes[:password])
+ ap_id = User.ap_id(%User{nickname: changeset.changes[:nickname]})
+ followers = User.ap_followers(%User{nickname: changeset.changes[:nickname]})
+ changeset
+ |> put_change(:password_hash, hashed)
+ |> put_change(:ap_id, ap_id)
+ |> put_change(:following, [followers])
+ |> put_change(:follower_address, followers)
+ else
+ changeset
+ end
+ end
+