Skip to content

Commit

Permalink
Initial MVP
Browse files Browse the repository at this point in the history
  • Loading branch information
maxime-rainville committed Jul 29, 2022
1 parent df6e9d1 commit 0d2ccf1
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 101 deletions.
108 changes: 7 additions & 101 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,109 +1,15 @@
# SilverStripe supported module skeleton
# Silverstripe CMS Password helper

A useful skeleton to more easily create a [Silverstripe Module](https://docs.silverstripe.org/en/4/developer_guides/extending/modules/) that conform to the
[Module Standard](https://docs.silverstripe.org/en/developer_guides/extending/modules/#module-standard).
This Silverstripe CMS module aims to make it easy for password managers to change passwords on behalf of users.

This readme contains descriptions of the parts of this module base you should customise to meet you own module needs.
For example, the module name in the H1 above should be you own module name, and the description text you are reading now
is where you should provide a good short explanation of what your module does.
It implements the [Well-Known URL for Changing Passwords](https://w3c.github.io/webappsec-change-password-url/) W3C spec in Silverstripe CMS.

Where possible we have included default text that can be included as is into your module and indicated in
other places where you need to customise it

Below is a template of the sections of your readme.md you should ideally include to met the Module Standard
and help others make use of your modules.

### Steps to prepare this module for your own use:

- Clone this repository into a folder
- Add your name/organisation to `LICENSE.md`
- Update this readme with information about your module. Ensure sections that aren't relevant are deleted and
placeholders are edited where relevant
- Review the README files in the various provided directories. You should replace these with `.gitkeep` or delete the
directories
- Update the module's `composer.json` with your requirements and package name
- Update (or remove) `package.json` with your requirements and package name. Run `yarn` (or remove `yarn.lock`) to
ensure dependencies resolve correctly
- Clear the git history by running `rm -rf .git && git init`
- Add and push to a VCS repository
- Either [publish](https://getcomposer.org/doc/02-libraries.md#publishing-to-packagist) the module on packagist.org, or add a [custom repository](https://getcomposer.org/doc/02-libraries.md#publishing-to-a-vcs) to your main `composer.json`
- Require the module in your main `composer.json`
- If you need to build a JS client
- Ensure that `vendor/silverstripe/admin` is installed with `composer install --prefer-source` instead of the default `--prefer-dist`. You may need to first remove the module from the vendor folder.
- Install third party dependencies in your module AND in `vendor/silverstripe/admin` by running `yarn install` in both locations
- Start developing your module!

## Requirements

* SilverStripe ^4.0
* [Yarn](https://yarnpkg.com/lang/en/), [NodeJS](https://nodejs.org/en/) (6.x) and [npm](https://npmjs.com) (for building
frontend assets)
* Other module
* Other server requirement
* Etc
Read [Help users change passwords easily by adding a well-known URL for changing passwords](https://web.dev/change-password-url/) on web.dev for an explanation.

## Installation
Add some installation instructions here, having a 1 line composer copy and paste is useful.
Here is a composer command to create a new module project. Ensure you read the
['publishing a module'](https://docs.silverstripe.org/en/developer_guides/extending/how_tos/publish_a_module/) guide
and update your module's composer.json to designate your code as a SilverStripe module.

```
composer require silverstripe-module/skeleton 4.x-dev
```

**Note:** When you have completed your module, submit it to Packagist or add it as a VCS repository to your
project's composer.json, pointing to the private repository URL.

## License
See [License](license.md)
Just install the module. It works out of the box without any config.

We have included a 3-clause BSD license you can use as a default. We advocate for the BSD license as
it is one of the most permissive and open licenses.

Feel free to alter the [license.md](license.md) to suit if you wan to use an alternative license.
You can use [choosealicense.com](http://choosealicense.com) to help pick a suitable license for your project.

## Documentation
* [Documentation readme](docs/en/readme.md)

Add links into your docs/<language> folder here unless your module only requires minimal documentation
in that case, add here and remove the docs folder. You might use this as a quick table of content if you
mhave multiple documentation pages.

## Example configuration (optional)
If your module makes use of the config API in SilverStripe it's a good idea to provide an example config
here that will get the module working out of the box and expose the user to the possible configuration options.

Provide a yaml code example where possible.

```yaml

Page:
config_option: true
another_config:
- item1
- item2

```

## Maintainers
* Person here <person@emailaddress.com>
* Another maintainer <maintain@emailaddress.com>

## Bugtracker
Bugs are tracked in the issues section of this repository. Before submitting an issue please read over
existing issues to ensure yours is unique.

If the issue does look like a new bug:

- Create a new issue
- Describe the steps required to reproduce your issue, and the expected outcome. Unit tests, screenshots
and screencasts can help here.
- Describe your environment as detailed as possible: SilverStripe version, Browser, PHP version,
Operating System, any installed SilverStripe modules.

Please report security issues to the module maintainers directly. Please don't file security issues in the bugtracker.

## Development and contribution
If you would like to make contributions to the module please ensure you raise a pull request and discuss with the module maintainers.
composer require maxime-rainville/silverstripe-password-manager-helper
```
10 changes: 10 additions & 0 deletions _config/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SilverStripe\Control\Director:
rules:
'.well-known/change-password':
Controller: '%$MaximeRainville\SilverstripePasswordManagerHelper\WellKnown'

SilverStripe\Core\Injector\Injector:
SilverStripe\Forms\PasswordField:
class: MaximeRainville\SilverstripePasswordManagerHelper\PasswordField
SilverStripe\Forms\ConfirmedPasswordField:
class: MaximeRainville\SilverstripePasswordManagerHelper\ConfirmedPasswordField
75 changes: 75 additions & 0 deletions src/ConfirmedPasswordField.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

namespace MaximeRainville\SilverstripePasswordManagerHelper;

use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\ConfirmedPasswordField as BaseConfirmedPasswordField;
use SilverStripe\Forms\Form;

/**
* Extends the ConfirmedPasswordField to set better auto-complete value.
*/
class ConfirmedPasswordField extends BaseConfirmedPasswordField
{

/**
* @param string $name
* @param string $title
* @param mixed $value
* @param Form $form
* @param boolean $showOnClick
* @param string $titleConfirmField Alternate title (not localizeable)
*/
public function __construct(
$name,
$title = null,
$value = "",
$form = null,
$showOnClick = false,
$titleConfirmField = null
) {
if ($this->forceShowConfirmPassword($form)) {
$showOnClick = false;
}
parent::__construct($name, $title, $value, $form, $showOnClick, $titleConfirmField);
$this->getPasswordField()->setAutocomplete('new-password');
$this->getConfirmPasswordField()->setAutocomplete('new-password');
}


private function forceShowConfirmPassword(): bool
{
$session = Injector::inst()->get(HTTPRequest::class)->getSession();
if ($session->get('ForceShowConfirmPassword')) {
$session->clear('ForceShowConfirmPassword');
return true;
}
return false;
}

public function setRequireExistingPassword($show)
{
// Store the current autocomplete value
$oldField = $this->passwordField;
$autocomplete = $oldField ? $oldField->getAutocomplete() : '';

// Don't modify if already added / removed
if ((bool)$show === $this->requireExistingPassword) {
return $this;
}
$this->requireExistingPassword = $show;
$name = $this->getName();
$currentName = "{$name}[_CurrentPassword]";
if ($show) {
$passwordField = PasswordField::create($currentName, _t('SilverStripe\\Security\\Member.CURRENT_PASSWORD', 'Current Password'));
$passwordField->setAutocomplete('current-password');
$this->getChildren()->unshift($passwordField);
} else {
$this->getChildren()->removeByName($currentName, true);
}
return $this;
}

}
42 changes: 42 additions & 0 deletions src/PasswordField.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace MaximeRainville\SilverstripePasswordManagerHelper;

use SilverStripe\Forms\PasswordField as BasePasswordField;

/**
* Extends the PasswordFiled so it can be fill by a password manager
*/
class PasswordField extends BasePasswordField
{

private string $autocomplete = '';

/**
* {@inheritdoc}
*/
public function getAttributes()
{
$attributes = parent::getAttributes();
$autocomplete = $this->getAutocomplete();

if ($autocomplete) {
$attributes['autocomplete'] = $autocomplete;
}

return $attributes;
}

public function setAutocomplete(string $value): self
{
$this->autocomplete = $value;

return $this;
}

public function getAutocomplete(): string
{
return $this->autocomplete;
}

}
1 change: 1 addition & 0 deletions src/WellKnown.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public function index(HTTPRequest $request): HTTPResponse
{
//** @var CMSProfileController $profile */
$profile = CMSProfileController::create();
$request->getSession()->set('ForceShowConfirmPassword', true);
return $this->redirect($profile->Link());
}
}

0 comments on commit 0d2ccf1

Please sign in to comment.