initial user verification stuff

This commit is contained in:
Luna D 2022-03-21 19:08:06 +01:00 committed by Luna D
parent aa1ca50f0c
commit a3db6f6eed
No known key found for this signature in database
GPG key ID: 4B1C63448394F688
12 changed files with 125 additions and 6 deletions

View file

@ -22,6 +22,7 @@ defmodule Philomena.Comments.Comment do
field :deletion_reason, :string, default: ""
field :destroyed_content, :boolean, default: false
field :name_at_post_time, :string
field :approved_at, :utc_datetime
timestamps(inserted_at: :created_at, type: :utc_datetime)
end

View file

@ -82,6 +82,7 @@ defmodule Philomena.Images.Image do
field :hidden_image_key, :string
field :scratchpad, :string
field :hides_count, :integer, default: 0
field :approved_at, :utc_datetime
# todo: can probably remove these now
field :tag_list_cache, :string

View file

@ -23,6 +23,7 @@ defmodule Philomena.Posts.Post do
field :deletion_reason, :string, default: ""
field :destroyed_content, :boolean, default: false
field :name_at_post_time, :string
field :approved_at, :utc_datetime
timestamps(inserted_at: :created_at, type: :utc_datetime)
end

View file

@ -15,6 +15,7 @@ defmodule Philomena.Reports.Report do
field :reason, :string
field :state, :string, default: "open"
field :open, :boolean, default: true
field :system, :boolean, default: false
# fixme: rails polymorphic relation
field :reportable_id, :integer

View file

@ -31,6 +31,7 @@ defmodule Philomena.Topics.Topic do
field :slug, :string
field :anonymous, :boolean, default: false
field :hidden_from_users, :boolean, default: false
field :approved_at, :utc_datetime
timestamps(inserted_at: :created_at, type: :utc_datetime)
end

View file

@ -671,6 +671,18 @@ defmodule Philomena.Users do
|> setup_roles()
end
def verify_user(%User{} = user) do
user
|> User.verify_changeset()
|> Repo.update()
end
def unverify_user(%User{} = user) do
user
|> User.unverify_changeset()
|> Repo.update()
end
defp setup_roles(nil), do: nil
defp setup_roles(user) do

View file

@ -119,6 +119,7 @@ defmodule Philomena.Users.User do
field :hide_default_role, :boolean, default: false
field :senior_staff, :boolean, default: false
field :bypass_rate_limits, :boolean, default: false
field :verified, :boolean, default: false
# For avatar validation/persistence
field :avatar_width, :integer, virtual: true
@ -446,6 +447,14 @@ defmodule Philomena.Users.User do
change(user, forced_filter_id: nil)
end
def verify_changeset(user) do
change(user, verified: true)
end
def unverify_changeset(user) do
change(user, verified: false)
end
def create_totp_secret_changeset(user) do
secret = :crypto.strong_rand_bytes(15) |> Base.encode32()
data = Philomena.Users.Encryptor.encrypt_model(secret)

View file

@ -0,0 +1,44 @@
defmodule PhilomenaWeb.Admin.User.VerificationController do
use PhilomenaWeb, :controller
alias Philomena.Users.User
alias Philomena.Users
plug :verify_authorized
plug :load_resource, model: User, id_name: "user_id", id_field: "slug", persisted: true
def create(conn, _params) do
{:ok, user} = Users.verify_user(conn.assigns.user)
conn
|> put_flash(:info, "User verification granted.")
|> moderation_log(details: &log_details/3, data: user)
|> redirect(to: Routes.profile_path(conn, :show, user))
end
def delete(conn, _params) do
{:ok, user} = Users.unverify_user(conn.assigns.user)
conn
|> put_flash(:info, "User verification revoked.")
|> moderation_log(details: &log_details/3, data: user)
|> redirect(to: Routes.profile_path(conn, :show, user))
end
defp verify_authorized(conn, _opts) do
case Canada.Can.can?(conn.assigns.current_user, :index, User) do
true -> conn
_false -> PhilomenaWeb.NotAuthorizedPlug.call(conn)
end
end
defp log_details(conn, action, user) do
body =
case action do
:create -> "Granted verification to #{user.name}"
:delete -> "Revoked verification from #{user.name}"
end
%{body: body, subject_path: Routes.profile_path(conn, :show, user)}
end
end

View file

@ -379,6 +379,8 @@ defmodule PhilomenaWeb.Router do
only: [:create, :delete],
singleton: true
resources "/verification", User.VerificationController, only: [:create, :delete], singleton: true
resources "/unlock", User.UnlockController, only: [:create], singleton: true
resources "/api_key", User.ApiKeyController, only: [:delete], singleton: true
resources "/downvotes", User.DownvoteController, only: [:delete], singleton: true

View file

@ -153,8 +153,19 @@ a.label.label--primary.label--block href="#" data-click-toggle=".js-admin__optio
i.fa.fa-fw.fa-ban
span.admin__button Ban this sucker
ul.profile-admin__options__column
= if can?(@conn, :index, Philomena.Users.User) do
li
= link to: Routes.admin_user_api_key_path(@conn, :delete, @user), data: [confirm: "Are you really, really sure?", method: "delete"] do
i.fas.fa-fw.fa-key
span.admin__button Reset API key
li
= if @user.verified do
= link to: Routes.admin_user_verification_path(@conn, :delete, @user), data: [confirm: "Are you really, really sure?", method: "delete"] do
i.fas.fa-fw.fa-user-times
span.admin__button Revoke Verification
- else
= link to: Routes.admin_user_verification_path(@conn, :create, @user), data: [confirm: "Are you really, really sure?", method: "create"] do
i.fas.fa-fw.fa-user-check
span.admin__button Grant Verification

View file

@ -0,0 +1,29 @@
defmodule Philomena.Repo.Migrations.AddApprovalQueue do
use Ecto.Migration
def change do
alter table("reports") do
add :system, :boolean, default: false
end
alter table("images") do
add :approved_at, :utc_datetime
end
alter table("comments") do
add :approved_at, :utc_datetime
end
alter table("posts") do
add :approved_at, :utc_datetime
end
alter table("topics") do
add :approved_at, :utc_datetime
end
alter table("users") do
add :verified, :boolean, default: false
end
end
end

View file

@ -282,7 +282,8 @@ CREATE TABLE public.comments (
deletion_reason character varying DEFAULT ''::character varying NOT NULL,
destroyed_content boolean DEFAULT false,
name_at_post_time character varying,
body character varying NOT NULL
body character varying NOT NULL,
approved_at timestamp(0) without time zone
);
@ -971,7 +972,8 @@ CREATE TABLE public.images (
hides_count integer DEFAULT 0 NOT NULL,
image_duration double precision,
description character varying DEFAULT ''::character varying NOT NULL,
scratchpad character varying
scratchpad character varying,
approved_at timestamp(0) without time zone
);
@ -1258,7 +1260,8 @@ CREATE TABLE public.posts (
deletion_reason character varying DEFAULT ''::character varying NOT NULL,
destroyed_content boolean DEFAULT false NOT NULL,
name_at_post_time character varying,
body character varying NOT NULL
body character varying NOT NULL,
approved_at timestamp(0) without time zone
);
@ -1300,7 +1303,8 @@ CREATE TABLE public.reports (
admin_id integer,
reportable_id integer NOT NULL,
reportable_type character varying NOT NULL,
reason character varying NOT NULL
reason character varying NOT NULL,
system boolean DEFAULT false
);
@ -1676,7 +1680,8 @@ CREATE TABLE public.topics (
deleted_by_id integer,
locked_by_id integer,
last_post_id integer,
hidden_from_users boolean DEFAULT false NOT NULL
hidden_from_users boolean DEFAULT false NOT NULL,
approved_at timestamp(0) without time zone
);
@ -2050,7 +2055,8 @@ CREATE TABLE public.users (
description character varying,
scratchpad character varying,
bypass_rate_limits boolean DEFAULT false,
scale_large_images character varying(255) DEFAULT 'true'::character varying NOT NULL
scale_large_images character varying(255) DEFAULT 'true'::character varying NOT NULL,
verified boolean DEFAULT false
);
@ -4970,3 +4976,4 @@ INSERT INTO public."schema_migrations" (version) VALUES (20210921025336);
INSERT INTO public."schema_migrations" (version) VALUES (20210929181319);
INSERT INTO public."schema_migrations" (version) VALUES (20211107130226);
INSERT INTO public."schema_migrations" (version) VALUES (20211219194836);
INSERT INTO public."schema_migrations" (version) VALUES (20220321173359);