chiark / gitweb /
Cosmetic fiddling.
[chopwood] / cmd-admin.py
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
26 from __future__ import with_statement
27
28 import agpl as AGPL
29 import cmdutil as CU
30 import dbmaint as D
31 from output import OUT, PRINT
32 import subcommand as SC
33 import 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')])
41 def 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')])
52 def 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')])
64 def 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')])
80 def 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')])
92 def 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')])
103 def 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')])
122 def 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 a `%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')])
139 def 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')])
157 def 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(
167   'source', ['admin', 'userv', 'remote'], """\
168 Write source code (in `.tar.gz' format) to standard output.""")
169 def cmd_source_admin():
170   AGPL.source(OUT)
171
172 ###----- That's all, folks --------------------------------------------------