Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var/
/venv/
.installed.txt
.lock
.mxdev_cache

##
# Add extra configuration options in .meta.toml:
Expand Down
9 changes: 8 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
## 1.3.2 (unreleased)
## 1.4.0 (unreleased)

- Upgrade dev environment to Plone 6.1.3
[remdub]

- Override views related to user management
We no longer create or modify users in Plone
This is now handled by Keycloak
[remdub]

- Remove deprecated methods related to redirect uris
We are not using those methods anymore since 1.3.0
Expand Down
2 changes: 1 addition & 1 deletion constraints.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
-c https://dist.plone.org/release/6.1.1/constraints.txt
-c https://dist.plone.org/release/6.1.3/constraints.txt
4 changes: 4 additions & 0 deletions mx.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ main-package = -e .[test]
; pushurl = git@github.com:collective/example.contenttype.git
; extras = test
; branch = feature-7
[pas.plugins.oidc]
url = https://github.com/collective/pas.plugins.oidc.git
pushurl = git@github.com:collective/pas.plugins.oidc.git
branch = main
32 changes: 32 additions & 0 deletions src/pas/plugins/kimug/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,37 @@
layer="pas.plugins.kimug.interfaces.IBrowserLayer"
/>

<browser:page
name="new-user"
for="plone.base.interfaces.INavigationRoot"
class=".view.NewUserView"
permission="plone.app.controlpanel.UsersAndGroups"
layer="pas.plugins.kimug.interfaces.IBrowserLayer"
/>

<browser:page
name="usergroup-userprefs"
for="plone.base.interfaces.IPloneSiteRoot"
class="Products.CMFPlone.controlpanel.browser.usergroups_usersoverview.UsersOverviewControlPanel"
template="usergroups_usersoverview.pt"
permission="plone.app.controlpanel.UsersAndGroups"
layer="pas.plugins.kimug.interfaces.IBrowserLayer"
/>

<browser:page
name="personal-information"
for="plone.base.interfaces.INavigationRoot"
class=".view.PersonalInformationView"
permission="cmf.SetOwnProperties"
layer="pas.plugins.kimug.interfaces.IBrowserLayer"
/>

<browser:page
name="change-password"
for="plone.base.interfaces.INavigationRoot"
class=".view.ChangePasswordView"
permission="cmf.SetOwnProperties"
layer="pas.plugins.kimug.interfaces.IBrowserLayer"
/>

</configure>
289 changes: 289 additions & 0 deletions src/pas/plugins/kimug/browser/usergroups_usersoverview.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:tal="http://xml.zope.org/namespaces/tal"
lang="en"
metal:use-macro="context/prefs_main_template/macros/master"
xml:lang="en"
i18n:domain="plone"
>

<body>

<metal:main fill-slot="prefs_configlet_main"
tal:define="
template_id string:@@usergroup-userprefs;
showAll python:request.get('showAll', '') and not view.newSearch and 'y';
Batch python:modules['Products.CMFPlone'].Batch;
b_start python:0 if showAll or view.newSearch else request.get('b_start',0);
b_size python:showAll and len(view.searchResults) or 20;
portal_roles view/portal_roles;
portal_url context/portal_url;
"
>

<tal:content>

<header>

<h1 class="documentFirstHeading"
i18n:translate=""
>Users</h1>

<div metal:use-macro="context/global_statusmessage/macros/portal_message">
Portal status message
</div>

<div class="text-muted mt-2"
i18n:translate="user_roles_note"
>
Note that roles set here apply directly to a user.
The symbol
<span i18n:name="image_link_icon"><tal:icon tal:replace="structure python:icons.tag('people', tag_alt='Inherited from Group')" /></span>
indicates a role inherited from membership in a group.
</div>
</header>

<div id="content-core">

<div class="autotabs">
<p class="alert alert-warn"
role="status"
tal:condition="view/show_users_listing_warning"
>
<strong i18n:translate="">Note</strong>
<span i18n:translate="description_pas_users_listing">Some or all of your PAS user source
plugins do not allow listing of users, so you may not see
the users defined by those plugins unless doing a specific
search.</span>
</p>

<form class="pat-formautofocus"
action=""
method="post"
name="users_search"
tal:define="
findAll python:'form.button.FindAll' in request.keys();
portal_users view/searchResults;
batch python:Batch(portal_users, b_size, int(b_start), orphan=1);
batchformkeys python:['searchstring','_authenticator'];
many_users view/many_users;
"
tal:attributes="
action string:$portal_url/$template_id;
"
>
<input name="form.submitted"
type="hidden"
value="1"
/>


<div class="mb-3 input-group">
<a class="me-3 btn btn-success"
id="add-user"
tal:attributes="
href string:${portal_url}/@@new-user;
"
i18n:translate="label_add_new_user"
>Add New User</a>
<span class="input-group-text"
id="quickSearchLabel"
i18n:translate="label_user_search"
>User Search</span>
<input class="form-control quickSearch"
id="quickSearch"
aria-labelledby="quickSearchLabel"
name="searchstring"
type="text"
value=""
tal:attributes="
value view/searchString;
"
/>
<button class="searchButton btn btn-primary"
name="form.button.Search"
type="submit"
value="Search"
i18n:attributes="value label_search;"
i18n:translate=""
>Search</button>

<button class="searchButton btn btn-secondary"
name="form.button.FindAll"
type="submit"
value="Show all"
tal:condition="not:many_users"
i18n:attributes="value label_showall;"
i18n:translate="label_showall"
>Show all</button>
</div>
<table class="table table-responsive table-bordered table-striped text-center"
summary="User Listing"
>
<thead tal:condition="portal_users">
<tr>
<th class="text-start"
i18n:translate="listingheader_user_name"
>User name</th>
<th class="rotate"
tal:repeat="portal_role portal_roles"
><div tal:content="portal_role"
i18n:translate=""
>Role</div></th>
</tr>
</thead>
<tbody>
<tal:loop repeat="user batch">
<tr tal:define="
oddrow repeat/user/odd;
userid user/userid;
userquery python:view.makeQuery(userid=userid);
"
tal:attributes="
class python:oddrow and 'odd' or 'even';
"
>

<td class="text-start">
<a href="@@user-i0nformation"
tal:attributes="
href string:$portal_url/@@user-information?${userquery};
title userid;
"
>
${user/fullname}
<span class="text-muted"
i18n:translate=""
>(${user/login})</span>
</a>
<input name="users.id:records"
type="hidden"
tal:attributes="
value userid;
"
/>
</td>

<td class="listingCheckbox"
tal:repeat="portal_role portal_roles"
>
<tal:block tal:define="
inherited python:user['roles'][portal_role]['inherited'];
explicit python:user['roles'][portal_role]['explicit'];
enabled python:user['roles'][portal_role]['canAssign'];
">
<input class="noborder"
name="users.roles:list:records"
type="checkbox"
value="Manager"
tal:condition="not:inherited"
tal:attributes="
value portal_role;
checked python:'checked' if explicit else nothing;
disabled python:default if enabled else 'disabled';
"
/>
<input name="users.roles:list:records"
type="hidden"
value="Manager"
tal:condition="python:inherited"
tal:attributes="
value portal_role;
"
/>
<tal:icon tal:condition="inherited"
tal:replace="structure python:icons.tag('people', tag_alt='Inherited from Group')"
/>

</tal:block>

</td>

</tr>
</tal:loop>
<tr tal:condition="not:batch">
<td style="text-align:center;"
tal:condition="view/searchString"
i18n:translate="text_nomatches"
>No matches</td>
<tal:block tal:condition="not:view/searchString">
<td class="discreet"
style="text-align:center; font-size: 100%;"
tal:condition="many_users"
i18n:translate="text_no_user_searchstring"
>
Enter a username to search for
</td>
<td class="discreet"
style="text-align:center; font-size: 100%;"
tal:condition="not:many_users"
i18n:translate="text_no_user_searchstring_largesite"
>
Enter a username to search for, or click 'Show All'
</td>
</tal:block>
</tr>
</tbody>
</table>

<div metal:use-macro="context/batch_macros/macros/navigation"></div>

<div class="showAllSearchResults"
tal:define="
mq python:modules['ZTUtils'].make_query;
keys batchformkeys|nothing;
linkparams python:keys and dict([(key, request.form[key]) for key in keys if key in request]) or request.form;
url batch_base_url | string:${context/absolute_url}/${template_id};
"
tal:condition="python:batch.next or batch.previous"
>
<a tal:attributes="
href python: '%s?%s' % (url, mq( linkparams, {'showAll':'y'} ));
"
i18n:translate="description_pas_show_all_search_results"
>
Show all search results
</a>
</div>

<input name="b_start"
type="hidden"
value="b_start"
tal:attributes="
value b_start;
"
/>

<input name="showAll"
type="hidden"
value=""
tal:attributes="
value showAll;
"
/>

<div tal:condition="batch">

<div class="btn-group">
<button class="btn btn-primary"
name="form.button.Modify"
type="submit"
value="Save"
i18n:translate="label_apply_changes"
>Apply changes</button>
</div>
</div>

<input tal:replace="structure context/@@authenticator/authenticator" />

</form>
</div>
</div>

</tal:content>

</metal:main>

</body>
</html>
22 changes: 22 additions & 0 deletions src/pas/plugins/kimug/browser/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,25 @@ def __call__(self):
self.request.response.redirect(return_url)
else:
raise Unauthorized()


class NewUserView(BrowserView):
def __call__(self):
url_to_redirect = self.context["acl_users"]["oidc"].getProperty("add_user_url")
self.request.response.redirect(url_to_redirect)


class PersonalInformationView(BrowserView):
def __call__(self):
url_to_redirect = self.context["acl_users"]["oidc"].getProperty(
"personal_information_url"
)
self.request.response.redirect(url_to_redirect)


class ChangePasswordView(BrowserView):
def __call__(self):
url_to_redirect = self.context["acl_users"]["oidc"].getProperty(
"change_password_url"
)
self.request.response.redirect(url_to_redirect)
Loading