Page MenuHomePhabricator

Choose default project image by icon
ClosedPublic

Authored by chad on Jun 30 2017, 9:05 AM.
Tags
None
Referenced Files
F13052159: D18174.id43763.diff
Fri, Apr 19, 7:27 AM
Unknown Object (File)
Fri, Apr 19, 4:48 AM
Unknown Object (File)
Fri, Apr 19, 4:39 AM
Unknown Object (File)
Thu, Apr 18, 9:46 AM
Unknown Object (File)
Wed, Apr 17, 5:22 PM
Unknown Object (File)
Wed, Apr 17, 2:31 PM
Unknown Object (File)
Mon, Apr 15, 9:45 AM
Unknown Object (File)
Sun, Apr 14, 9:25 AM
Subscribers

Details

Summary

Builds out a map for icon->image in Projects, selects the icon's image as the default project image if there is no custom image chosen by the user.

Test Plan

Select various icons, see image change. Test choose picture, pick a new image.

Diff Detail

Repository
rP Phabricator
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

Project icons are customizable via projects.icons, but this hard-codes support for only the default upstream set.

Instead, you should add a key to the configuration, update the default values and validation in PhabricatorProjectIconSet, and provide a way for users to learn what the acceptable values are (maybe a UIExample?).

This revision now requires changes to proceed.Jun 30 2017, 12:45 PM

This doesn't break anything though, right? It's just a nice benefit to extend it to customization? Or does this path make customization not possible?

This doesn't break anything, but I don't want to take a step backwards here by hard-coding this behavior. If you don't want to fully integrate this change, I can commandeer it and integrate it when I have time.

oh, i see what you're saying - add ours to iconset too

Specifically, we currently specify the default icons like this, in PhabricatorProjectIconSet:

array(
  'key' => 'tag',
  'icon' => 'fa-tags',
  'name' => pht('Tag'),
),

...and a user might specify an icon in JSON like this:

{
  "key": "tag",
  "icon": "fa-tags",
  "name": "Tag"
}

We should add a key like "image" to the defaults, and allow users to specify an "image" as well. For example, this would let an install rename the "Tag" icon to "Label" with internal key "label" if they think that word is more clear (or "Label, Eh?" if they primarily speak Canadian) , but keep the actual FontAwesome icon () and new illustrated image, since both are appropriate for an icon called "Label".

Ideally, we should let users pick any image and not expose file path internals to the user. For example, if users specify "/v3/" paths and we later replace these with "/v4/", the mapping will break. We don't have a great way to do (or, generally, to formalize builtins and make them extensible) right now so this is likely to require migrations and guidance eventually, but I suppose we can cross that bridge when we come to it.

chad edited edge metadata.
  • all ok?
  • test setting custom images

I think I got everything covered here, other than adding a "uiexamples" page of the built-in images. I can build that out later once I clean up that folder, also having another 8 icons produced currently.

epriestley added inline comments.
src/applications/project/icon/PhabricatorProjectIconSet.php
266–268

This allows attackers to hijack an administrator account, specify paths like ../../config/local/config.json, and then (at least potentially) read credentials and private keys.

This code should instead build a list of all the allowed values (you can follow the example in PhabricatorFilesOnDiskBuiltinFile->getAllBuiltinFiles()) and then test if the provided value is on that list.

This revision now requires changes to proceed.Jul 8 2017, 3:18 PM
src/applications/project/icon/PhabricatorProjectIconSet.php
266–268

Can that be done in a static method?

Yeah, although you'll need a parameter or something if you want to restrict selections to just intended project icons (but maybe you don't).

chad edited edge metadata.
  • add a check for valid values based on disk

Some inlines about edge cases.

src/applications/project/controller/PhabricatorProjectEditPictureController.php
101–105

(See below for null behavior.)

src/applications/project/icon/PhabricatorProjectIconSet.php
278

I think this error is a little misleading since you actually have to specify "projects/" yourself?

(The "." is also inside the quotes, which could be slightly misleading.)

That is, if resources/builtin/projects/x.png exists, and I specify "x.png", I'll get this error and be confused since the file definitely exists -- but the code really looked at resources/builtin/x.png, without projects/, even though the error suggests it added projects/ for me.

src/applications/project/query/PhabricatorProjectQuery.php
377–381

This may return null (if configuration does not specify an 'image', and the parameter is optional) and then I think we'll fatal. That is, you should make sure that things work OK if a custom icon does not specify an image.

This revision is now accepted and ready to land.Jul 9 2017, 4:33 PM
chad marked an inline comment as done.
  • return an image, not null if no image set

I think this is all square but feels a little fragile.

This revision was automatically updated to reflect the committed changes.

I think this might break with these values:

'image' => ''
'image' => '0'

It looks like they'll evade the setup check, but fail to fall back to the default icon.

Doing this purely in a setup check (instead of also when accessing the image) is a tiny bit flimsy: it's possible for configuration values to change without the configuration setup checks running on them. Two examples are: an administrator editing conf/local/local.json, and a dynamic check (like a conf.php file or a SiteSource) making a runtime decision to produce a different value. We don't perform config setup checks every time a value is read, for performance reasons, and we can't detect when a value changes if it's changed outside of our control (editing a file, dynamic source). We could attempt to detect these changes by hashing config, but there'd be some level of performance/correctness tradeoff.

As written, there's currently no way to do anything dangerous with this minor flimsiness, since we always actually load the file through loadBuiltin() now, which does a check that is slightly too loose but would still catch anything dangerous. You can also only change config outside of our control with root access.

We could clean this up in the future, e.g. when UIExamples gets extended or when we run into a use case for third-party builtin files (it would be nice to let extensions add more project icons today if then want, for example, but they can't do it without us making some upstream changes).