chiark / gitweb /
httpauth.py: Don't crash if Base-64 decoding of the CSRF token fails.
[chopwood] / cmd-admin.py
CommitLineData
a2916c06
MW
1### -*-python-*-
2###
3### Administrative commands
4###
5### (c) 2013 Mark Wooding
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This file is part of Chopwood: a password-changing service.
11###
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.
16###
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.
21###
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/>.
25
26from __future__ import with_statement
27
28import agpl as AGPL
29import cmdutil as CU
30import dbmaint as D
31from output import OUT, PRINT
32import subcommand as SC
33import util as U
34
35@SC.subcommand(
36 'listusers', ['admin'], 'List the existing users.',
37 opts = [SC.Opt('service', '-s', '--service',
38 'list users with SERVICE accounts',
39 argname = 'SERVICE')],
40 oparams = [SC.Arg('pat')])
41def cmd_listuser(service = None, pat = None):
42 CU.format_list(CU.list_users(service, pat),
43 [CU.column('USER', "~={0.user}A", 3),
44 CU.column('EMAIL', "~={0.email}:[---~;~={0.email}A~]")])
45
46@SC.subcommand(
47 'adduser', ['admin'], 'Add a user to the master database.',
48 opts = [SC.Opt('email', '-e', '--email',
49 "email address for the new user",
50 argname = 'EMAIL')],
51 params = [SC.Arg('user')])
52def cmd_adduser(user, email = None):
53 with D.DB:
54 CU.check_user(user, False)
55 D.DB.execute("INSERT INTO users (user, email) VALUES ($user, $email)",
56 user = user, email = email)
57 D.DB.execute("""INSERT INTO services (user, service)
58 VALUES ($user, $service)""",
59 user = user, service = 'master')
60
61@SC.subcommand(
62 'deluser', ['admin'], 'Remove USER from the master database.',
63 params = [SC.Arg('user')])
64def cmd_deluser(user, email = None):
65 with D.DB:
66 CU.check_user(user)
67 D.DB.execute("DELETE FROM users WHERE user = $user", user = user)
68
69@SC.subcommand(
70 'edituser', ['admin'], 'Modify a user record.',
71 opts = [SC.Opt('email', '-e', '--email',
72 "change USER's email address",
73 argname = 'EMAIL'),
74 SC.Opt('noemail', '-E', '--no-email',
75 "forget USER's email address"),
76 SC.Opt('rename', '-r', '--rename',
77 "rename USER",
78 argname = 'NEW-NAME')],
79 params = [SC.Arg('user')])
80def cmd_edituser(user, email = None, noemail = False, rename = None):
81 with D.DB:
82 CU.check_user(user)
83 if rename is not None: check_user(rename, False)
84 CU.edit_records('users', 'user = $user',
85 [('email', email, noemail),
86 ('user', rename, False)],
87 user = user)
88
89@SC.subcommand(
90 'delsvc', ['admin'], "Remove all records for SERVICE.",
91 params = [SC.Arg('service')])
92def cmd_delsvc(service):
93 with D.DB:
94 CU.check_service(service, must_config_p = False, must_records_p = True)
95 D.DB.execute("DELETE FROM services WHERE service = $service",
96 service = service)
97
98@SC.subcommand(
99 'editsvc', ['admin'], "Edit a given SERVICE.",
100 opts = [SC.Opt('rename', '-r', '--rename', "rename the SERVICE",
101 argname = 'NEW-NAME')],
102 params = [SC.Arg('service')])
103def cmd_editsvc(service, rename = None):
104 with D.DB:
105 if service == 'master':
106 raise U.ExpectedError, (400, "Can't edit the master service")
107 if rename is None:
108 CU.check_service(service, must_config_p = True, must_records_p = True)
109 else:
110 CU.check_service(service, must_config_p = False, must_records_p = True)
111 CU.check_service(rename, must_config_p = True, must_records_p = False)
112 CU.edit_records('services', 'service = $service',
113 [('service', rename, False)],
114 service = service)
115
116@SC.subcommand(
117 'addacct', ['admin'], 'Add an account for a user.',
118 opts = [SC.Opt('alias', '-a', '--alias',
119 "alias by which USER is known to SERVICE",
120 argname = 'ALIAS')],
121 params = [SC.Arg('user'), SC.Arg('service')])
122def cmd_addacct(user, service, alias = None):
123 with D.DB:
124 CU.check_user(user)
125 CU.check_service(service)
126 D.DB.execute("""SELECT 1 FROM services
127 WHERE user = $user AND service = $service""",
128 user = user, service = service)
129 if D.DB.fetchone() is not None:
130 raise U.ExpectedError, (
131 400, "User `%s' already has `%s' account" % (user, service))
132 D.DB.execute("""INSERT INTO services (service, user, alias)
133 VALUES ($service, $user, $alias)""",
134 service = service, user = user, alias = alias)
135
136@SC.subcommand(
137 'delacct', ['admin'], "Remove USER's SERVICE account.",
138 params = [SC.Arg('user'), SC.Arg('service')])
139def cmd_delacct(user, service):
140 with D.DB:
141 CU.resolve_account(service, user)
142 if service == 'master':
143 raise U.ExpectedError, \
144 (400, "Can't delete master accounts: use `deluser'")
145 D.DB.execute("""DELETE FROM services
146 WHERE service = $service AND user = $user""",
147 service = service, user = user)
148
149@SC.subcommand(
150 'editacct', ['admin'], "Modify USER's SERVICE account record.",
151 opts = [SC.Opt('alias', '-a', '--alias',
152 "change USER's login name for SERVICE",
153 argname = 'ALIAS'),
154 SC.Opt('noalias', '-A', '--no-alias',
155 "use USER's master login name")],
156 params = [SC.Arg('user'), SC.Arg('service')])
157def cmd_editacct(user, service, alias = None, noalias = False):
158 with D.DB:
159 CU.resolve_account(service, user)
160 if service == 'master':
161 raise U.ExpectedError, (400, "Can't edit master accounts")
162 CU.edit_records('services', 'user = $user AND service = $service',
163 [('alias', alias, noalias)],
164 user = user, service = service)
165
166@SC.subcommand(
4f09f456 167 'source', ['admin', 'userv', 'remote'], """\
a2916c06
MW
168Write source code (in `.tar.gz' format) to standard output.""")
169def cmd_source_admin():
170 AGPL.source(OUT)
171
172###----- That's all, folks --------------------------------------------------