3 ### Administrative commands
5 ### (c) 2013 Mark Wooding
8 ###----- Licensing notice ---------------------------------------------------
10 ### This file is part of Chopwood: a password-changing service.
12 ### Chopwood is free software; you can redistribute it and/or modify
13 ### it under the terms of the GNU Affero General Public License as
14 ### published by the Free Software Foundation; either version 3 of the
15 ### License, or (at your option) any later version.
17 ### Chopwood is distributed in the hope that it will be useful,
18 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ### GNU Affero General Public License for more details.
22 ### You should have received a copy of the GNU Affero General Public
23 ### License along with Chopwood; if not, see
24 ### <http://www.gnu.org/licenses/>.
26 from __future__
import with_statement
31 import config
as CONF
; CFG
= CONF
.CFG
33 import operation
as OP
34 from output
import OUT
, PRINT
36 import subcommand
as SC
40 'listusers', ['admin'], 'List the existing users.',
41 opts
= [SC
.Opt('service', '-s', '--service',
42 'list users with SERVICE accounts',
43 argname
= 'SERVICE')],
44 oparams
= [SC
.Arg('pat')])
45 def cmd_listuser(service
= None, pat
= None):
46 CU
.format_list(CU
.list_users(service
, pat
),
47 [CU
.column('USER', "~={0.user}A", 3),
48 CU
.column('EMAIL', "~={0.email}:[---~;~={0.email}A~]")])
51 'adduser', ['admin'], 'Add a user to the master database.',
52 opts
= [SC
.Opt('email', '-e', '--email',
53 "email address for the new user",
55 params
= [SC
.Arg('user')])
56 def cmd_adduser(user
, email
= None):
58 CU
.check_user(user
, False)
59 D
.DB
.execute("INSERT INTO users (user, email) VALUES ($user, $email)",
60 user
= user
, email
= email
)
61 D
.DB
.execute("""INSERT INTO services (user, service)
62 VALUES ($user, $service)""",
63 user
= user
, service
= 'master')
66 'deluser', ['admin'], 'Remove USER from the master database.',
67 params
= [SC
.Arg('user')])
68 def cmd_deluser(user
, email
= None):
71 for service
, alias
in D
.DB
.execute(
72 "SELECT service, alias FROM services WHERE user = $user",
74 if service
== 'master': continue
76 svc
= S
.SERVICES
[service
]
78 OUT
.warn("User `%s' has account for unknown service `%s'" %
81 if svc
.manage_pwent_p
:
82 if alias
is None: alias
= user
84 D
.DB
.execute("DELETE FROM users WHERE user = $user", user
= user
)
87 'edituser', ['admin'], 'Modify a user record.',
88 opts
= [SC
.Opt('email', '-e', '--email',
89 "change USER's email address",
91 SC
.Opt('noemail', '-E', '--no-email',
92 "forget USER's email address"),
93 SC
.Opt('rename', '-r', '--rename',
95 argname
= 'NEW-NAME')],
96 params
= [SC
.Arg('user')])
97 def cmd_edituser(user
, email
= None, noemail
= False, rename
= None):
100 if rename
is not None: check_user(rename
, False)
101 CU
.edit_records('users', 'user = $user',
102 [('email', email
, noemail
),
103 ('user', rename
, False)],
107 'delsvc', ['admin'], "Remove all records for SERVICE.",
108 params
= [SC
.Arg('service')])
109 def cmd_delsvc(service
):
111 CU
.check_service(service
, must_config_p
= False, must_records_p
= True)
112 D
.DB
.execute("DELETE FROM services WHERE service = $service",
116 'editsvc', ['admin'], "Edit a given SERVICE.",
117 opts
= [SC
.Opt('rename', '-r', '--rename', "rename the SERVICE",
118 argname
= 'NEW-NAME')],
119 params
= [SC
.Arg('service')])
120 def cmd_editsvc(service
, rename
= None):
122 if service
== 'master':
123 raise U
.ExpectedError
, (400, "Can't edit the master service")
125 CU
.check_service(service
, must_config_p
= True, must_records_p
= True)
127 CU
.check_service(service
, must_config_p
= False, must_records_p
= True)
128 CU
.check_service(rename
, must_config_p
= True, must_records_p
= False)
129 CU
.edit_records('services', 'service = $service',
130 [('service', rename
, False)],
134 'addacct', ['admin'], 'Add an account for a user.',
135 opts
= [SC
.Opt('alias', '-a', '--alias',
136 "alias by which USER is known to SERVICE",
138 params
= [SC
.Arg('user'), SC
.Arg('service')],
139 rparam
= SC
.Arg('fields'))
140 def cmd_addacct(user
, service
, fields
, alias
= None):
143 svc
= CU
.check_service(service
)
144 D
.DB
.execute("""SELECT 1 FROM services
145 WHERE user = $user AND service = $service""",
146 user
= user
, service
= service
)
147 if D
.DB
.fetchone() is not None:
148 raise U
.ExpectedError
, (
149 400, "User `%s' already has a `%s' account" %
(user
, service
))
150 D
.DB
.execute("""INSERT INTO services (service, user, alias)
151 VALUES ($service, $user, $alias)""",
152 service
= service
, user
= user
, alias
= alias
)
154 if svc
.manage_pwent_p
:
155 if alias
is None: alias
= user
156 passwd
= CFG
.RQCLASS
.reset([OP
.acct(svc
, alias
)]).pwgen()
157 svc
.mkpwent(alias
, passwd
, fields
)
159 raise U
.ExpectedError
, (
160 400, "Password entry fields supplied, "
161 "but `%s' entries must be created manually" % service
)
164 'delacct', ['admin'], "Remove USER's SERVICE account.",
165 params
= [SC
.Arg('user'), SC
.Arg('service')])
166 def cmd_delacct(user
, service
):
168 svc
, alias
= CU
.resolve_account(service
, user
)
169 if service
== 'master':
170 raise U
.ExpectedError
, \
171 (400, "Can't delete master accounts: use `deluser'")
172 D
.DB
.execute("""DELETE FROM services
173 WHERE service = $service AND user = $user""",
174 service
= service
, user
= user
)
175 if svc
.manage_pwent_p
:
178 OUT
.warn("You must remove the `%s' password entry for `%s' by hand" %
182 'editacct', ['admin'], "Modify USER's SERVICE account record.",
183 opts
= [SC
.Opt('alias', '-a', '--alias',
184 "change USER's login name for SERVICE",
186 SC
.Opt('noalias', '-A', '--no-alias',
187 "use USER's master login name")],
188 params
= [SC
.Arg('user'), SC
.Arg('service')])
189 def cmd_editacct(user
, service
, alias
= None, noalias
= False):
191 CU
.resolve_account(service
, user
)
192 if service
== 'master':
193 raise U
.ExpectedError
, (400, "Can't edit master accounts")
194 CU
.edit_records('services', 'user = $user AND service = $service',
195 [('alias', alias
, noalias
)],
196 user
= user
, service
= service
)
199 'source', ['admin', 'userv', 'remote'], """\
200 Write source code (in `.tar.gz' format) to standard output.""")
201 def cmd_source_admin():
204 ###----- That's all, folks --------------------------------------------------