Index: trunk/wmfmailadmin/wmfmailadmin.py |
— | — | @@ -5,7 +5,7 @@ |
6 | 6 | Written by Mark Bergsma <mark@wikimedia.org> |
7 | 7 | """ |
8 | 8 | |
9 | | -import sys |
| 9 | +import sys, os |
10 | 10 | |
11 | 11 | dbname = 'user.db' |
12 | 12 | conn = None |
— | — | @@ -22,7 +22,7 @@ |
23 | 23 | fieldmappings = { |
24 | 24 | # Option: ( fieldname, description, default ) |
25 | 25 | 'e': ('email', "E-mail address", None), |
26 | | - 'p': ('password', "Password", None), |
| 26 | + 'p': ('password', "Password", '-'), |
27 | 27 | 'r': ('realname', "Real name", None), |
28 | 28 | 'i': ('id', "Id", None), |
29 | 29 | 'q': ('quota', "Quota", 2**30/1024), |
— | — | @@ -33,6 +33,8 @@ |
34 | 34 | |
35 | 35 | updateables = ('password', 'quota', 'realname', 'active') |
36 | 36 | |
| 37 | +supported_hash_algorithms = ('{SHA1}') |
| 38 | + |
37 | 39 | def list_accounts(fields): |
38 | 40 | """ |
39 | 41 | List accounts in the database |
— | — | @@ -74,17 +76,20 @@ |
75 | 77 | |
76 | 78 | global conn, longmappings, updateables |
77 | 79 | |
78 | | - required_fields = ('email', 'password', 'realname') |
| 80 | + required_fields = ('email', 'realname') # password will be prompted for if needed |
79 | 81 | require_fields( (required_fields, ), fields) |
80 | 82 | |
81 | 83 | # Set default values for fields not given |
82 | | - value_fields = ['localpart', 'domain', 'password', 'realname'] |
| 84 | + value_fields = ['localpart', 'domain', 'realname'] |
83 | 85 | for fieldname in updateables: |
84 | 86 | default = longmappings[fieldname][2] |
85 | 87 | if fieldname not in fields and default is not None: |
86 | 88 | fields[fieldname] = default |
87 | 89 | value_fields.append(fieldname) |
88 | 90 | |
| 91 | + # Input password if needed |
| 92 | + password_input(fields) |
| 93 | + |
89 | 94 | # Construct list of fields that are either given, or should get default values |
90 | 95 | values_list = "(" + ", ".join(value_fields) + ") VALUES (:" + ", :".join(value_fields) + ")" |
91 | 96 | |
— | — | @@ -115,6 +120,9 @@ |
116 | 121 | |
117 | 122 | require_fields( (('id', ), ('email', )), fields) |
118 | 123 | require_fields( (('password', ), ('realname', ), ('quota', ), ('active', ), ), fields) |
| 124 | + |
| 125 | + # Input password if needed |
| 126 | + password_input(fields) |
119 | 127 | |
120 | 128 | # Build UPDATE clause from update arguments |
121 | 129 | update_clause = " AND ".join( |
— | — | @@ -151,6 +159,26 @@ |
152 | 160 | # TODO: syntax checking |
153 | 161 | return fields |
154 | 162 | |
| 163 | +def password_input(fields): |
| 164 | + """ |
| 165 | + Checks if the password argument on the commandline was "-", |
| 166 | + and prompts for a password if that is the case |
| 167 | + """ |
| 168 | + |
| 169 | + global supported_hash_algorithms |
| 170 | + |
| 171 | + if fields['password'] != '-': return |
| 172 | + |
| 173 | + # Simply outsource to dovecotpw |
| 174 | + pipe = os.popen('dovecotpw -s sha1', 'r') |
| 175 | + password = pipe.readline().rstrip('\n') |
| 176 | + rval = pipe.close() |
| 177 | + if rval is None and password.startswith(supported_hash_algorithms): |
| 178 | + fields['password'] = password |
| 179 | + else: |
| 180 | + raise Exception("Problem invoking dovecotpw") |
| 181 | + |
| 182 | + |
155 | 183 | def add_index(dct, fieldindex): |
156 | 184 | """ |
157 | 185 | Expects: a dict containing tuples |