Skip to content

Commit

Permalink
Add proper support for chosing a parent group and also for adding use…
Browse files Browse the repository at this point in the history
…rs to publishers
  • Loading branch information
rossjones committed Mar 6, 2012
1 parent 5bb1b18 commit 0db27b1
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 41 deletions.
33 changes: 18 additions & 15 deletions ckan/logic/auth/publisher/create.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from ckan.logic.auth import get_package_object, get_group_object, \
get_user_object, get_resource_object
from ckan.logic.auth.publisher import _groups_intersect
from ckan.logic.auth.publisher import _groups_intersect
from ckan.logic import NotFound
from ckan.authz import Authorizer
from ckan.lib.base import _
Expand All @@ -13,37 +13,37 @@ def package_create(context, data_dict=None):
model = context['model']
user = context['user']
userobj = model.User.get( user )

if userobj:
return {'success': True}

return {'success': False, 'msg': 'You must be logged in to create a package'}

def resource_create(context, data_dict):
return {'success': False, 'msg': 'Not implemented yet in the auth refactor'}

def package_relationship_create(context, data_dict):
"""
Permission for users to create a new package relationship requires that the
Permission for users to create a new package relationship requires that the
user share a group with both packages.
"""
model = context['model']
user = context['user']

id = data_dict.get('id', '')
id2 = data_dict.get('id2', '')

pkg1 = model.Package.get(id)
pkg2 = model.Package.get(id2)

if not pkg1 or not pkg2:
return {'success': False, 'msg': _('Two package IDs are required')}
return {'success': False, 'msg': _('Two package IDs are required')}

pkg1grps = pkg1.get_groups('publisher')
pkg2grps = pkg2.get_groups('publisher')

usergrps = model.User.get( user ).get_groups('publisher')
authorized = _groups_intersect( usergrps, pkg1grps ) and _groups_intersect( usergrps, pkg2grps )
authorized = _groups_intersect( usergrps, pkg1grps ) and _groups_intersect( usergrps, pkg2grps )
if not authorized:
return {'success': False, 'msg': _('User %s not authorized to edit these packages') % str(user)}
else:
Expand All @@ -52,26 +52,29 @@ def package_relationship_create(context, data_dict):
def group_create(context, data_dict=None):
"""
Group create permission. If a group is provided, within which we want to create a group
then we check that the user is within that group. If not then we just say Yes for now
then we check that the user is within that group. If not then we just say Yes for now
although there may be some approval issues elsewhere.
"""
model = context['model']
user = context['user']

if not user:
return {'success': False, 'msg': _('User is not authorized to create groups') }

return {'success': False, 'msg': _('User is not authorized to create groups') }

if Authorizer.is_sysadmin(user):
return {'success': True}

try:
# If the user is doing this within another group then we need to make sure that
# the user has permissions for this group.
group = get_group_object( context )
except NotFound:
return { 'success' : True }

userobj = model.User.get( user )
if not userobj:
return {'success': False, 'msg': _('User %s not authorized to create groups') % str(user)}
return {'success': False, 'msg': _('User %s not authorized to create groups') % str(user)}

authorized = _groups_intersect( userobj.get_groups('publisher'), [group] )
if not authorized:
return {'success': False, 'msg': _('User %s not authorized to create groups') % str(user)}
Expand Down
76 changes: 50 additions & 26 deletions ckanext/publisher_form/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os, logging
from ckan.authz import Authorizer
from ckan.logic import check_access
import ckan.logic.action.create as create
import ckan.logic.action.update as update
import ckan.logic.action.get as get
Expand Down Expand Up @@ -31,13 +32,13 @@

class PublisherForm(SingletonPlugin):
"""
This plugin implements an IGroupForm for form associated with a
This plugin implements an IGroupForm for form associated with a
publisher group. ``IConfigurer`` is used to add the local template
path and the IGroupForm supplies the custom form.
"""
implements(IGroupForm, inherit=True)
implements(IConfigurer, inherit=True)
implements(IConfigurer, inherit=True)

def update_config(self, config):
"""
This IConfigurer implementation causes CKAN to look in the
Expand All @@ -49,12 +50,12 @@ def update_config(self, config):
'publisher_form', 'templates')
config['extra_template_paths'] = ','.join([template_dir,
config.get('extra_template_paths', '')])

def group_form(self):
"""
Returns a string representing the location of the template to be
rendered. e.g. "forms/group_form.html".
"""
"""
return 'publisher_form.html'

def group_types(self):
Expand All @@ -75,11 +76,11 @@ def is_fallback(self):
Returns true iff this provides the fallback behaviour, when no other
plugin instance matches a group's type.
As this is not the fallback controller we should return False. If
As this is not the fallback controller we should return False. If
we were wanting to act as the fallback, we'd return True
"""
return False
return False

def form_to_db_schema(self):
"""
Returns the schema for mapping group data from a form to a format
Expand All @@ -93,7 +94,7 @@ def db_to_form_schema(self):
format suitable for the form (optional)
"""
return {}

def check_data_dict(self, data_dict):
"""
Check if the return data is correct.
Expand All @@ -104,22 +105,46 @@ def check_data_dict(self, data_dict):
def setup_template_variables(self, context, data_dict):
"""
Add variables to c just prior to the template being rendered. We should
use the available groups for the current user, but should be optional
use the available groups for the current user, but should be optional
in case this is a top level group
"""
#c.user_groups = c.userobj.get_groups('publisher')
c.user_groups = ['One', 'Two', 'Three']


"""
c.user_groups = c.userobj.get_groups('publisher')
local_ctx = {'model': model, 'session': model.Session,
'user': c.user or c.author}

try:
check_access('group_create', local_ctx)
c.is_superuser_or_groupadmin = True
except NotAuthorized:
c.is_superuser_or_groupadmin = False

if 'group' in context:
group = context['group']
possible_parents = model.Session.query(model.Group).\
filter(model.Group.state == 'active').\
filter(model.Group.type == 'publisher').\
filter(model.Group.id != group.id ).order_by(model.Group.title).all()

# Only show possible groups where the current user is a member
user_groups = c.userobj.get_groups('publisher')
c.possible_parents =[p for p in possible_parents if p in user_groups]

c.parent = None
grps = group.get_groups('publisher')
if grps:
c.parent = grps[0]
c.users = group.members_of_type(model.User)


class PublisherDatasetForm(SingletonPlugin):
"""
This plugin implements a new publisher form for cases where we
This plugin implements a new publisher form for cases where we
want to enforce group (type=publisher) membership on a dataset.
"""
implements(IDatasetForm, inherit=True)
implements(IConfigurer, inherit=True)
implements(IConfigurer, inherit=True)

def update_config(self, config):
"""
This IConfigurer implementation causes CKAN to look in the
Expand All @@ -131,20 +156,20 @@ def update_config(self, config):
'publisher_form', 'templates')
config['extra_template_paths'] = ','.join([template_dir,
config.get('extra_template_paths', '')])

def package_form(self):
"""
Returns a string representing the location of the template to be
rendered. e.g. "package/new_package_form.html".
"""
"""
return 'dataset_form.html'

def is_fallback(self):
"""
Returns true iff this provides the fallback behaviour, when no other
plugin instance matches a package's type.
As this is not the fallback controller we should return False. If
As this is not the fallback controller we should return False. If
we were wanting to act as the fallback, we'd return True
"""
return True
Expand All @@ -166,14 +191,14 @@ def setup_template_variables(self, context, data_dict=None):
"""
Adds variables to c just prior to the template being rendered that can
then be used within the form
"""
"""
c.licences = [('', '')] + model.Package.get_license_options()
c.publishers = [('Example publisher', 'Example publisher 2')]
c.is_sysadmin = Authorizer().is_sysadmin(c.user)
c.resource_columns = model.Resource.get_columns()
c.groups_available = c.userobj.get_groups('publisher') if c.userobj else []


## This is messy as auths take domain object not data_dict
pkg = context.get('package') or c.pkg
if pkg:
Expand All @@ -186,7 +211,7 @@ def form_to_db_schema(self):
suitable for the database.
"""
return package_form_schema()

def db_to_form_schema(data):
"""
Returns the schema for mapping package data from the database into a
Expand All @@ -200,4 +225,3 @@ def check_data_dict(self, data_dict):
"""
pass


22 changes: 22 additions & 0 deletions ckanext/publisher_form/templates/publisher_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ <h2>Errors in form</h2>
<span class="hints">You can use <a href="http://daringfireball.net/projects/markdown/syntax" target="_blank">Markdown formatting</a> here.</span>
</div></dd>

<dt class="parent-label" py:if="c.is_superuser_or_groupadmin">
<label class="field_opt" for="parent">Parent publisher</label>
</dt>

<dd py:if="c.group and not c.is_superuser_or_groupadmin">
<span py:if="c.parent is not None" class="js-title">
${ c.parent.title }
</span>
<span py:if="c.parent is None" class="js-title">
No parent publisher
</span>
</dd>

<dd py:if="c.is_superuser_or_groupadmin" class="parent-field">
<select id="parent" name="parent" class="chzn-select" data-placeholder="Please choose a publisher">
<option value=""></option>
<py:for each="pg in c.possible_parents">
<option py:attrs="{'selected': 'selected' if c.parent and pg.id == c.parent.id else None}" value="${pg.id}">${pg.title}</option>
</py:for>
</select>
</dd>


<dt class="state-label" py:if="c.is_sysadmin or c.auth_for_change_state"><label class="field_opt" for="state">State</label></dt>
<dd class="state-field" py:if="c.is_sysadmin or c.auth_for_change_state">
Expand Down

0 comments on commit 0db27b1

Please sign in to comment.