Fixes T4931. Each new credential should come with the ability to lock the credential permanently, so that no one can ever edit again. Each existing credential must allow user to lock existing credential.
Details
- Reviewers
epriestley - Group Reviewers
Blessed Reviewers - Maniphest Tasks
- T4931: Add a "Lock Permanently" action to Passphrase
- Commits
- Restricted Diffusion Commit
rPd7b7b1933793: Add a "Lock Permanently" action to Passphrase
Create new credential, verify that you can lock it before saving it. Open existing unlocked credential, verify that option to lock it exists. Once credential is locked, the option to reveal it should be disabled, and editing the credential won't allow username/password updates.
Diff Detail
- Repository
- rP Phabricator
- Branch
- lockcredentials
- Lint
Lint Passed - Unit
No Test Coverage - Build Status
Buildable 188 Build 188: [Placeholder Plan] Wait for 30 Seconds
Event Timeline
Handful of minor things inline, but this looks generally correct to me.
src/applications/passphrase/controller/PassphraseCredentialDestroyController.php | ||
---|---|---|
54–60 | Locking a credential does not need to prevent it from being destroyed -- you should still be able to destroy it, just not read it. | |
src/applications/passphrase/controller/PassphraseCredentialEditController.php | ||
156–178 | When a credential is locked, we should prevent the actual changes from being applied here. Right now if I'm editing a locked credential the "secret" input will be disabled, but I can control-click the document, find the textarea, deleted the disabled="disabled" attribute, and then use the form normally -- even if the credential is locked. Instead, we should only build the $type_is_locked, $type_destroy and $type_secret_id transactions if the credential is not locked. Then even if a user removes the "disabled" attribute they still can not edit the secret. That is, the code should look something like: $xactions[] = name; if (!$credential->getIsLocked()) { $xactions[] = username; $xactions[] = secret; $xactions[] = locked; } | |
255–256 | If the credential is locked, it might be nice to appendRemarkupInstructions() here with a message like "This credential is permanently locked and can not be edited.", to explain why the controls are disabled. | |
270–275 | Let's only show this if the credential is being created. The major reason for this convenience checkbox is that some workflows (like creating a new repository in Diffusion) create credentials using this form as a popup dialog, while you're in the middle of some other workflow -- so once you're done, you don't end up on the credential detail page, but back in the middle of creating a repository or whatever. In these cases it would be inconvenient to navigate to the credential page in order to lock the credential. You can test $is_new to see if the credential is being freshly created vs edited. | |
src/applications/passphrase/controller/PassphraseCredentialLockController.php | ||
53–62 | This block should move above the $request->isFormPost() test on line 37. Currently, you can control-click the document and edit things a bit (this is a little involved) and produce a submit button. Then you click that and end up with an isFormPost() request, which will get you into the if ($request->isFormPost()) block and let you take the action. In this case, taking the action multiple times doesn't matter, but as a general rule it's better to put a check like this earlier, so the main action of the controller is completely unreachable. | |
64–78 | As a recently-introduced optional convenience, you can now replace this longer dialog style: $dialog = id(new AphrontDialogView()) ->setUser($viewer) ->...; return id(new AphrontDialogResponse())->setDialog($dialog); ...with this slightly shorter, less boilerplatey style: return $this->newDialog() ->...; ...provided $this is a PhabricatorController (when you want to build a dialog, it almost always is). | |
src/applications/passphrase/controller/PassphraseCredentialRevealController.php | ||
79–85 | This is correct, but should move above the $request->isFormPost() call on line 37. |
Caught one minor logical issue and two tiny nitpicks, I'm just going to tweak those in the pull. Thanks!
src/applications/passphrase/controller/PassphraseCredentialEditController.php | ||
---|---|---|
177 | I think this is the wrong check (getIsLocked() vs !getIsLocked()) and we can just skip all of these transactions (including $type_destroy, which un-destroys credentials) for locked secrets. Basically just remove this line and the closing brace on 161, so all this stuff is covered by the !getisLocked() check? | |
261–262 | You should concatenate inside pht(), because it's easier for a translator to translate the full string than part of the string. That is, instead of doing this: pht('a').pht('b') ...this is usually better: pht('a'.'b') The static analysis stuff is smart enough to figure out 'a'.'b', but can't combine the other form in the general case. | |
src/applications/passphrase/controller/PassphraseCredentialLockController.php | ||
53–77 | This has no actual impact, but should move above line 37 for consistency. |