- Added a menu panel in the sidebar
- Added an account page - Added a timezone - Added a change password page - Various other bugfixes and tweaks
This commit is contained in:
commit
ca205d287f
@ -42,6 +42,7 @@ paths.themes = %(here)s/themes
|
|||||||
# Security settings
|
# Security settings
|
||||||
security.salt = secretsalt
|
security.salt = secretsalt
|
||||||
|
|
||||||
|
# Mail server settings
|
||||||
mail.on = false
|
mail.on = false
|
||||||
mail.manager = immediate
|
mail.manager = immediate
|
||||||
mail.transport = smtp
|
mail.transport = smtp
|
||||||
@ -49,6 +50,9 @@ mail.smtp.server = mail.mydomain.com
|
|||||||
mail.smtp.username = mymailusername
|
mail.smtp.username = mymailusername
|
||||||
mail.smtp.password = mymailpassword
|
mail.smtp.password = mymailpassword
|
||||||
|
|
||||||
|
# Server-related settings
|
||||||
|
server.timezone = 'Africa/Johannesburg'
|
||||||
|
|
||||||
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
|
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
|
||||||
# Debug mode will enable the interactive debugging tool, allowing ANYONE to
|
# Debug mode will enable the interactive debugging tool, allowing ANYONE to
|
||||||
# execute malicious code after an exception is raised.
|
# execute malicious code after an exception is raised.
|
||||||
|
@ -51,9 +51,12 @@ def make_map():
|
|||||||
map.connect('/tag/{id}', controller='blog', action='tag')
|
map.connect('/tag/{id}', controller='blog', action='tag')
|
||||||
map.connect('/calendar/{year}/{month}', controller='blog', action='calendar')
|
map.connect('/calendar/{year}/{month}', controller='blog', action='calendar')
|
||||||
|
|
||||||
|
map.connect('/{controller}')
|
||||||
map.connect('/{controller}/{action}')
|
map.connect('/{controller}/{action}')
|
||||||
map.connect('/{controller}/{action}/{id}')
|
map.connect('/{controller}/{action}/{id}')
|
||||||
|
|
||||||
|
map.connect('/{url}', controller='page', action='view')
|
||||||
|
|
||||||
map.connect('/', controller='blog', action='index')
|
map.connect('/', controller='blog', action='index')
|
||||||
|
|
||||||
return map
|
return map
|
||||||
|
@ -27,6 +27,7 @@ from urlparse import urlsplit
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from formencode.validators import Int
|
from formencode.validators import Int
|
||||||
|
from pytz import all_timezones
|
||||||
|
|
||||||
from scribeengine.lib.base import *
|
from scribeengine.lib.base import *
|
||||||
from scribeengine.lib.validation.client import JSString, JSEmail
|
from scribeengine.lib.validation.client import JSString, JSEmail
|
||||||
@ -39,26 +40,94 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class AccountController(BaseController):
|
class AccountController(BaseController):
|
||||||
|
|
||||||
|
@authenticate()
|
||||||
def index(self):
|
def index(self):
|
||||||
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
|
c.page_title = u'My Account'
|
||||||
|
c.timezones = all_timezones
|
||||||
|
return render(u'/account/index.mako')
|
||||||
|
|
||||||
|
@jsvalidate(u'account-account')
|
||||||
|
def index_jsschema(self):
|
||||||
|
return {
|
||||||
|
u'account-nick': JSString(required=True,
|
||||||
|
message=u'You need to type in a nick.'),
|
||||||
|
u'account-email': JSEmail(required=True,
|
||||||
|
message=u'You need to supply a valid e-mail address.')
|
||||||
|
}
|
||||||
|
|
||||||
|
def index_schema(self):
|
||||||
|
return {
|
||||||
|
'account-nick': UnicodeString(not_empty=True,
|
||||||
|
messages={u'empty': u'You need to type in a nick.'}),
|
||||||
|
'account-email': Email(not_empty=True,
|
||||||
|
messages={u'empty': u'You need to supply a valid e-mail address.'})
|
||||||
|
}
|
||||||
|
|
||||||
|
def index_POST(self):
|
||||||
|
try:
|
||||||
|
for key, value in c.form_values.iteritems():
|
||||||
|
setattr(c.current_user, key[8:], value)
|
||||||
|
Session.add(c.current_user)
|
||||||
|
Session.commit()
|
||||||
|
h.flash.set_message(u'Successfully updated your account.', u'success')
|
||||||
|
except:
|
||||||
|
h.flash.set_message(u'There was a problem updating your account.', u'error')
|
||||||
|
h.redirect_to(h.url_for(controller=u'account'))
|
||||||
|
|
||||||
|
@authenticate()
|
||||||
|
def password(self):
|
||||||
|
c.page_title = u'Your Password'
|
||||||
|
return render(u'/account/password.mako')
|
||||||
|
|
||||||
|
@jsvalidate(u'account-password')
|
||||||
|
def password_jsschema(self):
|
||||||
|
return {
|
||||||
|
u'password-password': JSString(required=True, message=u'You haven\'t typed in a password.'),
|
||||||
|
u'password-confirm': JSString(required=True, equalTo=u'#password-password', message=u'Your passwords don\'t match.')
|
||||||
|
}
|
||||||
|
|
||||||
|
def password_schema(self):
|
||||||
|
return {
|
||||||
|
'password-password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'}),
|
||||||
|
'confirm-password': [FieldsMatch('password-password', 'password-confirm', messages={'invalid': u'Your passwords don\'t match.'})]
|
||||||
|
}
|
||||||
|
|
||||||
|
@authenticate()
|
||||||
|
def password_POST(self):
|
||||||
|
password_hash = utils.hash_password(c.form_values[u'password-password'])
|
||||||
|
log.debug('Old Hash: "%s"', c.current_user.password)
|
||||||
|
log.debug('New Hash: "%s"', password_hash)
|
||||||
|
c.current_user.password = password_hash
|
||||||
|
c.current_user.modified = datetime.now()
|
||||||
|
Session.add(c.current_user)
|
||||||
|
Session.commit()
|
||||||
|
h.flash.set_message(u'Successfully updated your password.', u'success')
|
||||||
|
h.redirect_to('/account/password')
|
||||||
|
|
||||||
def register(self):
|
def register(self):
|
||||||
c.page_title = u'Register'
|
c.page_title = u'Register'
|
||||||
return render(u'/account/register.mako')
|
return render(u'/account/register.mako')
|
||||||
|
|
||||||
@jsvalidate(u'register-form')
|
@jsvalidate(u'account-register')
|
||||||
def register_jsschema(self):
|
def register_jsschema(self):
|
||||||
return {
|
return {
|
||||||
u'register-email': JSEmail(required=True, message=u'You haven\'t typed in an e-mail address.'),
|
u'register-email': JSEmail(required=True,
|
||||||
u'register-password': JSString(required=True, message=u'You haven\'t typed in a password.'),
|
message=u'You haven\'t typed in an e-mail address.'),
|
||||||
u'register-confirm': JSString(required=True, equalTo=u'#password', message=u'Your passwords don\'t match.')
|
u'register-password': JSString(required=True,
|
||||||
|
message=u'You haven\'t typed in a password.'),
|
||||||
|
u'register-confirm': JSString(required=True, equalTo=u'#password',
|
||||||
|
message=u'Your passwords don\'t match.')
|
||||||
}
|
}
|
||||||
|
|
||||||
def register_schema(self):
|
def register_schema(self):
|
||||||
return {
|
return {
|
||||||
'register-email': Email(not_empty=True, messages={'empty': u'You haven\'t typed in an e-mail address.'}),
|
'register-email': Email(not_empty=True,
|
||||||
'register-password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'}),
|
messages={'empty': u'You haven\'t typed in an e-mail address.'}),
|
||||||
'confirm-password': [FieldsMatch('register-password', 'register-confirm', messages={'invalid': u'Your passwords don\'t match.'})]
|
'register-password': UnicodeString(not_empty=True,
|
||||||
|
messages={'empty': u'You haven\'t typed in a password.'}),
|
||||||
|
'confirm-password': [
|
||||||
|
FieldsMatch('register-password', 'register-confirm',
|
||||||
|
messages={'invalid': u'Your passwords don\'t match.'})]
|
||||||
}
|
}
|
||||||
|
|
||||||
def register_POST(self):
|
def register_POST(self):
|
||||||
@ -168,7 +237,10 @@ class AccountController(BaseController):
|
|||||||
u'e-mail.', u'success')
|
u'e-mail.', u'success')
|
||||||
h.redirect_to('/account/login')
|
h.redirect_to('/account/login')
|
||||||
|
|
||||||
def password(self, id=None):
|
def resetpassword(self, id=None):
|
||||||
|
"""
|
||||||
|
Reset your password.
|
||||||
|
"""
|
||||||
if not id or not request.GET.get(u'code'):
|
if not id or not request.GET.get(u'code'):
|
||||||
h.flash.set_message(u'There was a problem with your activation code, please reset your password again.', u'error')
|
h.flash.set_message(u'There was a problem with your activation code, please reset your password again.', u'error')
|
||||||
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
|
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
|
||||||
@ -179,33 +251,35 @@ class AccountController(BaseController):
|
|||||||
if c.user.activation_key != request.GET.get(u'code'):
|
if c.user.activation_key != request.GET.get(u'code'):
|
||||||
h.flash.set_message(u'There was a problem with your activation code, please reset your password again.', u'error')
|
h.flash.set_message(u'There was a problem with your activation code, please reset your password again.', u'error')
|
||||||
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
|
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
|
||||||
c.page_title = u'Change Password'
|
c.page_title = u'Reset Password'
|
||||||
return render(u'/account/password.mako')
|
return render(u'/account/resetpassword.mako')
|
||||||
|
|
||||||
@jsvalidate(u'account-password')
|
@jsvalidate(u'account-resetpassword')
|
||||||
def password_jsschema(self):
|
def resetpassword_jsschema(self):
|
||||||
return {
|
return {
|
||||||
u'password-password': JSString(required=True, message=u'You haven\'t typed in a password.'),
|
u'password-password': JSString(required=True, message=u'You haven\'t typed in a password.'),
|
||||||
u'password-confirm': JSString(required=True, equalTo=u'#password-password', message=u'Your passwords don\'t match.')
|
u'password-confirm': JSString(required=True, equalTo=u'#password-password', message=u'Your passwords don\'t match.')
|
||||||
}
|
}
|
||||||
|
|
||||||
def password_schema(self):
|
def resetpassword_schema(self):
|
||||||
return {
|
return {
|
||||||
'password-password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'}),
|
'password-password': UnicodeString(not_empty=True, messages={'empty': u'You haven\'t typed in a password.'}),
|
||||||
'confirm-password': [FieldsMatch('password-password', 'password-confirm', messages={'invalid': u'Your passwords don\'t match.'})]
|
'confirm-password': [FieldsMatch('password-password', 'password-confirm', messages={'invalid': u'Your passwords don\'t match.'})]
|
||||||
}
|
}
|
||||||
|
|
||||||
def password_POST(self, id=None):
|
def resetpassword_POST(self, id=None):
|
||||||
user = Session.query(User).get(id)
|
user = Session.query(User).get(id)
|
||||||
if not user:
|
if not user:
|
||||||
h.flash.set_message(u'There was a problem with your account, please reset your password again.', u'error')
|
h.flash.set_message(u'There was a problem with your account, '
|
||||||
|
u'please reset your password again.', u'error')
|
||||||
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
|
h.redirect_to(h.url_for(controller=u'account', action=u'login'))
|
||||||
user.password = utils.hash_password(c.form_values[u'password-password'])
|
user.password = utils.hash_password(c.form_values[u'password-password'])
|
||||||
user.activation_key = None
|
user.activation_key = None
|
||||||
user.modified = datetime.now()
|
user.modified = datetime.now()
|
||||||
Session.add(user)
|
Session.add(user)
|
||||||
Session.commit()
|
Session.commit()
|
||||||
h.flash.set_message(u'Successfully updated your password. Please login with your new password.', u'success')
|
h.flash.set_message(u'Successfully updated your password. Please login '
|
||||||
|
u'with your new password.', u'success')
|
||||||
h.redirect_to('/account/login')
|
h.redirect_to('/account/login')
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
|
@ -25,6 +25,7 @@ from datetime import datetime
|
|||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
|
|
||||||
from sqlalchemy.sql import or_
|
from sqlalchemy.sql import or_
|
||||||
|
from pytz import timezone
|
||||||
|
|
||||||
from scribeengine.lib.base import *
|
from scribeengine.lib.base import *
|
||||||
from scribeengine.lib import utils
|
from scribeengine.lib import utils
|
||||||
@ -170,7 +171,10 @@ class BlogController(BaseController):
|
|||||||
def calendar(self, year, month):
|
def calendar(self, year, month):
|
||||||
#c.calendar = Calendar(6)
|
#c.calendar = Calendar(6)
|
||||||
#c.today = datetime.today()
|
#c.today = datetime.today()
|
||||||
c.thismonth = datetime.now().replace(int(year), int(month))
|
server_tz = timezone(config.get(u'server.timezone', u'UTC'))
|
||||||
|
user_tz = c.current_user.timezone if c.current_user and c.current_user.timezone else u'UTC'
|
||||||
|
now = datetime.now(server_tz).astimezone(timezone(user_tz))
|
||||||
|
c.thismonth = now.replace(int(year), int(month))
|
||||||
c.prev_month = c.thismonth - monthdelta(1)
|
c.prev_month = c.thismonth - monthdelta(1)
|
||||||
c.next_month = c.thismonth + monthdelta(1)
|
c.next_month = c.thismonth + monthdelta(1)
|
||||||
month_start = datetime(c.thismonth.year, c.thismonth.month, 1, 0, 0, 0, 0)
|
month_start = datetime(c.thismonth.year, c.thismonth.month, 1, 0, 0, 0, 0)
|
||||||
|
75
scribeengine/controllers/page.py
Normal file
75
scribeengine/controllers/page.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# ScribeEngine - Open Source Blog Software #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2010 Raoul Snyman #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# This program is free software; you can redistribute it and/or modify it #
|
||||||
|
# under the terms of the GNU General Public License as published by the Free #
|
||||||
|
# Software Foundation; version 2 of the License. #
|
||||||
|
# #
|
||||||
|
# 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 General Public License for #
|
||||||
|
# more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License along #
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
import time
|
||||||
|
|
||||||
|
from scribeengine.lib.base import *
|
||||||
|
from scribeengine.lib import utils
|
||||||
|
from scribeengine.model import Page
|
||||||
|
from scribeengine.model.meta import Session
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class PageController(BaseController):
|
||||||
|
|
||||||
|
def index(self):
|
||||||
|
h.redirect_to('/')
|
||||||
|
|
||||||
|
def view(self, url):
|
||||||
|
c.page = Session.query(Page)\
|
||||||
|
.filter_by(url=url)\
|
||||||
|
.first()
|
||||||
|
#.filter_by(status=u'published')\
|
||||||
|
c.page_title = c.page.title
|
||||||
|
return render(u'/page/view.mako')
|
||||||
|
|
||||||
|
@authenticate(u'Add Pages')
|
||||||
|
def new(self):
|
||||||
|
c.page_title = u'New Page'
|
||||||
|
return render(u'/page/new.mako')
|
||||||
|
|
||||||
|
@authenticate(u'Edit My Pages')
|
||||||
|
def edit(self, id=None):
|
||||||
|
if id is None:
|
||||||
|
h.redirect_to(h.url_for(controller=u'page', action=u'new'))
|
||||||
|
c.page = Session.query(Page).get(id)
|
||||||
|
c.page_title = u'Edit Page: %s' % c.page.title
|
||||||
|
return render(u'/post/edit.mako')
|
||||||
|
|
||||||
|
@authenticate(u'Edit My Pages')
|
||||||
|
def edit_POST(self, id=None):
|
||||||
|
url = utils.generate_url(c.form_values[u'page-title'])
|
||||||
|
if id is None:
|
||||||
|
page = Page()
|
||||||
|
page.user = c.current_user
|
||||||
|
page.created = datetime.now()
|
||||||
|
else:
|
||||||
|
page = Session.query(Page).get(id)
|
||||||
|
page.modified = datetime.now()
|
||||||
|
page.title = c.form_values[u'page-title']
|
||||||
|
page.body = c.form_values[u'page-body']
|
||||||
|
page.url = url
|
||||||
|
Session.add(page)
|
||||||
|
Session.commit()
|
||||||
|
h.redirect_to('/' + str(page.url))
|
@ -39,6 +39,7 @@ from pylons.templating import render_mako
|
|||||||
from sqlalchemy.sql.expression import asc, desc
|
from sqlalchemy.sql.expression import asc, desc
|
||||||
from formencode import Schema, Invalid
|
from formencode import Schema, Invalid
|
||||||
from monthdelta import monthdelta
|
from monthdelta import monthdelta
|
||||||
|
from pytz import timezone
|
||||||
|
|
||||||
from scribeengine.lib import helpers as h
|
from scribeengine.lib import helpers as h
|
||||||
from scribeengine.lib.validation import jsvalidate
|
from scribeengine.lib.validation import jsvalidate
|
||||||
@ -57,9 +58,11 @@ class BaseController(WSGIController):
|
|||||||
c.categories = Session.query(Category).order_by(Category.name.asc()).all()
|
c.categories = Session.query(Category).order_by(Category.name.asc()).all()
|
||||||
c.pages = Session.query(Page).all()
|
c.pages = Session.query(Page).all()
|
||||||
c.calendar = Calendar(6)
|
c.calendar = Calendar(6)
|
||||||
c.today = datetime.today()
|
server_tz = timezone(config.get(u'server.timezone', u'UTC'))
|
||||||
|
user_tz = c.current_user.timezone if c.current_user and c.current_user.timezone else u'UTC'
|
||||||
|
c.today = datetime.now(server_tz).astimezone(timezone(user_tz))
|
||||||
if not c.thismonth:
|
if not c.thismonth:
|
||||||
c.thismonth = datetime.now()
|
c.thismonth = c.today #datetime.utcnow().astimezone(timezone(c.current_user.timezone))
|
||||||
c.prev_month = c.thismonth - monthdelta(1)
|
c.prev_month = c.thismonth - monthdelta(1)
|
||||||
c.next_month = c.thismonth + monthdelta(1)
|
c.next_month = c.thismonth + monthdelta(1)
|
||||||
month_start = datetime(c.thismonth.year, c.thismonth.month, 1, 0, 0, 0, 0)
|
month_start = datetime(c.thismonth.year, c.thismonth.month, 1, 0, 0, 0, 0)
|
||||||
|
@ -108,6 +108,12 @@ class User(BaseModel):
|
|||||||
if perm == permission:
|
if perm == permission:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
elif isinstance(permission, list):
|
||||||
|
for role in self.roles:
|
||||||
|
for perm in role.permissions:
|
||||||
|
if perm.name in permission:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -103,6 +103,7 @@ users_table = Table(u'users', metadata,
|
|||||||
Column(u'first_name', Unicode(100), default=u''),
|
Column(u'first_name', Unicode(100), default=u''),
|
||||||
Column(u'last_name', Unicode(100), default=u''),
|
Column(u'last_name', Unicode(100), default=u''),
|
||||||
Column(u'homepage', Unicode(200), default=u''),
|
Column(u'homepage', Unicode(200), default=u''),
|
||||||
|
Column(u'timezone', Unicode(200), default=u'UTC'),
|
||||||
Column(u'activation_key', Unicode(40), default=None)
|
Column(u'activation_key', Unicode(40), default=None)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -393,6 +393,19 @@ fieldset {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-select {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #1f1f1f;
|
||||||
|
font-size: 1.2em;
|
||||||
|
border: 1px solid #454545;
|
||||||
|
padding: 3px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-select option {
|
||||||
|
background-color: #1f1f1f;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.form-text {
|
.form-text {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
@ -423,6 +436,22 @@ fieldset {
|
|||||||
margin-top: 0.2em;
|
margin-top: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fieldset.form-details {
|
||||||
|
background-color: #111;
|
||||||
|
margin: 4em 0 1.5em;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.form-details legend {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: -1.7em 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.form-details .form-text {
|
||||||
|
width: 573px;
|
||||||
|
}
|
||||||
|
|
||||||
#register-now {
|
#register-now {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
48
scribeengine/templates/account/index.mako
Normal file
48
scribeengine/templates/account/index.mako
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<%inherit file="/base.mako"/>
|
||||||
|
<%include file="/flash.mako"/>
|
||||||
|
<div class="post">
|
||||||
|
<h2 class="title">My Account</h2>
|
||||||
|
<p>This is your account page. Update your details by changing them below and clicking the Save button.</p>
|
||||||
|
<%include file="/errors.mako"/>
|
||||||
|
<form id="account-account" action="${h.url_for(controller=u'account', action=u'index')}" method="post">
|
||||||
|
<fieldset class="form-details">
|
||||||
|
<legend>Required Details</legend>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="account-nick">Nick:</label>
|
||||||
|
<input type="text" name="account-nick" id="account-nick" class="form-text" value="${c.current_user.nick}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="account-email">E-mail:</label>
|
||||||
|
<input type="text" name="account-email" id="account-email" class="form-text" value="${c.current_user.email}" />
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="form-details">
|
||||||
|
<legend>Personal Details</legend>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="account-first_name">First Name:</label>
|
||||||
|
<input type="text" name="account-first_name" id="account-first_name" class="form-text" value="${c.current_user.first_name}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="account-last_name">Last Name:</label>
|
||||||
|
<input type="text" name="account-last_name" id="account-last_name" class="form-text" value="${c.current_user.last_name}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="account-timezone">Timezone:</label>
|
||||||
|
<select name="account-timezone" id="account-timezone" class="form-select">
|
||||||
|
% for timezone in c.timezones:
|
||||||
|
% if c.current_user.timezone == timezone:
|
||||||
|
<option value="${timezone}" selected="selected">${timezone}</option>
|
||||||
|
% else:
|
||||||
|
<option value="${timezone}">${timezone}</option>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<div class="form-item">
|
||||||
|
<input type="submit" name="account-action" value="Save" class="form-button"/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -1,9 +1,9 @@
|
|||||||
<%inherit file="/base.mako"/>
|
<%inherit file="/base.mako"/>
|
||||||
<%include file="/flash.mako"/>
|
<%include file="/flash.mako"/>
|
||||||
<div class="post">
|
<div class="post">
|
||||||
<h2 class="title">New password</h2>
|
<h2 class="title">Change password</h2>
|
||||||
<%include file="/errors.mako"/>
|
<%include file="/errors.mako"/>
|
||||||
<form id="account-password" action="${h.url_for(controller=u'account', action=u'password', id=c.user.id)}" method="post">
|
<form id="account-password" action="${h.url_for(controller=u'account', action=u'password')}" method="post">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<div class="form-item">
|
<div class="form-item">
|
||||||
<label for="password-password">Password:</label>
|
<label for="password-password">Password:</label>
|
||||||
|
21
scribeengine/templates/account/resetpassword.mako
Normal file
21
scribeengine/templates/account/resetpassword.mako
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<%inherit file="/base.mako"/>
|
||||||
|
<%include file="/flash.mako"/>
|
||||||
|
<div class="post">
|
||||||
|
<h2 class="title">Reset password</h2>
|
||||||
|
<%include file="/errors.mako"/>
|
||||||
|
<form id="account-resetpassword" action="${h.url_for(controller=u'account', action=u'resetpassword', id=c.user.id)}" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="password-password">Password:</label>
|
||||||
|
<input type="password" name="password-password" id="password-password" class="form-text" />
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="password-confirm">Confirm password:</label>
|
||||||
|
<input type="password" name="password-confirm" id="password-confirm" class="form-text" />
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<input type="submit" name="password-action" value="Change password" class="form-button"/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -29,17 +29,10 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><a href="${h.url_for('/')}">Home</a></li>
|
<li><a href="${h.url_for('/')}">Home</a></li>
|
||||||
% for page in c.pages:
|
% for page in c.pages:
|
||||||
<li><a href="${page.url}">${page.name}</a></li>
|
<li><a href="${page.url}">${page.title}</a></li>
|
||||||
% endfor
|
% endfor
|
||||||
% if c.current_user:
|
% if c.current_user:
|
||||||
% if c.current_user.has_permission('Add Posts'):
|
|
||||||
<li><a href="${h.url_for(controller=u'post', action=u'new')}">New Post</a></li>
|
|
||||||
<li><a href="${h.url_for(controller=u'post', action=u'draft')}">Draft Posts</a></li>
|
|
||||||
% endif
|
|
||||||
<li><a href="${h.url_for(controller=u'account', action=u'logout')}">Logout</a></li>
|
|
||||||
<li>Logged in as <em>${c.current_user.nick}</em></li>
|
<li>Logged in as <em>${c.current_user.nick}</em></li>
|
||||||
% else:
|
|
||||||
<li><a href="${h.url_for(controller=u'account', action=u'login')}">Login</a></li>
|
|
||||||
% endif
|
% endif
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,7 @@ You have just reset your password on ${c.blog_title}, but before you continue,
|
|||||||
you will need to activate your account. You can do this by simply clicking on
|
you will need to activate your account. You can do this by simply clicking on
|
||||||
the link below, or copying and pasting it into your browser.
|
the link below, or copying and pasting it into your browser.
|
||||||
|
|
||||||
${c.blog_host}${h.url_for(controller=u'account', action=u'password', id=c.user.id, code=c.user.activation_key)}
|
${c.blog_host}${h.url_for(controller=u'account', action=u'resetpassword', id=c.user.id, code=c.user.activation_key)}
|
||||||
|
|
||||||
Kind regards,
|
Kind regards,
|
||||||
|
|
||||||
|
21
scribeengine/templates/page/new.mako
Normal file
21
scribeengine/templates/page/new.mako
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<%inherit file="/base.mako"/>
|
||||||
|
<%include file="/flash.mako"/>
|
||||||
|
<div class="page">
|
||||||
|
<h2 class="title">New Page</h2>
|
||||||
|
<%include file="/errors.mako"/>
|
||||||
|
<form id="page-new" action="${h.url_for('/page/edit')}" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<div class="form-item">
|
||||||
|
<!-- <label for="page-title">Title:</label> -->
|
||||||
|
<input type="text" name="page-title" id="page-title" class="form-text" />
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<!-- <label for="page-body">Body:</label> -->
|
||||||
|
<textarea name="page-body" id="page-body" class="form-textarea"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<input type="submit" name="page-action" value="Save" class="form-button"/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
8
scribeengine/templates/page/view.mako
Normal file
8
scribeengine/templates/page/view.mako
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<%inherit file="/base.mako"/>
|
||||||
|
<%include file="/flash.mako"/>
|
||||||
|
<div class="page">
|
||||||
|
<h2 class="title">${c.page.title}</h2>
|
||||||
|
<div class="entry">
|
||||||
|
${h.literal(c.page.body)}
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -25,6 +25,39 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
% endif
|
% endif
|
||||||
|
<li>
|
||||||
|
<h2>Meta</h2>
|
||||||
|
<ul>
|
||||||
|
% if c.current_user:
|
||||||
|
<li>
|
||||||
|
Account
|
||||||
|
<ul>
|
||||||
|
<li><a href="${h.url_for(controller=u'account')}">My Details</a></li>
|
||||||
|
<li><a href="${h.url_for(controller=u'account', action=u'password')}">My Password</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
% if c.current_user.has_permission([u'Add Posts', u'Add Pages', u'Edit My Posts', u'Edit My Pages']):
|
||||||
|
<li>
|
||||||
|
Content
|
||||||
|
<ul>
|
||||||
|
% if c.current_user.has_permission(u'Add Posts'):
|
||||||
|
<li><a href="${h.url_for(controller=u'post', action=u'new')}">New Post</a></li>
|
||||||
|
% endif
|
||||||
|
% if c.current_user.has_permission(u'Add Pages'):
|
||||||
|
<li><a href="${h.url_for(controller=u'page', action=u'new')}">New Page</a></li>
|
||||||
|
% endif
|
||||||
|
% if c.current_user.has_permission(u'Edit My Posts'):
|
||||||
|
<li><a href="${h.url_for(controller=u'post', action=u'draft')}">Draft Posts</a></li>
|
||||||
|
% endif
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
<li><a href="${h.url_for(controller=u'account', action=u'logout')}">Logout</a></li>
|
||||||
|
% else:
|
||||||
|
<li><a href="${h.url_for(controller=u'account', action=u'login')}">Login</a></li>
|
||||||
|
% endif
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div style="clear: both; height: 40px;"> </div>
|
<div style="clear: both; height: 40px;"> </div>
|
||||||
</div>
|
</div>
|
||||||
|
7
scribeengine/tests/functional/test_page.py
Normal file
7
scribeengine/tests/functional/test_page.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from scribeengine.tests import *
|
||||||
|
|
||||||
|
class TestPageController(TestController):
|
||||||
|
|
||||||
|
def test_index(self):
|
||||||
|
response = self.app.get(url(controller='page', action='index'))
|
||||||
|
# Test response...
|
4
setup.py
4
setup.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
try:
|
try:
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -28,7 +29,8 @@ setup(
|
|||||||
"Pylons==0.9.7",
|
"Pylons==0.9.7",
|
||||||
"SQLAlchemy>=0.5,<0.6",
|
"SQLAlchemy>=0.5,<0.6",
|
||||||
"TurboMail>=3.0,<3.1",
|
"TurboMail>=3.0,<3.1",
|
||||||
"MonthDelta>=0.9,<0.10"
|
"MonthDelta>=0.9,<0.10",
|
||||||
|
"pytz"
|
||||||
],
|
],
|
||||||
setup_requires=["PasteScript>=1.6.3"],
|
setup_requires=["PasteScript>=1.6.3"],
|
||||||
packages=find_packages(exclude=['ez_setup']),
|
packages=find_packages(exclude=['ez_setup']),
|
||||||
|
Reference in New Issue
Block a user