What can be done to many files at once. A person gets here through the timeline's selection
and an agent through the API tools (PhoenixKitPhotos.API); both take the same two steps,
so an agent cannot do what a person's screen would refuse.
plan/4 reads and writes nothing: it checks every file for the person acting and says which
can go ahead and which cannot, and why. run/2 does what a plan says. Nothing here trusts
a client's list: a file the person may not read counts as one that does not exist, and a
plan's files are read from the database, never taken from the request.
| Action | Needs | Does |
|---|---|---|
:download | read | nothing here: PhoenixKitPhotos.Web.Download streams the plan |
:links | read | nothing here: the page lists the addresses |
:copy | read, and upload in the target library | a new file in the target library |
:move | edit, and upload in the target | copy, then the original to the trash |
:tag | edit | adds tags to metadata["tags"], or removes them |
:trash | edit | Storage.trash_file/1, which :restore undoes |
:restore | edit | Storage.restore_file/1 |
Nothing here deletes for good: a trashed file comes back with :restore until the site's
trash retention empties it. A move leaves the original in the trash, and the new file has
all it had (date, place, tags, title and description), since after the retention it is the
only one left. An image that has been edited stays where it is: its unedited original is not
something a new library could hold. Copying someone else's file brings only what core gives a
stranger (Storage.link_copy/3), so not their tags, their place or a date they set by hand.
Files here are the timeline's: photos and videos. :trash and :move ask the host's removal
guard (config :phoenix_kit, :file_removal_guard), and anything it says is in use stays.
Summary
Functions
The action named by a client's string, or nil.
A hash of the values a plan would touch, for a confirmation that must fail when they changed: the same for the same data, whatever order the ids came in, and untouched by what the action does not depend on (a new tag does not void a confirmed trash).
The most files one action takes.
Checks ids for action by auth.
What to tell a person about a file that could not be included.
Does what the plan says. Each file stands alone: one that fails is reported and the rest go
on. :on_progress is called with how many are done and how many there are.
Tags as a list: from a list or from text with commas, trimmed, without doubles, at most 20 of at most 60 characters.
Types
@type action() :: :download | :links | :copy | :move | :tag | :trash | :restore
@type plan() :: %{ action: action(), auth: PhoenixKit.Users.Auth.Scope.t() | nil, files: [PhoenixKit.Modules.Storage.File.t()], refused: [refusal()], target: PhoenixKit.Modules.Storage.Library.t() | nil, add: [String.t()], remove: [String.t()] }
@type reason() ::
:not_found
| :not_allowed
| :same_library
| :already_there
| :not_trashed
| :trashed
| :no_target
| :edited
| :in_use
Functions
The action named by a client's string, or nil.
A hash of the values a plan would touch, for a confirmation that must fail when they changed: the same for the same data, whatever order the ids came in, and untouched by what the action does not depend on (a new tag does not void a confirmed trash).
@spec limit() :: pos_integer()
The most files one action takes.
@spec plan(action(), [String.t()], PhoenixKit.Users.Auth.Scope.t() | nil, map()) :: plan()
Checks ids for action by auth.
params holds what the action needs: "library" (a uuid) for :copy and :move, "add" and
"remove" (lists of tags, or text with commas) for :tag.
What to tell a person about a file that could not be included.
@spec run(plan(), keyword()) :: %{ action: action(), done: [String.t()], failed: [refusal()], created: [String.t()] }
Does what the plan says. Each file stands alone: one that fails is reported and the rest go
on. :on_progress is called with how many are done and how many there are.
Tags as a list: from a list or from text with commas, trimmed, without doubles, at most 20 of at most 60 characters.