chiark / gitweb /
chpwd, operation.py: Logging for operations.
[chopwood] / cmd-user.py
CommitLineData
a2916c06
MW
1### -*-python-*-
2###
3### User 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 getpass as GP
29import sys as SYS
30
31import cmdutil as CU
32import dbmaint as D
33import operation as OP
34from output import PRINT
35import service as S
36import subcommand as SC
37import util as U
38
39OMSG = [None,
40 "Partial failure",
41 "Operation failed",
42 "No services selected"]
43
44def operate(op, accts, *args, **kw):
45 """
46 Perform a request as indicated by the arguments (see `operation.operate'
47 for the full details), and report the results.
48 """
49
50 ## Collect the results.
51 o, ii, rq, ops = OP.operate(op, accts, *args, **kw)
52
53 ## Report any additional information collected.
54 if o.nwin and ii:
55 CU.format_list(ii,
56 [CU.column('RESULT', "~={0.desc}A"),
57 CU.column('VALUE', "~={0.value}A")])
58 PRINT()
59
60 ## Report the outcomes of the indvidual operations.
61 if ops:
62 CU.format_list(ops,
63 [CU.column('SERVICE',
64 "~={0.svc.friendly}A"),
65 CU.column('RESULT', "~={0.error}:["
66 "OK~={0.result}@[ ~A~]~;"
67 "FAILED: ~={0.error.msg}A~]")])
68
69 ## If it failed, report an appropriate error.
70 if o.rc:
71 if o.nlose: PRINT()
72 raise U.ExpectedError, (400, OMSG[o.rc])
73
74@SC.subcommand(
75 'set', ['userv'],
76 """Sets the password for the SERVICES to a given string. If standard input
77is a terminal, read the password interactively, with prompts, disabling echo,
78and asking for confirmation to catch typos. Otherwise, just read one line
79and use the result as the password.""",
80 rparam = SC.Arg('services'))
81def cmd_set_userv(services):
82 accts = CU.resolve_accounts(CU.USER, services)
83 if not SYS.stdin.isatty():
84 new = U.readline('new password')
85 else:
86 first = GP.getpass('Enter new password: ')
87 second = GP.getpass('Confirm new password: ')
88 if first != second: raise U.ExpectedError, (400, "Passwords don't match")
89 new = first
90 operate('set', accts, new)
91
92@SC.subcommand(
93 'reset', ['userv'],
94 """Resets the password for the SERVICES.""",
95 rparam = SC.Arg('services'))
96def cmd_reset_userv(services):
97 accts = CU.resolve_accounts(CU.USER, services)
98 operate('reset', accts)
99
100@SC.subcommand(
101 'clear', ['userv'],
102 """Clears the password for the SERVICES, preventing access. This doesn't
103work for all services, depending on how passwords are represented.""",
104 rparam = SC.Arg('services'))
105def cmd_clear_userv(services):
106 accts = CU.resolve_accounts(CU.USER, services)
107 operate('clear', accts)
108
109@SC.subcommand('list', ['userv'], 'List available accounts')
110def cmd_list_userv():
111 CU.format_list(CU.list_accounts(CU.USER),
112 [CU.column('NAME', "~={0.service}A"),
113 CU.column('DESCRIPTION', "~={0.friendly}A"),
114 CU.column('LOGIN', "~={0.alias}:[---~;~={0.alias}A~]")])
115
116###----- That's all, folks --------------------------------------------------