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 from auto
import PACKAGE
, VERSION
37 import operation
as OP
38 import output
as O
; OUT
= O
.OUT
; PRINT
= O
.PRINT
40 import subcommand
as SC
43 ###--------------------------------------------------------------------------
46 def operate(what
, op
, services
, *args
, **kw
):
47 accts
= CU
.resolve_accounts(CU
.USER
, services
)
48 o
, ii
, rq
, ops
= OP
.operate(op
, accts
, *args
, **kw
)
49 CGI
.page('operate.fhtml',
50 header
= dict(pragma
= 'no-cache', cache_control
= 'no-cache'),
51 title
= 'Chopwood: %s' % what
,
53 outcome
= o
, info
= ii
, results
= ops
)
55 ###--------------------------------------------------------------------------
58 @CGI.subcommand('list', ['cgi-query'], 'List available accounts')
60 CGI
.page('list.fhtml',
61 header
= dict(pragma
= 'no-cache', cache_control
= 'no-cache'),
62 title
= 'Chopwood: accounts list',
63 accts
= CU
.list_accounts(CU
.USER
),
67 'set', ['cgi'], 'Set password for a collection of services.',
69 params
= [SC
.Arg('first'), SC
.Arg('second')],
70 rparam
= SC
.Arg('services'))
71 def cmd_set_cgi(first
, second
, services
= []):
72 if first
!= second
: raise U
.ExpectedError
, (400, "Passwords don't match")
73 operate('set passwords', 'set', services
, first
)
77 'Reset passwords for a collection of services.',
79 rparam
= SC
.Arg('services'))
80 def cmd_reset_cgi(services
= []):
81 operate('reset passwords', 'reset', services
)
85 'Clear passwords for a collection of services.',
87 rparam
= SC
.Arg('services'))
88 def cmd_clear_cgi(services
= []):
89 operate('clear passwords', 'clear', services
)
93 'Log out of the web interface.',
96 CGI
.redirect(CGI
.action('login', why
= 'LOGOUT'),
97 set_cookie
= HA
.bake_cookie('logged-out'))
100 'fail', ['cgi-noauth'],
101 'Raise an exception, to test the error reporting machinery.',
102 opts
= [SC
.Opt('partial', '-p', '--partial',
103 'Raise exception after producing partial output.')])
104 def cmd_fail_cgi(partial
= False):
106 OUT
.header(content_type
= 'text/html')
109 <head><title>Chopwood: filler text</title></head>
111 <h1>Failure expected soon
112 <p>This is some normal output which will be rudely interrupted.""")
113 raise Exception, 'You asked for this.'
116 'warn', ['cgi-noauth'],
117 'Raise an exception, to test the error reporting machinery.')
119 OUT
.header(content_type
= 'text/html')
120 OUT
.warn("Here's a very important warning.")
121 CGI
.format_tmpl(CGI
.TMPL
['wrapper.fhtml'],
122 title
= "Warning test", warnings
= OUT
.warnings
,
123 payload
= "<h1>Chopwood: warning test</h1>\n"
124 "<p>There ought to be a warning below.\n")
126 ###--------------------------------------------------------------------------
129 ## A map of file names to content objects. See below.
132 class PlainOutput (O
.FileOutput
):
133 def header(me
, **kw
):
136 class StaticContent (object):
137 def __init__(me
, type):
140 OUT
.header(content_type
= me
._type
)
142 def _write(me
, dest
):
143 with
open(dest
, 'w') as f
:
144 with OUT
.redirect_to(PlainOutput(f
)):
150 if e
.errno
!= E
.ENOENT
: raise
154 class TemplateContent (StaticContent
):
155 def __init__(me
, template
, *args
, **kw
):
156 super(TemplateContent
, me
).__init__(*args
, **kw
)
157 me
._template
= template
159 CGI
.format_tmpl(CGI
.TMPL
[me
._template
])
161 class HTMLContent (StaticContent
):
162 def __init__(me
, title
, template
, type = 'text/html', *args
, **kw
):
163 super(HTMLContent
, me
).__init__(type = type, *args
, **kw
)
164 me
._template
= template
167 CGI
.page(me
._template
, title
= me
._title
)
170 'chpwd.css': TemplateContent(template
= 'chpwd.css',
172 'chpwd.js': TemplateContent(template
= 'chpwd.js',
173 type = 'text/javascript'),
174 'about.html': HTMLContent('Chopwood: about this program',
175 template
= 'about.fhtml'),
176 'cookies.html': HTMLContent('Chopwood: use of cookies',
177 template
= 'cookies.fhtml')
181 'static', ['cgi-noauth'], 'Output a static file.',
182 rparam
= SC
.Arg('path'))
183 def cmd_static_cgi(path
):
184 name
= '/'.join(path
)
185 try: content
= CONTENT
[name
]
186 except KeyError: raise U
.ExpectedError
, (404, "Unknown file `%s'" % name
)
190 'static', ['admin'], 'Write the static files to DIR.',
191 params
= [SC
.Arg('dir')])
192 def cmd_static_admin(dir):
193 try: OS
.makedirs(dir, 0777)
195 if e
.errno
!= E
.EEXIST
: raise
196 for f
, c
in CONTENT
.iteritems():
197 c
.write(OS
.path
.join(dir, f
))
199 TARBALL
= '%s-%s.tar.gz' %
(PACKAGE
, VERSION
)
200 @CGI.subcommand(TARBALL
, ['cgi-noauth'], """\
201 Download source code (in `.tar.gz' format).""")
202 def cmd_source_cgi():
203 OUT
.header(content_type
= 'application/octet-stream')
206 @CGI.subcommand('source', ['cgi-noauth'], """\
207 Redirect to the source code tarball (so that it's correctly named).""")
208 def cmd_sourceredirect_cgi():
209 CGI
.redirect(CGI
.action(TARBALL
))
211 ###----- That's all, folks --------------------------------------------------