# w.c.s. (asec) - w.c.s. extension for poll & survey service # Copyright (C) 2010-2011 Entr'ouvert # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public # License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import imghdr from quixote import get_request, get_response, get_session, redirect from quixote.directory import Directory from quixote.html import TemplateIO, htmltext from qommon import misc, get_cfg, get_logger from qommon.admin.cfg import cfg_submit from qommon.backoffice.menu import html_top import qommon.ident.password from qommon.ident.password_accounts import PasswordAccount import qommon.admin.texts from qommon.form import * import quota def get_logo_url(): pages_data_dir = os.path.join(get_publisher().app_dir, 'pages', 'data') for f in ('png', 'jpeg', 'gif'): logo_path = os.path.join(pages_data_dir, 'logo.%s' % f) if os.path.exists(logo_path): return '%spages/data/logo.%s' % (get_publisher().get_root_url(), f) return None class TextsDirectory(qommon.admin.texts.TextsDirectory): def html_top(self, title): html_top('config', title) class ConfigDirectory(Directory): _q_exports = ['', 'password', 'contact', 'sitetitle', 'homepage', 'texts', 'appearance', 'logo'] def _q_traverse (self, path): get_response().breadcrumb.append( ('config/', _('Configuration')) ) self.texts = TextsDirectory() self.texts.texts_dict = self.texts.texts_dict.copy() for k in self.texts.texts_dict.keys(): if k not in ('asec-recorded-vote',): del self.texts.texts_dict[k] return Directory._q_traverse(self, path) def _q_index(self): return redirect('..') def contact(self): get_response().breadcrumb.append( ('contact', _('Contact Information')) ) r = TemplateIO(html=True) form = Form(enctype='multipart/form-data') user = get_request().user form.add(StringWidget, 'name', title=_('Name'), required=True, size=30, value = user.name) form.add(EmailWidget, 'email', title=_('Email'), required=False, size=30, value=user.email) form.add_submit('submit', _('Apply Changes')) form.add_submit('cancel', _('Cancel')) if form.get_submit() == 'cancel': return redirect('.') if form.is_submitted() and not form.has_errors(): self.contact_submit(form) return redirect('.') html_top('config', _('Contact Information')) r += htmltext('

%s

') % _('Contact Information') r += form.render() return r.getvalue() def contact_submit(self, form): user = get_request().user for f in ('name', 'email'): widget = form.get_widget(f) if widget: setattr(user, f, widget.parse()) user.store() def password(self): get_response().breadcrumb.append( ('password', _('Password Change')) ) ident_method = get_cfg('identification', {}).get('methods', ['idp'])[0] if ident_method != 'password': raise errors.TraversalError() form = Form(enctype='multipart/form-data') form.add(PasswordWidget, 'current_password', title=_('Current Password'), required=True) form.add(PasswordWidget, 'new_password', title=_('New Password'), required=True) form.add(PasswordWidget, 'new2_password', title=_('New Password (confirm)'), required=True) form.add_submit('submit', _('Change Password')) form.add_submit('cancel', _('Cancel')) if form.get_submit() == 'cancel': return redirect('.') if form.is_submitted() and not form.has_errors(): account = PasswordAccount.get(get_session().username) if not account.is_password_ok(form.get_widget('current_password').parse()): form.set_error('current_password', _('Wrong Password')) if form.is_submitted() and not form.has_errors(): qommon.ident.password.check_password(form, 'new_password') new_password = form.get_widget('new_password').parse() new2_password = form.get_widget('new2_password').parse() if new_password != new2_password: form.set_error('new2_password', _('Passwords do not match')) if form.is_submitted() and not form.has_errors(): passwords_cfg = get_cfg('passwords', {}) account = PasswordAccount.get(get_session().username) account.hashing_algo = passwords_cfg.get('hashing_algo') account.set_password(new_password) account.store() return redirect('.') html_top('config', _('Password Change')) r = TemplateIO(html=True) r += htmltext('

%s

') % _('Password Change') r += form.render() return r.getvalue() def sitetitle(self): get_response().breadcrumb.append( ('sitetitle', _('Site Title')) ) misc_cfg = get_cfg('misc', {}) form = Form(enctype='multipart/form-data') form.add(StringWidget, 'sitename', title=_('Site Title'), value=misc_cfg.get('sitename', ''), size=30) form.add_submit('submit', _('Submit')) form.add_submit('cancel', _('Cancel')) if form.get_widget('cancel').parse(): return redirect('.') if not form.is_submitted() or form.has_errors(): html_top('config', title = _('Site Title')) r = TemplateIO(html=True) r += htmltext('

%s

') % _('Site Title') r += form.render() return r.getvalue() else: cfg_submit(form, 'misc', ['sitename']) redirect('.') def homepage(self): get_response().breadcrumb.append( ('homepage', _('Home Page Text')) ) texts_cfg = get_cfg('texts', {}) form = Form(enctype='multipart/form-data') form.add(TextWidget, 'welcome-unlogged', title=_('For unlogged users'), value=texts_cfg.get('text-welcome-unlogged'), cols=80, rows=10) form.add(TextWidget, 'welcome-logged', title=_('For logged users'), value=texts_cfg.get('text-welcome-logged'), cols=80, rows=10) form.add_submit('submit', _('Submit')) form.add_submit('cancel', _('Cancel')) if form.get_widget('cancel').parse(): return redirect('.') if not form.is_submitted() or form.has_errors(): html_top('config', title = _('Home Page Text')) r = TemplateIO(html=True) r += htmltext('

%s

') % _('Home Page Text') r += form.render() return r.getvalue() else: texts_cfg[str('text-welcome-unlogged')] = form.get_widget('welcome-unlogged').parse() texts_cfg[str('text-welcome-logged')] = form.get_widget('welcome-logged').parse() get_publisher().cfg[str('texts')] = texts_cfg get_publisher().write_cfg() redirect('.') def appearance(self): get_response().breadcrumb.append(('appearance', _('Appearance'))) html_top('config', title = _('Appearance')) r = TemplateIO(html=True) if quota.can_theme(): r += htmltext("

%s

") % _('Appearance') r += self.appearance_theme() if quota.can_logo(): r += self.appearance_logo() return r.getvalue() def appearance_theme(self): request = get_request() if request.form.has_key('theme'): themes = qommon.template.get_themes() if themes.has_key(str(request.form['theme'])): branding_cfg = get_cfg('branding', {}) branding_cfg[str('theme')] = str(request.form['theme']) get_publisher().cfg[str('branding')] = branding_cfg get_publisher().write_cfg() current_theme = get_cfg('branding', {}).get('theme', 'default') r = TemplateIO(html=True) r += htmltext('
') r += htmltext('

') r += _('Click on a thumbnail to change the appearance of your site.') r += htmltext('

') themes = qommon.template.get_themes() for theme, (label, desc, author, icon) in sorted(themes.items()): if not theme.startswith(str('asec')): # ignore themes that were not made for asec continue if current_theme == theme: active = ' active' else: active = '' r += htmltext('
') % active r += htmltext('') % theme r += htmltext('') % theme r += htmltext('') r += htmltext('
') r += htmltext('
') r += htmltext('
') return r.getvalue() def appearance_logo(self): r = TemplateIO(html=True) r += htmltext('
') r += htmltext('

%s

') % _('Logo') r += get_session().display_message() logo_url = get_logo_url() if logo_url: r += htmltext('') % logo_url r += htmltext('
') r += htmltext('') if logo_url: r += htmltext('') % _('Upload New Logo') r += htmltext('') % _('Remove Current Logo') else: r += htmltext('') % _('Upload Logo') r += htmltext('
') r += htmltext('
') return r.getvalue() def logo(self): if not quota.can_logo(): raise quota.NotAvailableFeature() form = Form(enctype='multipart/form-data', use_tokens=False) form.add(FileWidget, 'file', title = _('Theme'), required=True) form.add_submit('submit', _('Upload')) form.add_submit('remove', _('Remove')) if not form.is_submitted(): return redirect('appearance') pages_data_dir = os.path.join(get_publisher().app_dir, 'pages', 'data') if form.get_submit() == 'remove': for f in ('png', 'jpeg', 'gif'): logo_path = os.path.join(pages_data_dir, 'logo.%s' % f) if os.path.exists(logo_path): os.unlink(logo_path) return redirect('appearance') # how come? return redirect('appearance') if form.has_errors(): get_session().message = ('error', _('Failed to set logo.')) return redirect('appearance') logo = form.get_widget('file').parse().fp.read() try: format = imghdr.what(None, logo) except: get_session().message = ('error', _('Failed to set logo (unknown format).')) return redirect('appearance') if format not in ('png', 'jpeg', 'gif'): get_session().message = ('error', _('Failed to set logo (format must be png, jpeg, or gif).')) return redirect('appearance') if not os.path.exists(pages_data_dir): os.makedirs(pages_data_dir) for f in ('png', 'jpeg', 'gif'): logo_path = os.path.join(pages_data_dir, 'logo.%s' % f) if f == format: file(logo_path, 'w').write(logo) else: # make sure older logo are removed if os.path.exists(logo_path): os.unlink(logo_path) return redirect('appearance')