Skip to content

Commit 080842b

Browse files
authored
Merge pull request #24 from 1drop/frontend_user_profile
FEATURE: Frontend user profile
2 parents dfc89af + 08835d3 commit 080842b

File tree

16 files changed

+413
-2
lines changed

16 files changed

+413
-2
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
namespace Sandstorm\UserManagement\Controller;
3+
4+
use Neos\Flow\Annotations as Flow;
5+
use Neos\Flow\Security\Account;
6+
use Neos\Flow\Security\Context;
7+
use Neos\Flow\Security\AccountRepository;
8+
use Neos\Flow\Security\Authentication\AuthenticationManagerInterface;
9+
use Neos\Flow\Security\Authentication\Token\UsernamePassword;
10+
use Neos\Flow\Security\Authentication\TokenInterface;
11+
use Neos\Flow\Security\Cryptography\HashService;
12+
use Neos\Flow\Mvc\Controller\ActionController;
13+
use Neos\Party\Domain\Repository\PartyRepository;
14+
use Sandstorm\UserManagement\Domain\Model\User;
15+
use Sandstorm\UserManagement\Domain\Repository\UserRepository;
16+
17+
/**
18+
*/
19+
class ProfileController extends ActionController
20+
{
21+
22+
/**
23+
* @var Context
24+
* @Flow\Inject
25+
*/
26+
protected $securityContext;
27+
28+
/**
29+
* @var PartyRepository
30+
* @Flow\Inject
31+
*/
32+
protected $partyRepository;
33+
34+
/**
35+
* @var UserRepository
36+
* @Flow\Inject
37+
*/
38+
protected $userRepository;
39+
40+
/**
41+
* @Flow\Inject
42+
* @var AuthenticationManagerInterface
43+
*/
44+
protected $authenticationManager;
45+
46+
/**
47+
* @Flow\Inject
48+
* @var AccountRepository
49+
*/
50+
protected $accountRepository;
51+
52+
/**
53+
* @Flow\Inject
54+
* @var HashService
55+
*/
56+
protected $hashService;
57+
58+
59+
public function indexAction()
60+
{
61+
$pluginArguments = $this->request->getInternalArguments();
62+
$account = $this->securityContext->getAccount();
63+
$user = $this->userRepository->findOneByAccount($account);
64+
$this->view->assign('account', $account);
65+
$this->view->assign('user', $user);
66+
$this->view->assign('pluginArguments', $pluginArguments);
67+
}
68+
69+
/**
70+
* @param User $user
71+
*/
72+
public function editProfileAction(User $user)
73+
{
74+
$this->userRepository->update($user);
75+
$this->redirect('index');
76+
}
77+
78+
/**
79+
* @param Account $account
80+
* @param array $password Expects an array in the format array('<password>', '<password confirmation>')
81+
* @Flow\Validate(argumentName="password", type="\Neos\Neos\Validation\Validator\PasswordValidator", options={ "allowEmpty"=1, "minimum"=1, "maximum"=255 })
82+
*/
83+
public function setNewPasswordAction(Account $account, array $password = array()) {
84+
$user = $this->userRepository->findOneByAccount($account);
85+
$password = array_shift($password);
86+
if (strlen(trim(strval($password))) > 0) {
87+
$this->setPassword($account, $password);
88+
}
89+
$this->redirect('index');
90+
91+
}
92+
93+
/**
94+
* Disable the technical error flash message
95+
*
96+
* @return boolean
97+
*/
98+
protected function getErrorFlashMessage()
99+
{
100+
return false;
101+
}
102+
103+
/**
104+
* Sets a new password for the given account
105+
*
106+
* @param Account $account The user to set the password for
107+
* @param string $password A new password
108+
* @return void
109+
* @api
110+
*/
111+
protected function setPassword(Account $account, $password)
112+
{
113+
$tokens = $this->authenticationManager->getTokens();
114+
$indexedTokens = array();
115+
foreach ($tokens as $token) {
116+
/** @var TokenInterface $token */
117+
$indexedTokens[$token->getAuthenticationProviderName()] = $token;
118+
}
119+
120+
/** @var Account $account */
121+
$authenticationProviderName = $account->getAuthenticationProviderName();
122+
if (isset($indexedTokens[$authenticationProviderName]) && $indexedTokens[$authenticationProviderName] instanceof UsernamePassword) {
123+
$account->setCredentialsSource($this->hashService->hashPassword($password));
124+
$this->accountRepository->update($account);
125+
}
126+
}
127+
}

Classes/Domain/Repository/UserRepository.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
* *
77
* */
88

9+
use Neos\Flow\Security\Account;
910
use Sandstorm\UserManagement\Domain\Model\User;
1011
use Neos\Flow\Annotations as Flow;
1112
use Neos\Flow\Persistence\Repository;
1213

1314
/**
1415
* @Flow\Scope("singleton")
1516
* @method User findOneByEmail(string $email)
17+
* @method User findOneByAccount(Account $account)
1618
*/
1719
class UserRepository extends Repository
1820
{

Configuration/NodeTypes.Profile.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
##
2+
# A simple "Login form" plugin that demonstrates "Frontend authorization"
3+
#
4+
'Sandstorm.UserManagement:Profile':
5+
superTypes:
6+
'Neos.Neos:Plugin': TRUE
7+
ui:
8+
label: i18n
9+
icon: 'icon-user'
10+
inspector:
11+
groups:
12+
pluginSettings:
13+
label: i18n
14+
properties:
15+
showPersonalInformation:
16+
type: boolean
17+
defaultValue: TRUE
18+
ui:
19+
label: i18n
20+
inspector:
21+
group: pluginSettings
22+
showAccountInformation:
23+
type: boolean
24+
defaultValue: TRUE
25+
ui:
26+
label: i18n
27+
inspector:
28+
group: pluginSettings
29+
enableNewPassword:
30+
type: boolean
31+
defaultValue: TRUE
32+
ui:
33+
label: i18n
34+
inspector:
35+
group: pluginSettings

Configuration/Policy.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ privilegeTargets:
1010
matcher: 'method(Neos\Flow\Security\Authentication\Controller\AbstractAuthenticationController->logoutAction())'
1111
'Sandstorm.UserManagement:Registration':
1212
matcher: 'method(Sandstorm\UserManagement\Controller\RegistrationController->(?!initialize).*Action())'
13+
'Sandstorm.UserManagement:Profile':
14+
matcher: 'method(Sandstorm\UserManagement\Controller\ProfileController->(?!initialize).*Action())'
1315

1416
roles:
1517
'Neos.Flow:Everybody':
@@ -23,3 +25,14 @@ roles:
2325
-
2426
privilegeTarget: 'Sandstorm.UserManagement:Logout'
2527
permission: GRANT
28+
'Neos.Neos:FrontendUser':
29+
privileges:
30+
-
31+
privilegeTarget: 'Sandstorm.UserManagement:Profile'
32+
permission: GRANT
33+
'Neos.Neos:Editor':
34+
privileges:
35+
-
36+
privilegeTarget: 'Sandstorm.UserManagement:Profile'
37+
permission: GRANT
38+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
prototype(Sandstorm.UserManagement:Profile) < prototype(Neos.Neos:Plugin) {
2+
package = 'Sandstorm.UserManagement'
3+
controller = 'Profile'
4+
action = 'index'
5+
showPersonalInformation = ${q(node).property('showPersonalInformation')}
6+
showAccountInformation = ${q(node).property('showAccountInformation')}
7+
enableNewPassword = ${q(node).property('enableNewPassword')}
8+
}

Resources/Private/Layouts/Default.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
</head>
1919
<body>
20-
<f:flashMessages class="flashmessages"/>
20+
<!--<f:flashMessages class="flashmessages"/>-->
2121
<f:render section="Content"/>
2222
</body>
2323
</html>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html xmlns:f="http://typo3.org/ns/TYPO3/Fluid/ViewHelpers"
3+
xmlns="http://www.w3.org/1999/xhtml"
4+
lang="en">
5+
6+
<f:section name="DataTable">
7+
<table>
8+
<tr>
9+
<td><f:translate id="accountData.email" package="Sandstorm.UserManagement" source="Partials/Profile/AccountData"/></td>
10+
<td>{account.accountIdentifier}</td>
11+
</tr>
12+
<tr>
13+
<td><f:translate id="accountData.roles" package="Sandstorm.UserManagement" source="Partials/Profile/AccountData"/></td>
14+
<td>
15+
<f:for each="{account.roles}" as="role">{role.name}</f:for>
16+
</td>
17+
</tr>
18+
<tr>
19+
<td><f:translate id="accountData.createdOn" package="Sandstorm.UserManagement" source="Partials/Profile/AccountData"/></td>
20+
<td>
21+
<f:format.date format='<f:translate id="accountData.dateFormat" package="Sandstorm.UserManagement" source="Partials/Profile/AccountData"/>'>{account.creationDate.date}</f:format.date>
22+
</td>
23+
</tr>
24+
</table>
25+
</f:section>
26+
27+
</html>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!DOCTYPE html>
2+
<html xmlns:f="http://typo3.org/ns/TYPO3/Fluid/ViewHelpers"
3+
xmlns="http://www.w3.org/1999/xhtml"
4+
lang="en">
5+
6+
<f:section name="NewPassword">
7+
<fieldset>
8+
<label for="password[0]">
9+
<f:translate id="passwordForm.newPassword" package="Sandstorm.UserManagement" source="Partials/Profile/PasswordForm"/>:
10+
</label>
11+
<f:form.password name="password[0]" id="password[0]" class="{f:validation.ifHasErrors(for: 'password', then: ' form-error')}"/>
12+
<label for="password[1]">
13+
<f:translate id="passwordForm.confirmNewPassword" package="Sandstorm.UserManagement" source="Partials/Profile/PasswordForm"/>:
14+
</label>
15+
<f:form.password name="password[1]" id="password[1]" class="{f:validation.ifHasErrors(for: 'password', then: ' form-error')}" />
16+
<f:render partial="FormErrors" section="ValidationResults" arguments="{for: 'password'}"/>
17+
<button class="button large primary"><f:translate id="passwordForm.changePassword" package="Sandstorm.UserManagement" source="Partials/Profile/PasswordForm"/></button>
18+
</fieldset>
19+
</f:section>
20+
21+
</html>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<!DOCTYPE html>
2+
<html xmlns:f="http://typo3.org/ns/TYPO3/Fluid/ViewHelpers"
3+
xmlns="http://www.w3.org/1999/xhtml"
4+
lang="en">
5+
6+
<f:section name="PersonalForm">
7+
<fieldset>
8+
<label for="profile-firstname" class="{f:validation.ifHasErrors(for: 'password', then: ' form-error')}">
9+
<f:translate id="personalForm.firstName" package="Sandstorm.UserManagement" source="Partials/Profile/PersonalForm"/>:
10+
</label>
11+
<f:form.textfield property="firstName"
12+
name="firstName"
13+
value="{user.firstName}"
14+
id="profile-firstname"
15+
placeholder="{f:translate(id:'personalForm.firstName',package:'Sandstorm.UserManagement',source:'Partials/Profile/PersonalForm')}" />
16+
<label for="profile-lastname">
17+
<f:translate id="personalForm.lastName" package="Sandstorm.UserManagement" source="Partials/Profile/PersonalForm"/>:
18+
</label>
19+
<f:form.textfield property="lastName"
20+
name="lastName"
21+
value="{user.lastName}"
22+
id="profile-lastname"
23+
placeholder="{f:translate(id:'personalForm.lastName',package:'Sandstorm.UserManagement',source:'Partials/Profile/PersonalForm')}" />
24+
25+
<f:render partial="FormErrors" section="ValidationResults" arguments="{for: 'user'}"/>
26+
27+
<button class="button large primary">
28+
<f:translate id="personalForm.changeData" package="Sandstorm.UserManagement" source="Partials/Profile/PersonalForm"/>
29+
</button>
30+
</fieldset>
31+
</f:section>
32+
33+
</html>

Resources/Private/Templates/Login/Login.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,4 @@
2626
</f:else>
2727
</usermanagement:ifAuthenticated>
2828
</f:section>
29-
3029
</html>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<!DOCTYPE html>
2+
3+
<html xmlns:f="http://typo3.org/ns/TYPO3/Fluid/ViewHelpers"
4+
xmlns:usermanagement="http://typo3.org/ns/Sandstorm/UserManagement/ViewHelpers"
5+
xmlns:neos="http://typo3.org/ns/Neos/Neos/ViewHelpers"
6+
xmlns="http://www.w3.org/1999/xhtml"
7+
lang="en">
8+
<f:layout name="Default"/>
9+
10+
<f:section name="Title">Profile Settings</f:section>
11+
12+
<f:section name="Content">
13+
<h2><f:translate id="profile.title" package="Sandstorm.UserManagement" source="Templates/Partials/Profile"/></h2>
14+
<f:if condition="{pluginArguments.__showPersonalInformation}">
15+
<f:render section="Personal" />
16+
</f:if>
17+
<f:if condition="{pluginArguments.__showAccountInformation}">
18+
<f:render section="Account" />
19+
</f:if>
20+
<f:if condition="{pluginArguments.__enableNewPassword}">
21+
<f:render section="Password" />
22+
</f:if>
23+
</f:section>
24+
<f:section name="Personal">
25+
<h4><f:translate id="profile.personal" package="Sandstorm.UserManagement" source="Templates/Partials/Profile"/></h4>
26+
<usermanagement:ifAuthenticated authenticationProviderName="Sandstorm.UserManagement:Login">
27+
<f:then>
28+
<f:form action="editProfile" method="post" object="{user}" objectName="user">
29+
<f:render partial="Profile/PersonalForm" section="PersonalForm" arguments="{_all}"/>
30+
</f:form>
31+
</f:then>
32+
<f:else>
33+
<f:render partial="Profile/PersonalForm" section="PersonalForm" arguments="{_all}"/>
34+
</f:else>
35+
</usermanagement:ifAuthenticated>
36+
</f:section>
37+
<f:section name="Account">
38+
<h4><f:translate id="profile.account" package="Sandstorm.UserManagement" source="Templates/Partials/Profile"/></h4>
39+
<f:render partial="Profile/AccountData" section="DataTable" arguments="{_all}"/>
40+
</f:section>
41+
<f:section name="Password">
42+
<h4><f:translate id="profile.password" package="Sandstorm.UserManagement" source="Templates/Partials/Profile"/></h4>
43+
<usermanagement:ifAuthenticated authenticationProviderName="Sandstorm.UserManagement:Login">
44+
<f:then>
45+
<f:form action="setNewPassword" object="{account}" objectName="account">
46+
<f:render partial="Profile/PasswordForm" section="NewPassword" arguments="{_all}"/>
47+
</f:form>
48+
</f:then>
49+
<f:else>
50+
<f:render partial="Profile/PasswordForm" section="NewPassword" arguments="{_all}"/>
51+
</f:else>
52+
</usermanagement:ifAuthenticated>
53+
</f:section>
54+
</html>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
3+
<file original="" product-name="Sandstorm.UserManagement" source-language="en" datatype="plaintext">
4+
<body>
5+
<trans-unit id="ui.label" xml:space="preserve">
6+
<source>User Profile</source>
7+
</trans-unit>
8+
<trans-unit id="groups.pluginSettings" xml:space="preserve">
9+
<source>User Profile Settings</source>
10+
</trans-unit>
11+
<trans-unit id="properties.showPersonalInformation" xml:space="preserve">
12+
<source>Show Personal Information</source>
13+
</trans-unit>
14+
<trans-unit id="properties.showAccountInformation" xml:space="preserve">
15+
<source>Show Account Information</source>
16+
</trans-unit>
17+
<trans-unit id="properties.enableNewPassword" xml:space="preserve">
18+
<source>Enable Setting of a new Password</source>
19+
</trans-unit>
20+
</body>
21+
</file>
22+
</xliff>

0 commit comments

Comments
 (0)