chiark / gitweb /
Cosmetic fiddling.
[chopwood] / cmd-user.py
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
26 from __future__ import with_statement
27
28 import getpass as GP
29 import sys as SYS
30
31 import cmdutil as CU
32 import dbmaint as D
33 import operation as OP
34 from output import PRINT
35 import service as S
36 import subcommand as SC
37 import util as U
38
39 OMSG = [None,
40         "Partial failure",
41         "Operation failed",
42         "No services selected"]
43
44 def 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
77 is a terminal, read the password interactively, with prompts, disabling echo,
78 and asking for confirmation to catch typos.  Otherwise, just read one line
79 and use the result as the password.""",
80   rparam = SC.Arg('services'))
81 def 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'))
96 def 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
103 work for all services, depending on how passwords are represented.""",
104   rparam = SC.Arg('services'))
105 def 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')
110 def 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 --------------------------------------------------