Merge pull request #73 from parasprite/Artist-links-code

Makes user links artist links
This commit is contained in:
Meow 2020-12-02 19:30:07 +01:00 committed by GitHub
commit 685159587c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 525 additions and 514 deletions

View file

@ -26,7 +26,7 @@ function close(burger, content, body, root) {
}, 300); }, 300);
} }
function copyUserLinksTo(burger) { function copyArtistLinksTo(burger) {
const copy = links => { const copy = links => {
burger.appendChild(document.createElement('hr')); burger.appendChild(document.createElement('hr'));
@ -50,7 +50,7 @@ function setupBurgerMenu() {
const body = document.body; const body = document.body;
const root = document.documentElement; const root = document.documentElement;
copyUserLinksTo(burger); copyArtistLinksTo(burger);
toggle.addEventListener('click', event => { toggle.addEventListener('click', event => {
event.stopPropagation(); event.stopPropagation();

View file

@ -3,7 +3,7 @@
background() { background() {
while :; do while :; do
mix run -e 'Philomena.Release.update_channels()' mix run -e 'Philomena.Release.update_channels()'
mix run -e 'Philomena.Release.verify_user_links()' mix run -e 'Philomena.Release.verify_artist_links()'
mix run -e 'Philomena.Release.update_stats()' mix run -e 'Philomena.Release.update_stats()'
sleep 300 sleep 300

View file

@ -0,0 +1,185 @@
defmodule Philomena.ArtistLinks do
@moduledoc """
The ArtistLinks context.
"""
import Ecto.Query, warn: false
alias Ecto.Multi
alias Philomena.Repo
alias Philomena.ArtistLinks.ArtistLink
alias Philomena.ArtistLinks.AutomaticVerifier
alias Philomena.Badges.Badge
alias Philomena.Badges.Award
alias Philomena.Tags.Tag
@doc """
Check links pending verification to see if the user placed
the appropriate code on the page.
"""
def automatic_verify! do
now = DateTime.utc_now() |> DateTime.truncate(:second)
# Automatically retry in an hour if we don't manage to
# successfully verify any given link
recheck_time = DateTime.add(now, 3600, :second)
recheck_query =
from ul in ArtistLink,
where: ul.aasm_state == "unverified",
where: ul.next_check_at < ^now
recheck_query
|> Repo.all()
|> Enum.map(fn link ->
ArtistLink.automatic_verify_changeset(link, AutomaticVerifier.check_link(link, recheck_time))
end)
|> Enum.map(&Repo.update!/1)
end
@doc """
Gets a single artist_link.
Raises `Ecto.NoResultsError` if the Artist link does not exist.
## Examples
iex> get_artist_link!(123)
%ArtistLink{}
iex> get_artist_link!(456)
** (Ecto.NoResultsError)
"""
def get_artist_link!(id), do: Repo.get!(ArtistLink, id)
@doc """
Creates a artist_link.
## Examples
iex> create_artist_link(%{field: value})
{:ok, %ArtistLink{}}
iex> create_artist_link(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_artist_link(user, attrs \\ %{}) do
tag = fetch_tag(attrs["tag_name"])
%ArtistLink{}
|> ArtistLink.creation_changeset(attrs, user, tag)
|> Repo.insert()
end
@doc """
Updates a artist_link.
## Examples
iex> update_artist_link(artist_link, %{field: new_value})
{:ok, %ArtistLink{}}
iex> update_artist_link(artist_link, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_artist_link(%ArtistLink{} = artist_link, attrs) do
tag = fetch_tag(attrs["tag_name"])
artist_link
|> ArtistLink.edit_changeset(attrs, tag)
|> Repo.update()
end
def verify_artist_link(%ArtistLink{} = artist_link, user) do
artist_link_changeset =
artist_link
|> ArtistLink.verify_changeset(user)
Multi.new()
|> Multi.update(:artist_link, artist_link_changeset)
|> Multi.run(:add_award, fn repo, _changes ->
now = DateTime.utc_now() |> DateTime.truncate(:second)
with badge when not is_nil(badge) <- repo.get_by(limit(Badge, 1), title: "Artist"),
nil <- repo.get_by(limit(Award, 1), badge_id: badge.id, user_id: artist_link.user_id) do
%Award{
badge_id: badge.id,
user_id: artist_link.user_id,
awarded_by_id: user.id,
awarded_on: now
}
|> Award.changeset(%{})
|> repo.insert()
else
_ ->
{:ok, nil}
end
end)
|> Repo.transaction()
end
def reject_artist_link(%ArtistLink{} = artist_link) do
artist_link
|> ArtistLink.reject_changeset()
|> Repo.update()
end
def contact_artist_link(%ArtistLink{} = artist_link, user) do
artist_link
|> ArtistLink.contact_changeset(user)
|> Repo.update()
end
@doc """
Deletes a ArtistLink.
## Examples
iex> delete_artist_link(artist_link)
{:ok, %ArtistLink{}}
iex> delete_artist_link(artist_link)
{:error, %Ecto.Changeset{}}
"""
def delete_artist_link(%ArtistLink{} = artist_link) do
Repo.delete(artist_link)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking artist_link changes.
## Examples
iex> change_artist_link(artist_link)
%Ecto.Changeset{source: %ArtistLink{}}
"""
def change_artist_link(%ArtistLink{} = artist_link) do
ArtistLink.changeset(artist_link, %{})
end
def count_artist_links(user) do
if Canada.Can.can?(user, :index, %ArtistLink{}) do
ArtistLink
|> where([ul], ul.aasm_state in ^["unverified", "link_verified", "contacted"])
|> Repo.aggregate(:count, :id)
else
nil
end
end
defp fetch_tag(name) do
Tag
|> preload(:aliased_tag)
|> where(name: ^name)
|> Repo.one()
|> case do
nil -> nil
tag -> tag.aliased_tag || tag
end
end
end

View file

@ -1,4 +1,4 @@
defmodule Philomena.UserLinks.UserLink do defmodule Philomena.ArtistLinks.ArtistLink do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
@ -24,59 +24,69 @@ defmodule Philomena.UserLinks.UserLink do
end end
@doc false @doc false
def changeset(user_link, attrs) do def changeset(artist_link, attrs) do
user_link artist_link
|> cast(attrs, []) |> cast(attrs, [])
|> validate_required([]) |> validate_required([])
end end
def edit_changeset(user_link, attrs, nil) do def edit_changeset(artist_link, attrs, nil) do
user_link artist_link
|> cast(attrs, [:uri, :public]) |> cast(attrs, [:uri, :public])
|> put_change(:tag_id, nil) |> put_change(:tag_id, nil)
|> validate_required([:user, :uri, :public]) |> validate_required([:user, :uri, :public])
|> parse_uri() |> parse_uri()
end end
def edit_changeset(user_link, attrs, tag) do def edit_changeset(artist_link, attrs, tag) do
user_link artist_link
|> cast(attrs, [:uri, :public]) |> cast(attrs, [:uri, :public])
|> put_change(:tag_id, tag.id) |> put_change(:tag_id, tag.id)
|> validate_required([:user, :uri, :public]) |> validate_required([:user, :uri, :public])
|> parse_uri() |> parse_uri()
end end
def creation_changeset(user_link, attrs, user, tag) do def creation_changeset(artist_link, attrs, user, tag) do
user_link artist_link
|> cast(attrs, [:uri, :public]) |> cast(attrs, [:uri, :public])
|> put_assoc(:tag, tag) |> put_assoc(:tag, tag)
|> put_assoc(:user, user) |> put_assoc(:user, user)
|> validate_required([:user, :uri, :public]) |> validate_required([:user, :uri, :public])
|> validate_required([:tag], message: "must exist") |> validate_required([:tag], message: "must exist")
|> validate_format(:uri, ~r|\Ahttps?://|) |> validate_format(:uri, ~r|\Ahttps?://|)
|> validate_category()
|> parse_uri() |> parse_uri()
|> put_verification_code() |> put_verification_code()
|> put_next_check_at() |> put_next_check_at()
end end
def reject_changeset(user_link) do def validate_category(changeset) do
change(user_link, aasm_state: "rejected") tag = get_field(changeset, :tag)
case tag.category in ["origin", "content-fanmade"] do
false -> add_error(changeset, :tag, "must be a creator tag")
true -> changeset
end
end end
def automatic_verify_changeset(user_link, attrs) do def reject_changeset(artist_link) do
cast(user_link, attrs, [:next_check_at, :aasm_state]) change(artist_link, aasm_state: "rejected")
end end
def verify_changeset(user_link, user) do def automatic_verify_changeset(artist_link, attrs) do
change(user_link) cast(artist_link, attrs, [:next_check_at, :aasm_state])
end
def verify_changeset(artist_link, user) do
change(artist_link)
|> put_change(:verified_by_user_id, user.id) |> put_change(:verified_by_user_id, user.id)
|> put_change(:aasm_state, "verified") |> put_change(:aasm_state, "verified")
end end
def contact_changeset(user_link, user) do def contact_changeset(artist_link, user) do
now = DateTime.utc_now() |> DateTime.truncate(:second) now = DateTime.utc_now() |> DateTime.truncate(:second)
change(user_link) change(artist_link)
|> put_change(:contacted_by_user_id, user.id) |> put_change(:contacted_by_user_id, user.id)
|> put_change(:contacted_at, now) |> put_change(:contacted_at, now)
|> put_change(:aasm_state, "contacted") |> put_change(:aasm_state, "contacted")

View file

@ -1,8 +1,8 @@
defmodule Philomena.UserLinks.AutomaticVerifier do defmodule Philomena.ArtistLinks.AutomaticVerifier do
def check_link(user_link, recheck_time) do def check_link(artist_link, recheck_time) do
user_link.uri artist_link.uri
|> Philomena.Http.get() |> Philomena.Http.get()
|> contains_verification_code?(user_link.verification_code) |> contains_verification_code?(artist_link.verification_code)
|> case do |> case do
true -> true ->
%{next_check_at: nil, aasm_state: "link_verified"} %{next_check_at: nil, aasm_state: "link_verified"}

View file

@ -3,7 +3,7 @@ defmodule Philomena.Images.DnpValidator do
import Ecto.Query import Ecto.Query
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
alias Philomena.UserLinks.UserLink alias Philomena.ArtistLinks.ArtistLink
def validate_dnp(changeset, uploader) do def validate_dnp(changeset, uploader) do
tags = tags =
@ -60,7 +60,7 @@ defmodule Philomena.Images.DnpValidator do
defp valid_user?(_dnp_entry, nil), do: false defp valid_user?(_dnp_entry, nil), do: false
defp valid_user?(dnp_entry, user) do defp valid_user?(dnp_entry, user) do
UserLink ArtistLink
|> where(tag_id: ^dnp_entry.tag_id) |> where(tag_id: ^dnp_entry.tag_id)
|> where(aasm_state: "verified") |> where(aasm_state: "verified")
|> where(user_id: ^user.id) |> where(user_id: ^user.id)

View file

@ -19,9 +19,9 @@ defmodule Philomena.Release do
Philomena.Channels.update_tracked_channels!() Philomena.Channels.update_tracked_channels!()
end end
def verify_user_links do def verify_artist_links do
start_app() start_app()
Philomena.UserLinks.automatic_verify!() Philomena.ArtistLinks.automatic_verify!()
end end
def update_stats do def update_stats do

View file

@ -14,7 +14,7 @@ defmodule Philomena.Tags do
alias Philomena.Users.User alias Philomena.Users.User
alias Philomena.Filters.Filter alias Philomena.Filters.Filter
alias Philomena.Images.Tagging alias Philomena.Images.Tagging
alias Philomena.UserLinks.UserLink alias Philomena.ArtistLinks.ArtistLink
alias Philomena.DnpEntries.DnpEntry alias Philomena.DnpEntries.DnpEntry
alias Philomena.Channels.Channel alias Philomena.Channels.Channel
@ -228,7 +228,7 @@ defmodule Philomena.Tags do
|> Repo.delete_all() |> Repo.delete_all()
# Update other assocations # Update other assocations
UserLink ArtistLink
|> where(tag_id: ^tag.id) |> where(tag_id: ^tag.id)
|> Repo.update_all(set: [tag_id: target_tag.id]) |> Repo.update_all(set: [tag_id: target_tag.id])

View file

@ -5,7 +5,7 @@ defmodule Philomena.Tags.Tag do
alias Philomena.Channels.Channel alias Philomena.Channels.Channel
alias Philomena.DnpEntries.DnpEntry alias Philomena.DnpEntries.DnpEntry
alias Philomena.UserLinks.UserLink alias Philomena.ArtistLinks.ArtistLink
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
alias Philomena.Slug alias Philomena.Slug
alias Philomena.Repo alias Philomena.Repo
@ -68,8 +68,8 @@ defmodule Philomena.Tags.Tag do
join_through: "tags_implied_tags", join_through: "tags_implied_tags",
join_keys: [implied_tag_id: :id, tag_id: :id] join_keys: [implied_tag_id: :id, tag_id: :id]
has_many :public_links, UserLink, where: [public: true, aasm_state: "verified"] has_many :public_links, ArtistLink, where: [public: true, aasm_state: "verified"]
has_many :hidden_links, UserLink, where: [public: false, aasm_state: "verified"] has_many :hidden_links, ArtistLink, where: [public: false, aasm_state: "verified"]
has_many :dnp_entries, DnpEntry, where: [aasm_state: "listed"] has_many :dnp_entries, DnpEntry, where: [aasm_state: "listed"]
field :slug, :string field :slug, :string

View file

@ -1,185 +0,0 @@
defmodule Philomena.UserLinks do
@moduledoc """
The UserLinks context.
"""
import Ecto.Query, warn: false
alias Ecto.Multi
alias Philomena.Repo
alias Philomena.UserLinks.UserLink
alias Philomena.UserLinks.AutomaticVerifier
alias Philomena.Badges.Badge
alias Philomena.Badges.Award
alias Philomena.Tags.Tag
@doc """
Check links pending verification to see if the user placed
the appropriate code on the page.
"""
def automatic_verify! do
now = DateTime.utc_now() |> DateTime.truncate(:second)
# Automatically retry in an hour if we don't manage to
# successfully verify any given link
recheck_time = DateTime.add(now, 3600, :second)
recheck_query =
from ul in UserLink,
where: ul.aasm_state == "unverified",
where: ul.next_check_at < ^now
recheck_query
|> Repo.all()
|> Enum.map(fn link ->
UserLink.automatic_verify_changeset(link, AutomaticVerifier.check_link(link, recheck_time))
end)
|> Enum.map(&Repo.update!/1)
end
@doc """
Gets a single user_link.
Raises `Ecto.NoResultsError` if the User link does not exist.
## Examples
iex> get_user_link!(123)
%UserLink{}
iex> get_user_link!(456)
** (Ecto.NoResultsError)
"""
def get_user_link!(id), do: Repo.get!(UserLink, id)
@doc """
Creates a user_link.
## Examples
iex> create_user_link(%{field: value})
{:ok, %UserLink{}}
iex> create_user_link(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_user_link(user, attrs \\ %{}) do
tag = fetch_tag(attrs["tag_name"])
%UserLink{}
|> UserLink.creation_changeset(attrs, user, tag)
|> Repo.insert()
end
@doc """
Updates a user_link.
## Examples
iex> update_user_link(user_link, %{field: new_value})
{:ok, %UserLink{}}
iex> update_user_link(user_link, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_user_link(%UserLink{} = user_link, attrs) do
tag = fetch_tag(attrs["tag_name"])
user_link
|> UserLink.edit_changeset(attrs, tag)
|> Repo.update()
end
def verify_user_link(%UserLink{} = user_link, user) do
user_link_changeset =
user_link
|> UserLink.verify_changeset(user)
Multi.new()
|> Multi.update(:user_link, user_link_changeset)
|> Multi.run(:add_award, fn repo, _changes ->
now = DateTime.utc_now() |> DateTime.truncate(:second)
with badge when not is_nil(badge) <- repo.get_by(limit(Badge, 1), title: "Artist"),
nil <- repo.get_by(limit(Award, 1), badge_id: badge.id, user_id: user_link.user_id) do
%Award{
badge_id: badge.id,
user_id: user_link.user_id,
awarded_by_id: user.id,
awarded_on: now
}
|> Award.changeset(%{})
|> repo.insert()
else
_ ->
{:ok, nil}
end
end)
|> Repo.transaction()
end
def reject_user_link(%UserLink{} = user_link) do
user_link
|> UserLink.reject_changeset()
|> Repo.update()
end
def contact_user_link(%UserLink{} = user_link, user) do
user_link
|> UserLink.contact_changeset(user)
|> Repo.update()
end
@doc """
Deletes a UserLink.
## Examples
iex> delete_user_link(user_link)
{:ok, %UserLink{}}
iex> delete_user_link(user_link)
{:error, %Ecto.Changeset{}}
"""
def delete_user_link(%UserLink{} = user_link) do
Repo.delete(user_link)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking user_link changes.
## Examples
iex> change_user_link(user_link)
%Ecto.Changeset{source: %UserLink{}}
"""
def change_user_link(%UserLink{} = user_link) do
UserLink.changeset(user_link, %{})
end
def count_user_links(user) do
if Canada.Can.can?(user, :index, %UserLink{}) do
UserLink
|> where([ul], ul.aasm_state in ^["unverified", "link_verified", "contacted"])
|> Repo.aggregate(:count, :id)
else
nil
end
end
defp fetch_tag(name) do
Tag
|> preload(:aliased_tag)
|> where(name: ^name)
|> Repo.one()
|> case do
nil -> nil
tag -> tag.aliased_tag || tag
end
end
end

View file

@ -17,7 +17,7 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
alias Philomena.Filters.Filter alias Philomena.Filters.Filter
alias Philomena.Galleries.Gallery alias Philomena.Galleries.Gallery
alias Philomena.DnpEntries.DnpEntry alias Philomena.DnpEntries.DnpEntry
alias Philomena.UserLinks.UserLink alias Philomena.ArtistLinks.ArtistLink
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
alias Philomena.TagChanges.TagChange alias Philomena.TagChanges.TagChange
alias Philomena.Reports.Report alias Philomena.Reports.Report
@ -76,11 +76,11 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
def can?(%User{role: "moderator"}, :show, %Report{}), do: true def can?(%User{role: "moderator"}, :show, %Report{}), do: true
def can?(%User{role: "moderator"}, :edit, %Report{}), do: true def can?(%User{role: "moderator"}, :edit, %Report{}), do: true
# Manage user links # Manage artist links
def can?(%User{role: "moderator"}, :create_links, %User{}), do: true def can?(%User{role: "moderator"}, :create_links, %User{}), do: true
def can?(%User{role: "moderator"}, :edit_links, %User{}), do: true def can?(%User{role: "moderator"}, :edit_links, %User{}), do: true
def can?(%User{role: "moderator"}, _action, UserLink), do: true def can?(%User{role: "moderator"}, _action, ArtistLink), do: true
def can?(%User{role: "moderator"}, _action, %UserLink{}), do: true def can?(%User{role: "moderator"}, _action, %ArtistLink{}), do: true
# Reveal anon users # Reveal anon users
def can?(%User{role: "moderator"}, :reveal_anon, _object), do: true def can?(%User{role: "moderator"}, :reveal_anon, _object), do: true
@ -262,24 +262,24 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
def can?(%User{role: "assistant", role_map: %{"Tag" => "moderator"}}, :batch_update, Tag), def can?(%User{role: "assistant", role_map: %{"Tag" => "moderator"}}, :batch_update, Tag),
do: true do: true
# User link assistant actions # Artist link assistant actions
def can?(%User{role: "assistant", role_map: %{"UserLink" => "moderator"}}, _action, %UserLink{}), def can?(%User{role: "assistant", role_map: %{"ArtistLink" => "moderator"}}, _action, %ArtistLink{}),
do: true do: true
def can?( def can?(
%User{role: "assistant", role_map: %{"UserLink" => "moderator"}}, %User{role: "assistant", role_map: %{"ArtistLink" => "moderator"}},
:create_links, :create_links,
%User{} %User{}
), ),
do: true do: true
def can?(%User{role: "assistant", role_map: %{"UserLink" => "moderator"}}, :edit, %UserLink{}), def can?(%User{role: "assistant", role_map: %{"ArtistLink" => "moderator"}}, :edit, %ArtistLink{}),
do: true do: true
def can?(%User{role: "assistant", role_map: %{"UserLink" => "moderator"}}, :edit_links, %User{}), def can?(%User{role: "assistant", role_map: %{"ArtistLink" => "moderator"}}, :edit_links, %User{}),
do: true do: true
def can?(%User{role: "assistant", role_map: %{"UserLink" => "moderator"}}, :index, %UserLink{}), def can?(%User{role: "assistant", role_map: %{"ArtistLink" => "moderator"}}, :index, %ArtistLink{}),
do: true do: true
# View forums # View forums
@ -322,9 +322,9 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
def can?(%User{id: id}, action, %Filter{user_id: id}) when action in [:edit, :update, :delete], def can?(%User{id: id}, action, %Filter{user_id: id}) when action in [:edit, :update, :delete],
do: true do: true
# View user links they've created # View artist links they've created
def can?(%User{id: id}, :create_links, %User{id: id}), do: true def can?(%User{id: id}, :create_links, %User{id: id}), do: true
def can?(%User{id: id}, :show, %UserLink{user_id: id}), do: true def can?(%User{id: id}, :show, %ArtistLink{user_id: id}), do: true
# Edit their commissions # Edit their commissions
def can?(%User{id: id}, action, %Commission{user_id: id}) def can?(%User{id: id}, action, %Commission{user_id: id})

View file

@ -9,7 +9,7 @@ defmodule Philomena.Users.User do
alias Philomena.Schema.Search alias Philomena.Schema.Search
alias Philomena.Filters.Filter alias Philomena.Filters.Filter
alias Philomena.UserLinks.UserLink alias Philomena.ArtistLinks.ArtistLink
alias Philomena.Badges alias Philomena.Badges
alias Philomena.Notifications.UnreadNotification alias Philomena.Notifications.UnreadNotification
alias Philomena.Galleries.Gallery alias Philomena.Galleries.Gallery
@ -24,9 +24,9 @@ defmodule Philomena.Users.User do
@derive {Phoenix.Param, key: :slug} @derive {Phoenix.Param, key: :slug}
@derive {Inspect, except: [:password]} @derive {Inspect, except: [:password]}
schema "users" do schema "users" do
has_many :links, UserLink has_many :links, ArtistLink
has_many :verified_links, UserLink, where: [aasm_state: "verified"] has_many :verified_links, ArtistLink, where: [aasm_state: "verified"]
has_many :public_links, UserLink, where: [public: true, aasm_state: "verified"] has_many :public_links, ArtistLink, where: [public: true, aasm_state: "verified"]
has_many :galleries, Gallery, foreign_key: :creator_id has_many :galleries, Gallery, foreign_key: :creator_id
has_many :awards, Badges.Award has_many :awards, Badges.Award
has_many :unread_notifications, UnreadNotification has_many :unread_notifications, UnreadNotification

View file

@ -0,0 +1,22 @@
defmodule PhilomenaWeb.Admin.ArtistLink.ContactController do
use PhilomenaWeb, :controller
alias Philomena.ArtistLinks.ArtistLink
alias Philomena.ArtistLinks
plug PhilomenaWeb.CanaryMapPlug, create: :edit
plug :load_and_authorize_resource,
model: ArtistLink,
id_name: "artist_link_id",
persisted: true,
preload: [:user]
def create(conn, _params) do
{:ok, _} = ArtistLinks.contact_artist_link(conn.assigns.artist_link, conn.assigns.current_user)
conn
|> put_flash(:info, "Artist successfully marked as contacted.")
|> redirect(to: Routes.admin_artist_link_path(conn, :index))
end
end

View file

@ -0,0 +1,22 @@
defmodule PhilomenaWeb.Admin.ArtistLink.RejectController do
use PhilomenaWeb, :controller
alias Philomena.ArtistLinks.ArtistLink
alias Philomena.ArtistLinks
plug PhilomenaWeb.CanaryMapPlug, create: :edit
plug :load_and_authorize_resource,
model: ArtistLink,
id_name: "artist_link_id",
persisted: true,
preload: [:user]
def create(conn, _params) do
{:ok, _} = ArtistLinks.reject_artist_link(conn.assigns.artist_link)
conn
|> put_flash(:info, "Artist link successfully marked as rejected.")
|> redirect(to: Routes.admin_artist_link_path(conn, :index))
end
end

View file

@ -0,0 +1,22 @@
defmodule PhilomenaWeb.Admin.ArtistLink.VerificationController do
use PhilomenaWeb, :controller
alias Philomena.ArtistLinks.ArtistLink
alias Philomena.ArtistLinks
plug PhilomenaWeb.CanaryMapPlug, create: :edit
plug :load_and_authorize_resource,
model: ArtistLink,
id_name: "artist_link_id",
persisted: true,
preload: [:user]
def create(conn, _params) do
{:ok, _} = ArtistLinks.verify_artist_link(conn.assigns.artist_link, conn.assigns.current_user)
conn
|> put_flash(:info, "Artist link successfully verified.")
|> redirect(to: Routes.admin_artist_link_path(conn, :index))
end
end

View file

@ -1,27 +1,27 @@
defmodule PhilomenaWeb.Admin.UserLinkController do defmodule PhilomenaWeb.Admin.ArtistLinkController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.UserLinks.UserLink alias Philomena.ArtistLinks.ArtistLink
alias Philomena.Repo alias Philomena.Repo
import Ecto.Query import Ecto.Query
plug :verify_authorized plug :verify_authorized
def index(conn, %{"all" => _value}) do def index(conn, %{"all" => _value}) do
load_links(UserLink, conn) load_links(ArtistLink, conn)
end end
def index(conn, %{"q" => query}) do def index(conn, %{"q" => query}) do
query = "%#{query}%" query = "%#{query}%"
UserLink ArtistLink
|> join(:inner, [ul], _ in assoc(ul, :user)) |> join(:inner, [ul], _ in assoc(ul, :user))
|> where([ul, u], ilike(u.name, ^query) or ilike(ul.uri, ^query)) |> where([ul, u], ilike(u.name, ^query) or ilike(ul.uri, ^query))
|> load_links(conn) |> load_links(conn)
end end
def index(conn, _params) do def index(conn, _params) do
UserLink ArtistLink
|> where([u], u.aasm_state in ^["unverified", "link_verified", "contacted"]) |> where([u], u.aasm_state in ^["unverified", "link_verified", "contacted"])
|> load_links(conn) |> load_links(conn)
end end
@ -38,11 +38,11 @@ defmodule PhilomenaWeb.Admin.UserLinkController do
]) ])
|> Repo.paginate(conn.assigns.scrivener) |> Repo.paginate(conn.assigns.scrivener)
render(conn, "index.html", title: "Admin - User Links", user_links: links) render(conn, "index.html", title: "Admin - Artist Links", artist_links: links)
end end
defp verify_authorized(conn, _opts) do defp verify_authorized(conn, _opts) do
case Canada.Can.can?(conn.assigns.current_user, :index, %UserLink{}) do case Canada.Can.can?(conn.assigns.current_user, :index, %ArtistLink{}) do
true -> conn true -> conn
false -> PhilomenaWeb.NotAuthorizedPlug.call(conn) false -> PhilomenaWeb.NotAuthorizedPlug.call(conn)
end end

View file

@ -1,22 +0,0 @@
defmodule PhilomenaWeb.Admin.UserLink.ContactController do
use PhilomenaWeb, :controller
alias Philomena.UserLinks.UserLink
alias Philomena.UserLinks
plug PhilomenaWeb.CanaryMapPlug, create: :edit
plug :load_and_authorize_resource,
model: UserLink,
id_name: "user_link_id",
persisted: true,
preload: [:user]
def create(conn, _params) do
{:ok, _} = UserLinks.contact_user_link(conn.assigns.user_link, conn.assigns.current_user)
conn
|> put_flash(:info, "User link successfully marked as contacted.")
|> redirect(to: Routes.admin_user_link_path(conn, :index))
end
end

View file

@ -1,22 +0,0 @@
defmodule PhilomenaWeb.Admin.UserLink.RejectController do
use PhilomenaWeb, :controller
alias Philomena.UserLinks.UserLink
alias Philomena.UserLinks
plug PhilomenaWeb.CanaryMapPlug, create: :edit
plug :load_and_authorize_resource,
model: UserLink,
id_name: "user_link_id",
persisted: true,
preload: [:user]
def create(conn, _params) do
{:ok, _} = UserLinks.reject_user_link(conn.assigns.user_link)
conn
|> put_flash(:info, "User link successfully marked as rejected.")
|> redirect(to: Routes.admin_user_link_path(conn, :index))
end
end

View file

@ -1,22 +0,0 @@
defmodule PhilomenaWeb.Admin.UserLink.VerificationController do
use PhilomenaWeb, :controller
alias Philomena.UserLinks.UserLink
alias Philomena.UserLinks
plug PhilomenaWeb.CanaryMapPlug, create: :edit
plug :load_and_authorize_resource,
model: UserLink,
id_name: "user_link_id",
persisted: true,
preload: [:user]
def create(conn, _params) do
{:ok, _} = UserLinks.verify_user_link(conn.assigns.user_link, conn.assigns.current_user)
conn
|> put_flash(:info, "User link successfully verified.")
|> redirect(to: Routes.admin_user_link_path(conn, :index))
end
end

View file

@ -0,0 +1,84 @@
defmodule PhilomenaWeb.Profile.ArtistLinkController do
use PhilomenaWeb, :controller
alias Philomena.ArtistLinks.ArtistLink
alias Philomena.ArtistLinks
alias Philomena.Users.User
alias Philomena.Repo
import Ecto.Query
plug PhilomenaWeb.FilterBannedUsersPlug when action in [:new, :create]
plug :load_and_authorize_resource,
model: ArtistLink,
only: [:show, :edit, :update],
preload: [:user, :tag, :contacted_by_user]
plug PhilomenaWeb.CanaryMapPlug,
index: :create_links,
new: :create_links,
create: :create_links,
show: :create_links,
edit: :edit_links,
update: :edit_links
plug :load_and_authorize_resource,
model: User,
id_field: "slug",
id_name: "profile_id",
persisted: true
def index(conn, _params) do
user = conn.assigns.current_user
artist_links =
ArtistLink
|> where(user_id: ^user.id)
|> Repo.all()
render(conn, "index.html", title: "Artist Links", artist_links: artist_links)
end
def new(conn, _params) do
changeset = ArtistLinks.change_artist_link(%ArtistLink{})
render(conn, "new.html", title: "New Artist Link", changeset: changeset)
end
def create(conn, %{"artist_link" => artist_link_params}) do
case ArtistLinks.create_artist_link(conn.assigns.user, artist_link_params) do
{:ok, artist_link} ->
conn
|> put_flash(
:info,
"Link submitted! Please put '#{artist_link.verification_code}' on your linked webpage now."
)
|> redirect(to: Routes.profile_artist_link_path(conn, :show, conn.assigns.user, artist_link))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, _params) do
artist_link = conn.assigns.artist_link
render(conn, "show.html", title: "Showing Artist Link", artist_link: artist_link)
end
def edit(conn, _params) do
changeset = ArtistLinks.change_artist_link(conn.assigns.artist_link)
render(conn, "edit.html", title: "Editing Artist Link", changeset: changeset)
end
def update(conn, %{"artist_link" => artist_link_params}) do
case ArtistLinks.update_artist_link(conn.assigns.artist_link, artist_link_params) do
{:ok, artist_link} ->
conn
|> put_flash(:info, "Link successfully updated.")
|> redirect(to: Routes.profile_artist_link_path(conn, :show, conn.assigns.user, artist_link))
{:error, changeset} ->
render(conn, "edit.html", changeset: changeset)
end
end
end

View file

@ -148,7 +148,7 @@ defmodule PhilomenaWeb.Profile.CommissionController do
false -> false ->
conn conn
|> put_flash(:error, "You must have a verified user link to create a commission listing.") |> put_flash(:error, "You must have a verified artist link to create a commission listing.")
|> redirect(to: Routes.commission_path(conn, :index)) |> redirect(to: Routes.commission_path(conn, :index))
|> halt() |> halt()
end end

View file

@ -1,84 +0,0 @@
defmodule PhilomenaWeb.Profile.UserLinkController do
use PhilomenaWeb, :controller
alias Philomena.UserLinks.UserLink
alias Philomena.UserLinks
alias Philomena.Users.User
alias Philomena.Repo
import Ecto.Query
plug PhilomenaWeb.FilterBannedUsersPlug when action in [:new, :create]
plug :load_and_authorize_resource,
model: UserLink,
only: [:show, :edit, :update],
preload: [:user, :tag, :contacted_by_user]
plug PhilomenaWeb.CanaryMapPlug,
index: :create_links,
new: :create_links,
create: :create_links,
show: :create_links,
edit: :edit_links,
update: :edit_links
plug :load_and_authorize_resource,
model: User,
id_field: "slug",
id_name: "profile_id",
persisted: true
def index(conn, _params) do
user = conn.assigns.current_user
user_links =
UserLink
|> where(user_id: ^user.id)
|> Repo.all()
render(conn, "index.html", title: "User Links", user_links: user_links)
end
def new(conn, _params) do
changeset = UserLinks.change_user_link(%UserLink{})
render(conn, "new.html", title: "New User Link", changeset: changeset)
end
def create(conn, %{"user_link" => user_link_params}) do
case UserLinks.create_user_link(conn.assigns.user, user_link_params) do
{:ok, user_link} ->
conn
|> put_flash(
:info,
"Link submitted! Please put '#{user_link.verification_code}' on your linked webpage now."
)
|> redirect(to: Routes.profile_user_link_path(conn, :show, conn.assigns.user, user_link))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, _params) do
user_link = conn.assigns.user_link
render(conn, "show.html", title: "Showing User Link", user_link: user_link)
end
def edit(conn, _params) do
changeset = UserLinks.change_user_link(conn.assigns.user_link)
render(conn, "edit.html", title: "Editing User Link", changeset: changeset)
end
def update(conn, %{"user_link" => user_link_params}) do
case UserLinks.update_user_link(conn.assigns.user_link, user_link_params) do
{:ok, user_link} ->
conn
|> put_flash(:info, "Link successfully updated.")
|> redirect(to: Routes.profile_user_link_path(conn, :show, conn.assigns.user, user_link))
{:error, changeset} ->
render(conn, "edit.html", changeset: changeset)
end
end
end

View file

@ -7,7 +7,7 @@ defmodule PhilomenaWeb.AdminCountersPlug do
alias Philomena.DuplicateReports alias Philomena.DuplicateReports
alias Philomena.Reports alias Philomena.Reports
alias Philomena.UserLinks alias Philomena.ArtistLinks
alias Philomena.DnpEntries alias Philomena.DnpEntries
import Plug.Conn, only: [assign: 3] import Plug.Conn, only: [assign: 3]
@ -33,13 +33,13 @@ defmodule PhilomenaWeb.AdminCountersPlug do
defp maybe_assign_admin_metrics(conn, user, true) do defp maybe_assign_admin_metrics(conn, user, true) do
duplicate_reports = DuplicateReports.count_duplicate_reports(user) duplicate_reports = DuplicateReports.count_duplicate_reports(user)
reports = Reports.count_reports(user) reports = Reports.count_reports(user)
user_links = UserLinks.count_user_links(user) artist_links = ArtistLinks.count_artist_links(user)
dnps = DnpEntries.count_dnp_entries(user) dnps = DnpEntries.count_dnp_entries(user)
conn conn
|> assign(:duplicate_report_count, duplicate_reports) |> assign(:duplicate_report_count, duplicate_reports)
|> assign(:report_count, reports) |> assign(:report_count, reports)
|> assign(:user_link_count, user_links) |> assign(:artist_link_count, artist_links)
|> assign(:dnp_entry_count, dnps) |> assign(:dnp_entry_count, dnps)
end end

View file

@ -261,7 +261,7 @@ defmodule PhilomenaWeb.Router do
only: [:edit, :update], only: [:edit, :update],
singleton: true singleton: true
resources "/user_links", Profile.UserLinkController resources "/artist_links", Profile.ArtistLinkController
resources "/awards", Profile.AwardController, except: [:index, :show] resources "/awards", Profile.AwardController, except: [:index, :show]
resources "/details", Profile.DetailController, only: [:index] resources "/details", Profile.DetailController, only: [:index]
@ -321,13 +321,13 @@ defmodule PhilomenaWeb.Router do
resources "/close", Report.CloseController, only: [:create], singleton: true resources "/close", Report.CloseController, only: [:create], singleton: true
end end
resources "/user_links", UserLinkController, only: [:index] do resources "/artist_links", ArtistLinkController, only: [:index] do
resources "/verification", UserLink.VerificationController, resources "/verification", ArtistLink.VerificationController,
only: [:create], only: [:create],
singleton: true singleton: true
resources "/contact", UserLink.ContactController, only: [:create], singleton: true resources "/contact", ArtistLink.ContactController, only: [:create], singleton: true
resources "/reject", UserLink.RejectController, only: [:create], singleton: true resources "/reject", ArtistLink.RejectController, only: [:create], singleton: true
end end
resources "/dnp_entries", DnpEntryController, only: [:index] do resources "/dnp_entries", DnpEntryController, only: [:index] do

View file

@ -1,21 +1,21 @@
h1 User Links h1 Artist Links
p Link creation is done via the Users menu. p Link creation is done via the Users menu.
p Verifying a link will automatically award an artist badge if the link is public, no artist badge exists, and an "artist:" tag is specified. p Verifying a link will automatically award an artist badge if the link is public, no artist badge exists, and an "artist:" tag is specified.
= form_for :user_link, Routes.admin_user_link_path(@conn, :index), [method: "get", class: "hform"], fn f -> = form_for :artist_link, Routes.admin_artist_link_path(@conn, :index), [method: "get", class: "hform"], fn f ->
.field .field
= text_input f, :q, name: :q, value: @conn.params["q"], class: "input hform__text", placeholder: "Search query", autocapitalize: "none" = text_input f, :q, name: :q, value: @conn.params["q"], class: "input hform__text", placeholder: "Search query", autocapitalize: "none"
= submit "Search", class: "hform__button button" = submit "Search", class: "hform__button button"
- route = fn p -> Routes.admin_user_link_path(@conn, :index, p) end - route = fn p -> Routes.admin_artist_link_path(@conn, :index, p) end
- pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @user_links, route: route, params: link_scope(@conn), conn: @conn - pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @artist_links, route: route, params: link_scope(@conn), conn: @conn
.block .block
.block__header .block__header
= if @conn.params["all"] do = if @conn.params["all"] do
= link "Show unverified only", to: Routes.admin_user_link_path(@conn, :index) = link "Show unverified only", to: Routes.admin_artist_link_path(@conn, :index)
- else - else
= link "Show all", to: Routes.admin_user_link_path(@conn, :index, all: "true") = link "Show all", to: Routes.admin_artist_link_path(@conn, :index, all: "true")
= pagination = pagination
@ -30,7 +30,7 @@ p Verifying a link will automatically award an artist badge if the link is publi
th Mark th Mark
th Public th Public
tbody tbody
= for link <- @user_links do = for link <- @artist_links do
tr tr
td class=link_state_class(link) td class=link_state_class(link)
strong strong
@ -56,20 +56,20 @@ p Verifying a link will automatically award an artist badge if the link is publi
= render PhilomenaWeb.TagView, "_tag.html", tag: link.tag, conn: @conn = render PhilomenaWeb.TagView, "_tag.html", tag: link.tag, conn: @conn
td td
=> link "View", to: Routes.profile_user_link_path(@conn, :show, link.user, link) => link "View", to: Routes.profile_artist_link_path(@conn, :show, link.user, link)
' &bull; ' &bull;
= link "Edit", to: Routes.profile_user_link_path(@conn, :edit, link.user, link) = link "Edit", to: Routes.profile_artist_link_path(@conn, :edit, link.user, link)
td td
=> link "Verify", to: Routes.admin_user_link_verification_path(@conn, :create, link), method: :post => link "Verify", to: Routes.admin_artist_link_verification_path(@conn, :create, link), method: :post
' &bull; ' &bull;
=> link "Reject", to: Routes.admin_user_link_reject_path(@conn, :create, link), method: :post => link "Reject", to: Routes.admin_artist_link_reject_path(@conn, :create, link), method: :post
br br
= if not verified?(link) do = if not verified?(link) do
= if contacted?(link) do = if contacted?(link) do
' Artist contacted ' Artist contacted
- else - else
= link "Artist contacted", to: Routes.admin_user_link_contact_path(@conn, :create, link), method: :post = link "Artist contacted", to: Routes.admin_artist_link_contact_path(@conn, :create, link), method: :post
td td
= public_text(link) = public_text(link)

View file

@ -85,8 +85,8 @@ h1 Users
=> link to: Routes.admin_user_ban_path(@conn, :new, username: user.name) do => link to: Routes.admin_user_ban_path(@conn, :new, username: user.name) do
i.fa.fa-fw.fa-ban i.fa.fa-fw.fa-ban
' Ban ' Ban
= if can?(@conn, :edit, Philomena.UserLinks.UserLink) do = if can?(@conn, :edit, Philomena.ArtistLinks.ArtistLink) do
=> link to: Routes.profile_user_link_path(@conn, :new, user) do => link to: Routes.profile_artist_link_path(@conn, :new, user) do
i.fa.fa-fw.fa-link i.fa.fa-fw.fa-link
' Add link ' Add link

View file

@ -21,12 +21,12 @@ br
= link "My Listings", to: Routes.dnp_entry_path(@conn, :index, mine: "1") = link "My Listings", to: Routes.dnp_entry_path(@conn, :index, mine: "1")
- not is_nil(@current_user) -> - not is_nil(@current_user) ->
' You must have a verified user link to create and manage DNP entries. ' You must have a verified artist link to create and manage DNP entries.
= link "Request a user link", to: Routes.profile_user_link_path(@conn, :new, @current_user) = link "Request an artist link", to: Routes.profile_artist_link_path(@conn, :new, @current_user)
| . | .
- true -> - true ->
' You must be logged in and have a verified user link to create and manage DNP entries. ' You must be logged in and have a verified artist link to create and manage DNP entries.
h3 The List h3 The List

View file

@ -83,7 +83,7 @@ header.header
a.header__link href="/posts?pq=my:posts" a.header__link href="/posts?pq=my:posts"
i.fas.fa-fw.fa-pen-square> i.fas.fa-fw.fa-pen-square>
| Posts | Posts
a.header__link href=Routes.profile_user_link_path(@conn, :index, @current_user) a.header__link href=Routes.profile_artist_link_path(@conn, :index, @current_user)
i.fa.fa-fw.fa-link> i.fa.fa-fw.fa-link>
| Links | Links
a.header__link href="/settings/edit" a.header__link href="/settings/edit"

View file

@ -53,11 +53,11 @@
span.header__counter__admin span.header__counter__admin
= @report_count = @report_count
= if @user_link_count do = if @artist_link_count do
= link to: Routes.admin_user_link_path(@conn, :index), class: "header__link", title: "User Links" do = link to: Routes.admin_artist_link_path(@conn, :index), class: "header__link", title: "Artist Links" do
' L ' L
span.header__counter__admin span.header__counter__admin
= @user_link_count = @artist_link_count
= if @dnp_entry_count do = if @dnp_entry_count do
= link to: Routes.admin_dnp_entry_path(@conn, :index), class: "header__link", title: "DNP Requests" do = link to: Routes.admin_dnp_entry_path(@conn, :index), class: "header__link", title: "DNP Requests" do

View file

@ -141,11 +141,11 @@ a.label.label--primary.label--block href="#" data-click-toggle=".js-admin__optio
i.fas.fa-fw.fa-dollar-sign i.fas.fa-fw.fa-dollar-sign
span.admin__button Donations span.admin__button Donations
= if can?(@conn, :edit, %Philomena.UserLinks.UserLink{}) do = if can?(@conn, :edit, %Philomena.ArtistLinks.ArtistLink{}) do
li li
= link to: Routes.profile_user_link_path(@conn, :new, @user) do = link to: Routes.profile_artist_link_path(@conn, :new, @user) do
i.fa.fa-fw.fa-link i.fa.fa-fw.fa-link
span.admin__button Add User Link span.admin__button Add Artist Link
= if can?(@conn, :create, Philomena.Bans.User) do = if can?(@conn, :create, Philomena.Bans.User) do
li li

View file

@ -24,9 +24,15 @@
= link "More information", to: Routes.profile_commission_path(@conn, :show, @user) = link "More information", to: Routes.profile_commission_path(@conn, :show, @user)
- current?(@user, @conn.assigns.current_user) -> - current?(@user, @conn.assigns.current_user) ->
= if Enum.any?(@conn.assigns.user.verified_links) do
em em
' You don't have any commission information listed yet. ' You don't have any commission information listed yet.
=> link "Click here", to: Routes.profile_commission_path(@conn, :new, @user) => link "Click here", to: Routes.profile_commission_path(@conn, :new, @user)
' to set it up. ' to set it up.
- else
em
' You must have a verified Artist Link to create a commission page.
=> link "Click here", to: Routes.profile_artist_link_path(@conn, :new, @user)
' to set one up.
- true -> - true ->

View file

@ -7,19 +7,15 @@
.field .field
p p
label for="tag_name" label for="tag_name"
' The tag, ' Artist Link validation is intended for artists. Validating your link will give you control over how your art is shared on the site and will allow you to create a
em> specific a> href="/commissions" commissions
' to you, usually ' listing. Do not request a link if the source has no artwork that you yourself did not create.
code> = text_input f, :tag_name, value: assigns[:tag_name], class: "input", autocomplete: "off", placeholder: "artist:your-name", data: [ac: "true", ac_min_length: "3", ac_source: "/tags/autocomplete?term="]
| artist:
em artist name here
' or a series name
= text_input f, :tag_name, value: assigns[:tag_name], class: "input", autocomplete: "off", placeholder: "artist:name", data: [ac: "true", ac_min_length: "3", ac_source: "/tags/autocomplete?term="]
= error_tag f, :tag = error_tag f, :tag
.field .field
label for="uri" label for="uri"
' URL of your art webpage ' URL of your art webpage (may be your Derpibooru profile page if you have no other sources)
= url_input f, :uri, class: "input input--wide", placeholder: "https://www.deviantart.com/your-name", required: true = url_input f, :uri, class: "input input--wide", placeholder: "https://www.deviantart.com/your-name", required: true
= error_tag f, :uri = error_tag f, :uri

View file

@ -0,0 +1,2 @@
h1 Edit Link
= render PhilomenaWeb.Profile.ArtistLinkView, "_form.html", conn: @conn, changeset: @changeset, tag_name: tag_name(@artist_link), action: Routes.profile_artist_link_path(@conn, :update, @artist_link.user, @artist_link)

View file

@ -0,0 +1,23 @@
h1 Artist Links
p
a.button href=Routes.profile_artist_link_path(@conn, :new, @user)
' Request a link
p
' Artist links associate your account on Derpibooru with tags about content you create and with accounts on sites elsewhere. This allows users to easily identify artists and staff to act more rapidly on takedown requests.
table.table
thead
tr
th URI
th Options
th Verification Code
th Verified?
th Public
tbody
= for link <- @artist_links do
tr
td = link link.uri, to: link.uri
td = link "View Details", to: Routes.profile_artist_link_path(@conn, :show, @user, link)
td = link.verification_code
th = verified_as_string(link)
th = public_as_string(link)

View file

@ -0,0 +1,2 @@
h1 Request Artist Link
= render PhilomenaWeb.Profile.ArtistLinkView, "_form.html", changeset: @changeset, action: Routes.profile_artist_link_path(@conn, :create, @user), conn: @conn

View file

@ -1,73 +1,72 @@
h1 h1
' Link to ' Link to
= link @user_link.uri, to: @user_link.uri = link @artist_link.uri, to: @artist_link.uri
h3 Status h3 Status
= cond do = cond do
- verified?(@user_link) -> - verified?(@artist_link) ->
p This link has been verified by a member of the administration team. p This link has been verified by a member of the administration team.
p You can now remove the verification text from your website if you have not done so already. p You can now remove the verification text from your website if you have not done so already.
- contacted?(@user_link) -> - contacted?(@artist_link) ->
p p
strong This link is awaiting your reply on the linked website in order to be verified. strong This link is awaiting your reply on the linked website in order to be verified.
p p
' An administrator ' An administrator
=> "(#{@user_link.contacted_by_user.name})" => "(#{@artist_link.contacted_by_user.name})"
' has manually contacted you at the address above, as your verification code was not found on the website. Please respond to the message from the administrator to confirm your link. ' has manually contacted you at the address above, as your verification code was not found on the website. Please respond to the message from the administrator to confirm your link.
p The verification code is: p The verification code is:
p p
code code
h1 = @user_link.verification_code h1 = @artist_link.verification_code
- link_verified?(@user_link) -> - link_verified?(@artist_link) ->
p p
strong This link is pending verification by a member of the administration team. strong This link is pending verification by a member of the administration team.
p We've now found the verification code on your website. An administrator still needs to check the tag list before verifying the link. Please leave the code on your website until verification is complete. p We've now found the verification code on your website. An administrator still needs to check the tag list before verifying the link. Please leave the code on your website until verification is complete.
p If you need it again, your verification code is: p If you need it again, your verification code is:
p p
code code
h1 = @user_link.verification_code h1 = @artist_link.verification_code
- unverified?(@user_link) -> - unverified?(@artist_link) ->
p p
strong This link is pending verification by a member of the administration team. strong This link is pending verification by a member of the administration team.
p .dnp-warning
h3 To have your link verified as fast as possible, please place this text somewhere on the page you are linking. h3 To have your link verified as fast as possible, please place this text somewhere on the page you are linking.
p
code code
h1 = @user_link.verification_code h1 = @artist_link.verification_code
p Otherwise, an administrator will have to contact you to verify your identity. p Otherwise, an administrator will have to contact you to verify your identity.
p Once the link has been verified you can remove the text; the text simply allows the team to directly check with your website rather than messaging you and waiting for a reply. p Once the link has been verified you can remove the text; the text simply allows the team to directly check with your website rather than messaging you and waiting for a reply.
- rejected?(@user_link) -> - rejected?(@artist_link) ->
p This link has been rejected by a member of the administration team; this is probably because you were not reachable in a timely manner (~1 week) to verify the link. p This link has been rejected by a member of the administration team; this is probably because you were not reachable in a timely manner (~1 week) to verify the link.
h3 Visibility h3 Visibility
= if public?(@user_link) do = if public?(@artist_link) do
p This link is public, and will be shown around the site. p This link is public, and will be shown around the site.
- else - else
p This link is not public, and will only be shown to administrators. p This link is not public, and will only be shown to administrators.
h3 Associated tag h3 Associated tag
= if @user_link.tag do = if @artist_link.tag do
.tag-list .tag-list
= render PhilomenaWeb.TagView, "_tag.html", tag: @user_link.tag, conn: @conn = render PhilomenaWeb.TagView, "_tag.html", tag: @artist_link.tag, conn: @conn
- else - else
p There is no tag associated with this link. p There is no tag associated with this link.
= if can?(@conn, :index, Philomena.UserLinks.UserLink) do = if can?(@conn, :index, Philomena.ArtistLinks.ArtistLink) do
p p
=> link "Edit", to: Routes.profile_user_link_path(@conn, :edit, @user, @user_link) => link "Edit", to: Routes.profile_artist_link_path(@conn, :edit, @user, @artist_link)
' &bull; ' &bull;
=> link "Verify", to: Routes.admin_user_link_verification_path(@conn, :create, @user_link), method: :post => link "Verify", to: Routes.admin_artist_link_verification_path(@conn, :create, @artist_link), method: :post
' &bull; ' &bull;
=> link "Reject", to: Routes.admin_user_link_reject_path(@conn, :create, @user_link), method: :post => link "Reject", to: Routes.admin_artist_link_reject_path(@conn, :create, @artist_link), method: :post
= if not verified?(@user_link) do = if not verified?(@artist_link) do
' &bull; ' &bull;
= if contacted?(@user_link) do = if contacted?(@artist_link) do
' Artist contacted ' Artist contacted
- else - else
= link "Artist contacted", to: Routes.admin_user_link_contact_path(@conn, :create, @user_link), method: :post = link "Artist contacted", to: Routes.admin_artist_link_contact_path(@conn, :create, @artist_link), method: :post
= link "Back", to: Routes.profile_user_link_path(@conn, :index, @user) = link "Back", to: Routes.profile_artist_link_path(@conn, :index, @user)

View file

@ -58,12 +58,12 @@
.block__content.commission__block_body .block__content.commission__block_body
== @rendered.will_not_create == @rendered.will_not_create
/ User link block / Artist link block
/.block /.block
.block__header: span.block__header__title User Links .block__header: span.block__header__title Artist Links
- is_current = (current_user && current_user.id == @user.id) - is_current = (current_user && current_user.id == @user.id)
- if @links.present? || is_current - if @links.present? || is_current
= render partial: 'profiles/user_link_area' = render partial: 'profiles/artist_link_area'
/ Options block / Options block
.block .block

View file

@ -65,10 +65,10 @@
.block .block
= if current?(@user, @conn.assigns.current_user) or manages_links?(@conn, @user) do = if current?(@user, @conn.assigns.current_user) or manages_links?(@conn, @user) do
a.block__header--single-item href=Routes.profile_user_link_path(@conn, :new, @user) User Links a.block__header--single-item href=Routes.profile_artist_link_path(@conn, :new, @user) Artist Links
- else - else
.block__header .block__header
span.block__header__title User Links span.block__header__title Artist Links
= for link <- @user.verified_links, should_see_link?(@conn, @user, link) do = for link <- @user.verified_links, should_see_link?(@conn, @user, link) do
- watchers = if link.tag, do: @watcher_counts[link.tag.id] || 0, else: 0 - watchers = if link.tag, do: @watcher_counts[link.tag.id] || 0, else: 0
@ -91,10 +91,10 @@
- else - else
' Hidden ' Hidden
' &bull; ' &bull;
a href=Routes.profile_user_link_path(@conn, :edit, @user, link) a href=Routes.profile_artist_link_path(@conn, :edit, @user, link)
' Edit ' Edit
' &bull; ' &bull;
a href=Routes.admin_user_link_reject_path(@conn, :create, link) data-method="post" a href=Routes.admin_artist_link_reject_path(@conn, :create, link) data-method="post"
' Reject ' Reject
- else - else
=> unless link.public do => unless link.public do

View file

@ -1,2 +0,0 @@
h1 Edit Link
= render PhilomenaWeb.Profile.UserLinkView, "_form.html", conn: @conn, changeset: @changeset, tag_name: tag_name(@user_link), action: Routes.profile_user_link_path(@conn, :update, @user_link.user, @user_link)

View file

@ -1,23 +0,0 @@
h1 User Links
p
a.button href=Routes.profile_user_link_path(@conn, :new, @user)
' Create a link
p
' User links associate your account on Derpibooru with tags about content you create and with accounts on sites elsewhere. This allows users to easily identify artists and admins to act more rapidly on takedown requests.
table.table
thead
tr
th URI
th Options
th Verification Code
th Verified?
th Public
tbody
= for link <- @user_links do
tr
td = link link.uri, to: link.uri
td = link "View Details", to: Routes.profile_user_link_path(@conn, :show, @user, link)
td = link.verification_code
th = verified_as_string(link)
th = public_as_string(link)

View file

@ -1,2 +0,0 @@
h1 Create Link
= render PhilomenaWeb.Profile.UserLinkView, "_form.html", changeset: @changeset, action: Routes.profile_user_link_path(@conn, :create, @user), conn: @conn

View file

@ -23,7 +23,7 @@ p
strong> Only an owner of an image's rights (normally the artist) can request a takedown. strong> Only an owner of an image's rights (normally the artist) can request a takedown.
' If you're the artist, you'll ' If you're the artist, you'll
strong> need strong> need
' a verified user link. ' a verified artist link.
p p
' For more information, please read the ' For more information, please read the
= link "takedown policy", to: "/pages/takedowns" = link "takedown policy", to: "/pages/takedowns"

View file

@ -43,10 +43,10 @@
strong.comment_deleted> Hidden links: strong.comment_deleted> Hidden links:
br br
= for user_link <- @tag.hidden_links do = for artist_link <- @tag.hidden_links do
=> link user_link.user.name, to: Routes.profile_path(@conn, :show, user_link.user) => link artist_link.user.name, to: Routes.profile_path(@conn, :show, artist_link.user)
' &rarr; ' &rarr;
=> link user_link.uri, to: user_link.uri => link artist_link.uri, to: artist_link.uri
br br

View file

@ -1,4 +1,4 @@
defmodule PhilomenaWeb.Admin.UserLinkView do defmodule PhilomenaWeb.Admin.ArtistLinkView do
use PhilomenaWeb, :view use PhilomenaWeb, :view
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
@ -35,7 +35,7 @@ defmodule PhilomenaWeb.Admin.UserLinkView do
def rejected?(%{aasm_state: state}), do: state == "rejected" def rejected?(%{aasm_state: state}), do: state == "rejected"
def public_text(%{public: true}), do: "Yes" def public_text(%{public: true}), do: "Yes"
def public_text(_user_link), do: "No" def public_text(_artist_link), do: "No"
def public?(%{public: public}), do: !!public def public?(%{public: public}), do: !!public
end end

View file

@ -43,7 +43,7 @@ defmodule PhilomenaWeb.Admin.UserView do
def description("moderator", "Image"), do: "Manage images" def description("moderator", "Image"), do: "Manage images"
def description("moderator", "DuplicateReport"), do: "Manage duplicates" def description("moderator", "DuplicateReport"), do: "Manage duplicates"
def description("moderator", "Comment"), do: "Manage comments" def description("moderator", "Comment"), do: "Manage comments"
def description("moderator", "UserLink"), do: "Manage user links" def description("moderator", "ArtistLink"), do: "Manage artist links"
def description("moderator", "Topic"), do: "Moderate forums" def description("moderator", "Topic"), do: "Moderate forums"
def description("moderator", "Tag"), do: "Manage tag details" def description("moderator", "Tag"), do: "Manage tag details"
@ -77,7 +77,7 @@ defmodule PhilomenaWeb.Admin.UserView do
["moderator", "DuplicateReport"], ["moderator", "DuplicateReport"],
["moderator", "Comment"], ["moderator", "Comment"],
["moderator", "Tag"], ["moderator", "Tag"],
["moderator", "UserLink"], ["moderator", "ArtistLink"],
["moderator", "Topic"] ["moderator", "Topic"]
] ]
end end

View file

@ -1,11 +1,11 @@
defmodule PhilomenaWeb.Api.Json.UserLinkView do defmodule PhilomenaWeb.Api.Json.ArtistLinkView do
use PhilomenaWeb, :view use PhilomenaWeb, :view
def render("user_link.json", %{user_link: %{public: false}}) do def render("artist_link.json", %{artist_link: %{public: false}}) do
nil nil
end end
def render("user_link.json", %{user_link: link}) do def render("artist_link.json", %{artist_link: link}) do
%{ %{
user_id: link.user_id, user_id: link.user_id,
created_at: link.created_at, created_at: link.created_at,

View file

@ -21,8 +21,8 @@ defmodule PhilomenaWeb.Api.Json.ProfileView do
links: links:
render_many( render_many(
user.public_links, user.public_links,
PhilomenaWeb.Api.Json.UserLinkView, PhilomenaWeb.Api.Json.ArtistLinkView,
"user_link.json", "artist_link.json",
assigns assigns
), ),
awards: render_many(user.awards, PhilomenaWeb.Api.Json.AwardView, "award.json", assigns) awards: render_many(user.awards, PhilomenaWeb.Api.Json.AwardView, "award.json", assigns)

View file

@ -1,4 +1,4 @@
defmodule PhilomenaWeb.Profile.UserLinkView do defmodule PhilomenaWeb.Profile.ArtistLinkView do
use PhilomenaWeb, :view use PhilomenaWeb, :view
def verified?(%{aasm_state: state}), do: state == "verified" def verified?(%{aasm_state: state}), do: state == "verified"
@ -10,10 +10,10 @@ defmodule PhilomenaWeb.Profile.UserLinkView do
def public?(%{public: public}), do: !!public def public?(%{public: public}), do: !!public
def verified_as_string(%{aasm_state: "verified"}), do: "Yes" def verified_as_string(%{aasm_state: "verified"}), do: "Yes"
def verified_as_string(_user_link), do: "No" def verified_as_string(_artist_link), do: "No"
def public_as_string(%{public: true}), do: "Yes" def public_as_string(%{public: true}), do: "Yes"
def public_as_string(_user_link), do: "No" def public_as_string(_artist_link), do: "No"
def tag_name(%{tag: nil}), do: nil def tag_name(%{tag: nil}), do: nil
def tag_name(%{tag: tag}), do: tag.name def tag_name(%{tag: tag}), do: tag.name

View file

@ -155,7 +155,7 @@ defmodule PhilomenaWeb.TagView do
end end
defp manages_links?(conn), defp manages_links?(conn),
do: can?(conn, :index, Philomena.UserLinks.UserLink) do: can?(conn, :index, Philomena.ArtistLinks.ArtistLink)
defp manages_dnp?(conn), defp manages_dnp?(conn),
do: can?(conn, :index, Philomena.DnpEntries.DnpEntry) do: can?(conn, :index, Philomena.DnpEntries.DnpEntry)

View file

@ -80,7 +80,7 @@
{"name": "moderator", "resource_type": "DuplicateReport"}, {"name": "moderator", "resource_type": "DuplicateReport"},
{"name": "moderator", "resource_type": "Comment"}, {"name": "moderator", "resource_type": "Comment"},
{"name": "moderator", "resource_type": "Tag"}, {"name": "moderator", "resource_type": "Tag"},
{"name": "moderator", "resource_type": "UserLink"}, {"name": "moderator", "resource_type": "ArtistLink"},
{"name": "admin", "resource_type": "Tag"}, {"name": "admin", "resource_type": "Tag"},
{"name": "moderator", "resource_type": "User"}, {"name": "moderator", "resource_type": "User"},
{"name": "admin", "resource_type": "SiteNotice"}, {"name": "admin", "resource_type": "SiteNotice"},