Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit 35298a2

Browse files
committed
Merge branch 'master' into py3-general-support
2 parents 313f651 + fbab8f5 commit 35298a2

19 files changed

+1167
-105
lines changed

ckan/cli/cli.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
profile,
1313
asset,
1414
datastore,
15+
sysadmin,
1516
translation,
1617
dataset,
1718
views,
@@ -20,7 +21,8 @@
2021
tracking,
2122
minify,
2223
less,
23-
generate
24+
generate,
25+
user
2426
)
2527

2628
from ckan.config.middleware import make_app
@@ -53,6 +55,7 @@ def ckan(ctx, config, *args, **kwargs):
5355
ckan.add_command(db.db)
5456
ckan.add_command(datapusher.datapusher)
5557
ckan.add_command(search_index.search_index)
58+
ckan.add_command(sysadmin.sysadmin)
5659
ckan.add_command(asset.asset)
5760
ckan.add_command(datastore.datastore)
5861
ckan.add_command(translation.translation)
@@ -64,3 +67,4 @@ def ckan(ctx, config, *args, **kwargs):
6467
ckan.add_command(minify.minify)
6568
ckan.add_command(less.less)
6669
ckan.add_command(generate.generate)
70+
ckan.add_command(user.user)

ckan/cli/sysadmin.py

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# encoding: utf-8
2+
3+
import click
4+
from six import text_type
5+
6+
import ckan.model as model
7+
from ckan.cli import error_shout
8+
from ckan.lib.cli import user_add
9+
10+
11+
@click.group(
12+
short_help=u"Gives sysadmin rights to a named user.",
13+
invoke_without_command=True,
14+
)
15+
@click.pass_context
16+
def sysadmin(ctx):
17+
"""Gives sysadmin rights to a named user.
18+
19+
"""
20+
if ctx.invoked_subcommand is None:
21+
ctx.invoke(list_sysadmins)
22+
23+
24+
@sysadmin.command(name=u"list", help=u"List sysadmins.")
25+
def list_sysadmins():
26+
click.secho(u"Sysadmins:")
27+
sysadmins = model.Session.query(model.User).filter_by(
28+
sysadmin=True, state=u"active"
29+
)
30+
click.secho(u"count = %i" % sysadmins.count())
31+
for sysadmin in sysadmins:
32+
click.secho(
33+
u"%s name=%s email=%s id=%s"
34+
% (
35+
sysadmin.__class__.__name__,
36+
sysadmin.name,
37+
sysadmin.email,
38+
sysadmin.id,
39+
)
40+
)
41+
42+
43+
@sysadmin.command(help=u"Convert user into a sysadmin.")
44+
@click.argument(u"username")
45+
@click.argument(u"args", nargs=-1)
46+
def add(username, args):
47+
48+
user = model.User.by_name(text_type(username))
49+
if not user:
50+
click.secho(u'User "%s" not found' % username, fg=u"red")
51+
if click.confirm(
52+
u"Create new user: %s?" % username, default=True, abort=True
53+
):
54+
# TODO: once, cli.user is merged, invoke `user.add_user` instead
55+
user_add([username] + list(args))
56+
user = model.User.by_name(text_type(username))
57+
58+
user.sysadmin = True
59+
model.Session.add(user)
60+
model.repo.commit_and_remove()
61+
click.secho(u"Added %s as sysadmin" % username, fg=u"green")
62+
63+
64+
@sysadmin.command(help=u"Removes user from sysadmins.")
65+
@click.argument(u"username")
66+
def remove(username):
67+
user = model.User.by_name(text_type(username))
68+
if not user:
69+
return error_shout(u'Error: user "%s" not found!' % username)
70+
user.sysadmin = False
71+
model.repo.commit_and_remove()
72+
click.secho(u"Removed %s from sysadmins" % username, fg=u"green")

ckan/cli/user.py

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# encoding: utf-8
2+
3+
import logging
4+
import sys
5+
from pprint import pprint
6+
7+
import click
8+
from six import text_type
9+
10+
import ckan.logic as logic
11+
import ckan.plugins as plugin
12+
from ckan.cli import error_shout
13+
14+
log = logging.getLogger(__name__)
15+
16+
17+
@click.group(name=u'user', short_help=u'Manage user commands')
18+
@click.help_option(u'-h', u'--help')
19+
def user():
20+
pass
21+
22+
23+
@user.command(u'add', short_help=u'Add new user')
24+
@click.argument(u'username')
25+
@click.argument(u'args', nargs=-1)
26+
@click.pass_context
27+
def add_user(ctx, username, args):
28+
u'''Add new user if we use ckan sysadmin add
29+
or ckan user add
30+
'''
31+
# parse args into data_dict
32+
data_dict = {u'name': username}
33+
for arg in args:
34+
try:
35+
field, value = arg.split(u'=', 1)
36+
data_dict[field] = value
37+
except ValueError:
38+
raise ValueError(
39+
u'Could not parse arg: %r (expected "<option>=<value>)"' % arg
40+
)
41+
42+
# Required
43+
if u'email' not in data_dict:
44+
data_dict['email'] = click.prompt(u'Email address ').strip()
45+
46+
if u'password' not in data_dict:
47+
data_dict['password'] = click.prompt(u'Password ', hide_input=True,
48+
confirmation_prompt=True)
49+
50+
# Optional
51+
if u'fullname' in data_dict:
52+
data_dict['fullname'] = data_dict['fullname'].decode(
53+
sys.getfilesystemencoding()
54+
)
55+
56+
# pprint(u'Creating user: %r' % username)
57+
58+
try:
59+
import ckan.logic as logic
60+
import ckan.model as model
61+
site_user = logic.get_action(u'get_site_user')({
62+
u'model': model,
63+
u'ignore_auth': True},
64+
{}
65+
)
66+
context = {
67+
u'model': model,
68+
u'session': model.Session,
69+
u'ignore_auth': True,
70+
u'user': site_user['name'],
71+
}
72+
flask_app = ctx.obj.app.apps[u'flask_app']._wsgi_app
73+
with flask_app.test_request_context():
74+
user_dict = logic.get_action(u'user_create')(context, data_dict)
75+
click.secho(u"Successfully created user: %s" % user_dict['name'],
76+
fg=u'green', bold=True)
77+
except logic.ValidationError as e:
78+
error_shout(e)
79+
80+
81+
def get_user_str(user):
82+
user_str = u'name=%s' % user.name
83+
if user.name != user.display_name:
84+
user_str += u' display=%s' % user.display_name
85+
return user_str
86+
87+
88+
@user.command(u'list', short_help=u'List all users')
89+
def list_users():
90+
import ckan.model as model
91+
click.secho(u'Users:')
92+
users = model.Session.query(model.User).filter_by(state=u'active')
93+
click.secho(u'count = %i' % users.count())
94+
for user in users:
95+
click.secho(get_user_str(user))
96+
97+
98+
@user.command(u'remove', short_help=u'Remove user')
99+
@click.argument(u'username')
100+
@click.pass_context
101+
def remove_user(ctx, username):
102+
import ckan.model as model
103+
if not username:
104+
error_shout(u'Please specify the username to be removed')
105+
return
106+
107+
flask_app = ctx.obj.app.apps['flask_app']._wsgi_app
108+
site_user = logic.get_action(u'get_site_user')({u'ignore_auth': True}, {})
109+
context = {u'user': site_user[u'name']}
110+
with flask_app.test_request_context():
111+
plugin.toolkit.get_action(u'user_delete')(context, {u'id': username})
112+
click.secho(u'Deleted user: %s' % username, fg=u'green', bold=True)
113+
114+
115+
@user.command(u'show', short_help=u'Show user')
116+
@click.argument(u'username')
117+
def show_user(username):
118+
import ckan.model as model
119+
if not username:
120+
error_shout(u'Please specify the username for the user')
121+
return
122+
user = model.User.get(text_type(username))
123+
click.secho(u'User: %s' % user)
124+
125+
126+
@user.command(u'setpass', short_help=u'Set password for the user')
127+
@click.argument(u'username')
128+
def set_password(username):
129+
import ckan.model as model
130+
if not username:
131+
error_shout(u'Need name of the user.')
132+
return
133+
user = model.User.get(username)
134+
if not user:
135+
error_shout(u"User not found!")
136+
return
137+
click.secho(u'Editing user: %r' % user.name, fg=u'yellow')
138+
139+
password = click.prompt(u'Password', hide_input=True,
140+
confirmation_prompt=True)
141+
user.password = password
142+
model.repo.commit_and_remove()
143+
click.secho(u'Password updated!', fg=u'green', bold=True)

ckan/controllers/error.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
from paste.urlparser import PkgResourcesParser
66
from pylons import request
77
from pylons.controllers.util import forward
8-
from webhelpers.html.builder import literal
98

109
from ckan.common import c
1110
from ckan.lib.base import BaseController
1211
from ckan.lib.base import render
12+
from ckan.lib.helpers import literal
1313

1414

1515
class ErrorController(BaseController):

ckan/lib/base.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
render_template as flask_render_template,
1616
abort as flask_abort
1717
)
18-
import six
1918

2019
import ckan.lib.i18n as i18n
2120
import ckan.lib.render as render_
@@ -35,7 +34,6 @@
3534
from pylons.controllers import WSGIController
3635
from pylons.controllers.util import abort as _abort
3736
from pylons.templating import cached_template, pylons_globals
38-
from webhelpers.html import literal
3937
from ckan.common import response
4038

4139

@@ -98,7 +96,7 @@ def render_snippet(*template_names, **kw):
9896
output = (
9997
'\n<!-- Snippet %s start -->\n%s\n<!-- Snippet %s end -->'
10098
'\n' % (template_name, output, template_name))
101-
return literal(output)
99+
return h.literal(output)
102100
except TemplateNotFound as exc:
103101
if exc.name == template_name:
104102
# the specified template doesn't exist - try the next fallback

0 commit comments

Comments
 (0)