0001-manager-add-help-on-users-imports.patch
src/authentic2/attribute_kinds.py | ||
---|---|---|
244 | 244 |
}, |
245 | 245 |
'html_value': profile_image_html_value, |
246 | 246 |
'attributes_ng_serialize': profile_attributes_ng_serialize, |
247 |
'csv_importable': False, |
|
247 | 248 |
}, |
248 | 249 |
] |
249 | 250 |
src/authentic2/manager/static/authentic2/manager/css/style.css | ||
---|---|---|
52 | 52 |
.email, #user-table .first_name, #user-table .last_name, #user-table .ou { |
53 | 53 |
text-align: left; |
54 | 54 |
} |
55 |
table.main.left { |
|
56 |
padding-left: 1rem; |
|
57 |
} |
|
58 |
table.main.left td, |
|
59 |
table.main.left th { |
|
60 |
text-align: left; |
|
61 |
} |
|
62 | ||
55 | 63 |
table.feeds td.url { |
56 | 64 |
text-align: left; |
57 | 65 |
padding-left: 1em; |
src/authentic2/manager/templates/authentic2/manager/user_imports.html | ||
---|---|---|
21 | 21 |
{% endblock %} |
22 | 22 | |
23 | 23 |
{% block content %} |
24 |
<h3>{% trans "Imports" %}</h3> |
|
25 |
<table class="main"> |
|
26 |
<thead> |
|
27 |
<tr> |
|
28 |
<td>{% trans "Filename" %}</td> |
|
29 |
<td>{% trans "Creation date" %}</td> |
|
30 |
<td>{% trans "By" %}</td> |
|
31 |
<td>{% trans "Rows" %}</td> |
|
32 |
<td></td> |
|
33 |
</tr> |
|
34 |
</thead> |
|
35 |
<tbody> |
|
36 |
{% for import in imports %} |
|
37 |
<tr> |
|
38 |
<td><a href="{% url "a2-manager-users-import" uuid=import.uuid %}">{{ import.filename }}</a></td> |
|
39 |
<td>{{ import.created }}</td> |
|
40 |
<td>{{ import.user }}</td> |
|
41 |
<td>{{ import.rows_count }}</td> |
|
42 |
<td><form method="post">{% csrf_token %}<button name="delete" value="{{ import.uuid }}">{% trans "Delete" %}</button></form></td> |
|
43 |
</tr> |
|
44 |
{% endfor %} |
|
45 |
</tbody> |
|
46 |
</table> |
|
24 | ||
25 |
<div class="section"> |
|
26 |
<h3>{% trans "Imports" %}</h3> |
|
27 |
<table class="main left"> |
|
28 |
<thead> |
|
29 |
<tr> |
|
30 |
<th>{% trans "Filename" %}</th> |
|
31 |
<th>{% trans "Creation date" %}</th> |
|
32 |
<th>{% trans "By" %}</th> |
|
33 |
<th>{% trans "Rows" %}</th> |
|
34 |
<th></th> |
|
35 |
</tr> |
|
36 |
</thead> |
|
37 |
<tbody> |
|
38 |
{% for import in imports %} |
|
39 |
<tr> |
|
40 |
<td><a href="{% url "a2-manager-users-import" uuid=import.uuid %}">{{ import.filename }}</a></td> |
|
41 |
<td>{{ import.created }}</td> |
|
42 |
<td>{{ import.user }}</td> |
|
43 |
<td>{{ import.rows_count }}</td> |
|
44 |
<td><form method="post">{% csrf_token %}<button name="delete" value="{{ import.uuid }}">{% trans "Delete" %}</button></form></td> |
|
45 |
</tr> |
|
46 |
{% endfor %} |
|
47 |
</tbody> |
|
48 |
</table> |
|
49 |
</div> |
|
50 | ||
51 |
<div class="section"> |
|
52 |
<h3>{% trans "Help" %}</h3> |
|
53 |
<p> |
|
54 |
{% blocktrans trimmed %} |
|
55 |
You can use the following columns in your CSV import file. |
|
56 |
{% endblocktrans %} |
|
57 |
<p> |
|
58 |
<h4>{% trans "Columns" %}</h4> |
|
59 |
<table class="main left"> |
|
60 |
<thead> |
|
61 |
<tr> |
|
62 |
<th>{% trans "Label" %}</th> |
|
63 |
<th>{% trans "Identifier" %}</th> |
|
64 |
</tr> |
|
65 |
</thead> |
|
66 |
<tbody> |
|
67 |
{% for column in help_columns %} |
|
68 |
<tr> |
|
69 |
<td>{{ column.label }}</td> |
|
70 |
<td>{{ column.name }}</td> |
|
71 |
</tr> |
|
72 |
{% endfor %} |
|
73 |
</tbody> |
|
74 |
</table> |
|
75 |
<h4>{% trans "Flags" %}</h4> |
|
76 |
<p>{% blocktrans trimmed %}Each column can receive flags after its name, separated by spaces. Each modifier can be prefixed by <tt>no-</tt> to set its value to false.{% endblocktrans %}</p> |
|
77 |
<table class="main left"> |
|
78 |
<thead> |
|
79 |
<tr> |
|
80 |
<th>{% trans "Flag" %}</th> |
|
81 |
<th>{% trans "Meaning" %}</th> |
|
82 |
<th>{% trans "Default" %}</th> |
|
83 |
</tr> |
|
84 |
</thead> |
|
85 |
<tbody> |
|
86 |
<tr> |
|
87 |
<td>key</td> |
|
88 |
<td> |
|
89 |
{% blocktrans trimmed %} |
|
90 |
The column is an import key, it is used to match the row with an existing user. Only one column can be an import key. |
|
91 |
{% endblocktrans %} |
|
92 |
</td> |
|
93 |
<td>{% trans "False" %}</td> |
|
94 |
</tr> |
|
95 |
<tr> |
|
96 |
<td>create</td> |
|
97 |
<td> |
|
98 |
{% blocktrans trimmed %} |
|
99 |
Values will be used when creating a new user. |
|
100 |
{% endblocktrans %} |
|
101 |
</td> |
|
102 |
<td>{% trans "True" %}</td> |
|
103 |
</tr> |
|
104 |
<tr> |
|
105 |
<td>update</td> |
|
106 |
<td> |
|
107 |
{% blocktrans trimmed %} |
|
108 |
Values will be used when updating an existing user. |
|
109 |
{% endblocktrans %} |
|
110 |
</td> |
|
111 |
<td>{% trans "True" %}</td> |
|
112 |
</tr> |
|
113 |
<tr> |
|
114 |
<td>unique</td> |
|
115 |
<td> |
|
116 |
{% blocktrans trimmed %} |
|
117 |
Values must be unique in the target organizational unit. |
|
118 |
{% endblocktrans %} |
|
119 |
</td> |
|
120 |
<td>{% trans "True" %}</td> |
|
121 |
</tr> |
|
122 |
<tr> |
|
123 |
<td>globally-unique</td> |
|
124 |
<td> |
|
125 |
{% blocktrans trimmed %} |
|
126 |
Values must be unique among all users. |
|
127 |
{% endblocktrans %} |
|
128 |
</td> |
|
129 |
<td>{% trans "True" %}</td> |
|
130 |
</tr> |
|
131 |
<tr> |
|
132 |
<td>verified</td> |
|
133 |
<td> |
|
134 |
{% blocktrans trimmed %} |
|
135 |
Values are verified. |
|
136 |
{% endblocktrans %} |
|
137 |
</td> |
|
138 |
<td>{% trans "False" %} {% blocktrans %}(default is True for the <tt>email</tt> column){% endblocktrans %}</td> |
|
139 |
</tr> |
|
140 |
</tbody> |
|
141 |
</table> |
|
142 | ||
143 |
<h4>{% trans "External identifier" %}</h4> |
|
144 |
<p> |
|
145 |
{% blocktrans trimmed %} |
|
146 |
You can also use two special columns <tt>_source_name</tt> and |
|
147 |
<tt>_source_id</tt>. <tt>_source_name</tt> must be the name of the |
|
148 |
source directory from which the users are exported, it must not |
|
149 |
change between imports. <tt>_source_id</tt> is the unique identifier |
|
150 |
from the source directory from which the users are extracted, it must |
|
151 |
not change between imports and should never be reused for different |
|
152 |
users. <tt>_source_id</tt> is automatically the key column, and you |
|
153 |
cannot use another key column. |
|
154 |
{% endblocktrans %} |
|
155 |
</p> |
|
156 |
</div> |
|
157 | ||
47 | 158 |
{% endblock %} |
src/authentic2/manager/user_views.py | ||
---|---|---|
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 |
import base64 |
|
17 | 18 |
import datetime |
18 | 19 |
import collections |
19 | 20 |
import operator |
... | ... | |
52 | 53 |
from .utils import get_ou_count, has_show_username |
53 | 54 |
from . import app_settings |
54 | 55 | |
56 |
User = get_user_model() |
|
57 | ||
55 | 58 | |
56 | 59 |
class UsersView(HideOUColumnMixin, BaseTableView): |
57 | 60 |
template_name = 'authentic2/manager/users.html' |
... | ... | |
659 | 662 | |
660 | 663 |
ctx = super(UserImportsView, self).get_context_data(**kwargs) |
661 | 664 |
ctx['imports'] = sorted(user_import.UserImport.all(), key=operator.attrgetter('created'), reverse=True) |
665 |
help_columns = [] |
|
666 |
field_columns = ['username', 'email', 'first_name', 'last_name'] |
|
667 |
if not has_show_username: |
|
668 |
field_columns.remove('username') |
|
669 |
for field_column in field_columns: |
|
670 |
field = User._meta.get_field(field_column) |
|
671 |
help_columns.append({ |
|
672 |
'label': field.verbose_name, |
|
673 |
'name': field.name |
|
674 |
}) |
|
675 |
for attribute in Attribute.objects.all(): |
|
676 |
kind = attribute.get_kind() |
|
677 |
if not kind.get('csv_importable', True): |
|
678 |
continue |
|
679 |
help_columns.append({ |
|
680 |
'label': attribute.label, |
|
681 |
'name': attribute.name, |
|
682 |
}) |
|
683 |
ctx['help_columns'] = help_columns |
|
684 |
example_data = u','.join(column['name'] for column in help_columns) + '\n' |
|
685 |
example_url = 'data:text/csv;base64,%s' % base64.b64encode(example_data.encode('utf-8')) |
|
686 |
ctx['form'].fields['import_file'].help_text = format_html( |
|
687 |
_('{0}. {1} <a download="{3}" href="{2}">{3}</a>'), |
|
688 |
ctx['form'].fields['import_file'].help_text, |
|
689 |
_('ex.:'), |
|
690 |
example_url, |
|
691 |
_('users.csv')) |
|
662 | 692 |
return ctx |
663 | 693 | |
664 | 694 |
user_imports = UserImportsView.as_view() |
665 |
- |