* Separated the global setup settings from those in the root site's preferences

* Added encoding="form" parameter to most of the macros using the request handler
 * Renamed commentsMode to commentMode (comments_mode to comment_mode in DB)
 * Reactivated notifications in a simplified manner
 * Throw an error in global sendMail() method if arguments are not sufficient
 * Added HopObject.notify() method
 * Added HopObject.kind_macro() method (provides the constructor's name in lowercase)
 * Added Messages.skin containing subskins suited for e-mail output
 * Removed obsolete skin files
 * Added reset_action() method for resetting a user's password to Members prototype
 * Added require() method to Membership prototype; wrapped static require() method around it
 * Added Membership.notify() method which does all the member-related notification stuff
 * Send notification on membership removal
 * Fixed contact form in Membership prototype
 * Dropped e-mail property from Site prototype (users can be contacted via Membership.contact_action(), Root prototype has extra e-mail property)
 * Added missing getPermission() method to User prototype, always requiring a privileged user
This commit is contained in:
Tobi Schäfer 2007-10-15 23:29:03 +00:00
parent 504260650e
commit 3e8c4c6313
34 changed files with 336 additions and 276 deletions

View file

@ -77,8 +77,8 @@ Admin.prototype.setup_action = function() {
};
Admin.prototype.update = function(data) {
root.update(data);
root.map({
email: data.email,
notificationScope: data.notificationScope,
quota: data.quota,
creationScope: data.creationScope,
@ -403,7 +403,6 @@ Admin.prototype.updateUser = function(data) {
};
Admin.prototype.renderItem = function(item) {
res.handlers.item = item;
var name = item._prototype;
(name === "Root") && (name = "Site");
Admin.prototype.renderSkin("Admin#" + name);

View file

@ -101,7 +101,7 @@ If this site is open it will replace the default front page.
</tr>
<tr>
<td>... search</td>
<td><input name="query" value="<% request.query %>" /></td>
<td><input name="query" value="<% request.query encoding="form" %>" /></td>
</tr>
<tr>
<td> </td>
@ -321,15 +321,6 @@ If this site is open it will replace the default front page.
<tr>
<td colspan="2"><strong>General</strong></td>
</tr>
<tr>
<td valign="top">Title:</td>
<td>
<% root.input title %><br />
<span class="small">
This is the main title of your Antville installation.
</span>
</td>
</tr>
<!-- tr>
<td valign="top">System URL:</td>
<td><%// root.sys_url as="editor" size="20" %><br />
@ -345,16 +336,6 @@ of this Antville installation will display the selected site instead of the
default front page.</span></td>
</tr -->
<tr>
<td valign="top">Layout:</td>
<td>
<% root.select layout %><br />
<span class="small">
Choose the layout to use for this Antville installation.
It will also be the default layout for any newly created site.
</span>
</td>
</tr>
<tr>
<td valign="top">e-mail:</td>
<td>
<% root.input email %><br />
@ -376,30 +357,6 @@ default front page.</span></td>
</td>
</tr>
<tr>
<td valign="top">Language:</td>
<td>
<% root.select language %><br />
<span class="small">
This defines the language of Antville's confirm and error messages.
If you select a language that Antville doesn't know, it will display all
messages in english. Whatever language you specify here will also be the
default for every new site created here.
</span>
</td>
</tr>
<tr>
<td>Time zone:</td>
<td><% root.select timeZone %></td>
</tr>
<tr>
<td>Long date format:</td>
<td><% root.select longDateFormat %></td>
</tr>
<tr>
<td>Short date format:</td>
<td><% root.select shortDateFormat %></td>
</tr>
<tr>
<td valign="top">Quota per site:</td>
<td>
<% root.input quota %> Kb<br />

View file

@ -50,7 +50,7 @@ Comment.prototype.getPermission = function(action) {
case ".":
case "main":
case "comment":
return this.site.commentsMode === Site.ENABLED &&
return this.site.commentMode === Site.ENABLED &&
this.story.getPermission(action) &&
this.status !== Comment.CLOSED &&
this.status !== Comment.PENDING;
@ -97,8 +97,8 @@ Comment.prototype.update = function(data) {
this.title = data.title;
this.text = data.text;
this.setContent(data);
if (this.site.commentsMode === Site.MODERATED ||
this.story.commentsMode === Site.MODERATED) {
if (this.site.commentMode === Site.MODERATED ||
this.story.commentMode === Site.MODERATED) {
this.mode = Comment.PENDING;
} else if (this.story.status === Story.PRIVATE &&
this.getDelta(data) > 50) {

View file

@ -46,6 +46,7 @@ Files.prototype.create_action = function() {
try {
file.update(req.postParams);
this.add(file);
file.notify(req.action);
res.message = gettext('The file was added successfully. Its name is "{0}"', file.name);
res.redirect(this.href());
} catch (ex) {

View file

@ -586,8 +586,7 @@ function injectXslDeclaration(xml) {
*/
function sendMail(sender, recipient, subject, body) {
if (!sender || !recipient || !body) {
app.log("Insufficient arguments in method sendMail()");
return;
throw Error("Insufficient arguments in method sendMail()");
}
var mail = new helma.Mail();
mail.setFrom(sender);

View file

@ -71,6 +71,10 @@ HopObject.prototype.onRequest = function() {
return;
};
HopObject.prototype.getPermission = function() {
return true;
};
HopObject.prototype.delete_action = function() {
if (req.postParams.proceed) {
//try {
@ -121,8 +125,25 @@ HopObject.prototype.touch = function() {
});
};
HopObject.prototype.getPermission = function() {
return true;
HopObject.prototype.notify = function(action) {
var site = res.handlers.site;
if (site.notificationMode === Site.NOBODY) {
return;
}
switch (action) {
case "comment":
action = "create"; break;
}
var membership;
for (var i=0; i<site.members.size(); i+=1) {
membership = site.members.get(i);
if (membership.require(site.notificationMode)) {
sendMail(root.email, membership.creator.email,
gettext("Notification of changes at site {0}", site.title),
this.renderSkinAsString("Messages#" + action));
}
}
return;
};
HopObject.prototype.input_macro = function(param, name) {
@ -214,6 +235,16 @@ HopObject.prototype.macro_macro = function(param, handler) {
return;
};
HopObject.prototype.kind_macro = function() {
var type = this.constructor.name.toLowerCase();
switch (type) {
default:
res.write(gettext(type));
break;
}
return;
};
HopObject.prototype.getFormValue = function(name) {
if (req.isPost()) {
return req.postParams[name];

View file

@ -0,0 +1,20 @@
<% #create %>
<% gettext 'Dear {0},
this message wants to inform you that a new {1} was published at {2} by user {3} on {4}.
Best regards.
The Management'
<% membership.name %> <% this.kind %> <% this.href %>
<% this.modifier %> <% this.modified short %> %>
<% #edit %>
<% gettext 'Dear {0},
this message wants to inform you that the {1} at {2} was modified by user {3} on {4}.
Best regards.
The Management'
<% membership.name %> <% this.kind %> <% this.href %>
<% this.modifier %> <% this.modified short %> %>

View file

@ -61,6 +61,7 @@ Images.prototype.create_action = function() {
try {
image.update(req.postParams);
this.add(image);
image.notify(req.action);
res.message = gettext('The uploaded image was saved successfully. Its name is "{0}"',
image.name);
session.data.referrer = null;

View file

@ -29,8 +29,9 @@ Members.prototype.getPermission = function(action) {
switch (action) {
case "login":
case "logout":
case "salt.js":
case "register":
case "reset":
case "salt.js":
return true;
case ".":
case "main":
@ -74,18 +75,12 @@ Members.prototype.main_action = function() {
Members.prototype.register_action = function() {
if (req.postParams.register) {
try {
var user = User.register(req.postParams);
// Subscribe user to this site if it is public
if (Site.require(Site.PUBLIC)) {
this.add(new Membership(user));
}
var title = res.handlers.site.title;
if (root.sys_email) {
var sp = {name: user.name};
sendMail(root.sys_email, user.email,
gettext('Welcome to "{0}"!', title),
this.renderSkinAsString("mailregconfirm", sp));
}
var user = User.register(req.postParams);
var membership = new Membership(user);
this.add(membership);
membership.notify(req.action, user.email,
gettext('Welcome to "{0}"!', title));
var url = session.data.referrer || this._parent.href();
delete session.data.referrer;
res.message = gettext('Welcome to "{0}", {1}. Have fun!',
@ -105,6 +100,36 @@ Members.prototype.register_action = function() {
return;
};
Members.prototype.reset_action = function() {
if (req.postParams.reset) {
try {
if (!req.postParams.name || !req.postParams.email) {
throw Error(gettext("Please enter username and e-mail of the desired account."));
}
var user = User.getByName(req.postParams.name);
if (!user || user.email !== req.postParams.email) {
throw Error(gettext("Username and e-mail do not match."))
}
var password = jala.util.createPassword(25, 2);
user.hash = (password + user.salt).md5()
sendMail(root.email, user.email,
gettext("Your login at {0}", this._parent.title),
user.renderSkinAsString("Messages#reset",
{password: password}));
res.message = "A new password is sent to the account's e-mail address.";
res.redirect(this._parent.href());
} catch(ex) {
app.log(ex);
res.message = ex;
}
}
res.data.action = this.href(req.action);
res.data.title = gettext("Reset password");
res.data.body = this.renderSkinAsString("Members#reset");
this._parent.renderSkin("page");
return;
};
Members.prototype.login_action = function() {
if (req.postParams.login) {
try {
@ -264,16 +289,10 @@ Members.prototype.add_action = function() {
}
} else if (req.postParams.add) {
try {
res.handlers.sender = User.getMembership();
var membership = this.addMembership(req.postParams);
var message = this.renderSkinAsString("mailnewmember", {
site: res.handlers.site.title,
creator: session.user.name,
url: res.handlers.site.href(),
account: req.postParams.name
});
// FIXME:
//sendMail(root.sys_email, result.obj.user.email,
// getMessage("mail.newMember", result.obj.site.title), message);
membership.notify(req.action, membership.creator.email,
gettext('Notification of membership change', root.title));
res.message = gettext("Successfully added {0} to the list of members.",
req.postParams.name);
res.redirect(membership.href("edit"));

View file

@ -1,6 +1,6 @@
<% #main %>
<div class="ample">
<% members.link add "add a member" prefix="...&nbsp;" %>
<% members.link add "add a member" prefix="..." %>
</div>
<% members.link . all prefix="... show " %>
<% members.link owners prefix="| " %>
@ -37,26 +37,26 @@ $(function() {
<table border="0" cellspacing="0" cellpadding="3">
<tr>
<td class="small">Username:</td>
<td nowrap="nowrap">
<td>
<input type="text" name="name" id="name" size="15" tabindex="1"
value="<% request.name %>" />
value="<% request.name encoding="form" %>" />
</td>
<td rowspan="4" nowrap="nowrap"> </td>
<td rowspan="4"> </td>
<td class="small">
<% members.link register "Not registered yet" %>
</td>
</tr>
<tr>
<td class="small" nowrap="nowrap">Password:</td>
<td class="small">Password:</td>
<td>
<input type="password" name="password" id="password" size="15" tabindex="2" />
</td>
<td class="small">
<% members.link sendpwd "Forgot your password?" %>
<% members.link reset "Password forgotten?" %>
</td>
</tr>
<tr>
<td nowrap="nowrap"> </td>
<td> </td>
<td colspan="2" class="small">
<input type="checkbox" id="remember" name="remember" tabindex="3"
<% if <% request.remember %> is "on" then 'checked="checked"' %> />
@ -64,7 +64,7 @@ value="<% request.name %>" />
</td>
</tr>
<tr>
<td nowrap="nowrap"> </td>
<td> </td>
<td colspan="2"><br />
<button type="submit" id="submit" name="login" value="1"
tabindex="4">login</button>
@ -99,32 +99,32 @@ $(function() {
<input type="hidden" name="hash" id="hash" />
<table border="0" cellspacing="0" cellpadding="3">
<tr>
<td class="small" nowrap="nowrap">Username:</td>
<td nowrap="nowrap">
<input type="text" name="name" value="<% request.name %>" />
</td>
</tr>
<tr>
<td class="small" valign="top" nowrap="nowrap">e-mail:</td>
<td class="small">Username:</td>
<td>
<input type="text" name="email" value="<% request.email %>" />
<input type="text" name="name" value="<% request.name encoding="form" %>" />
</td>
</tr>
<tr>
<td class="small" nowrap="nowrap">Password:</td>
<td nowrap="nowrap">
<td class="small" valign="top">e-mail:</td>
<td>
<input type="text" name="email" value="<% request.email encoding="form" %>" />
</td>
</tr>
<tr>
<td class="small">Password:</td>
<td>
<input type="password" name="password" id="password" />
</td>
</tr>
<tr>
<td class="small" nowrap="nowrap">Confirm password:</td>
<td nowrap="nowrap">
<td class="small">Confirm password:</td>
<td>
<input type="password" name="passwordConfirm" id="passwordConfirm" />
</td>
</tr>
<tr>
<td nowrap="nowrap">&nbsp;</td>
<td nowrap="nowrap"><br />
<td></td>
<td><br />
<button type="submit" id="submit" name="register"
value="register">Register</button>
<button type="submit" name="cancel" value="cancel">Cancel</button>
@ -133,14 +133,28 @@ value="register">Register</button>
</table>
</form>
<% #reset %>
<form id="login" method="post" action="<% response.action %>">
<div class="small">Username:</div>
<div><input type="text" name="name" id="name" size="15" tabindex="1"
value="<% request.name encoding="form" %>" /></div>
<div class="small">e-mail:</div>
<div><input type="text" name="email" id="email" size="15" tabindex="2"
value="<% request.email encoding="form" %>"/></div>
<br />
<button type="submit" id="submit" name="reset" value="1"
tabindex="4">reset</button>
</form>
<% #add %>
<form method="post" action="<% response.action %>">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td nowrap="nowrap">
<input type="text" name="term" id="term" value="<% request.term %>" />
<td>
<input type="text" name="term" id="term"
value="<% request.term encoding="form" %>" />
</td>
<td nowrap="nowrap">
<td>
<button type="submit" name="search" value="1">Search</button>
</td>
</tr>

View file

@ -1,7 +0,0 @@
<% param.creator %> has added you (meaning your account "<% param.account %>") to the list of members of <% param.site %> (<% param.url %>).
Have fun!
---------------------------------------
<% root.title %> - <% root.url %>
---------------------------------------

View file

@ -1,9 +0,0 @@
On <% now format="long" %> you requested a list of all your accounts for '<% root.title %>', so here it is:
<% param.text %>
Have fun!
---------------------------------------
<% root.title %> - <% root.url %>
---------------------------------------

View file

@ -1,12 +0,0 @@
Welcome to <% root.title %>!
Here's your login info:
Username: <% param.name %>
Password: <% param.password %>
Have fun!
---------------------------------------
<% root.title %> - <% root.url %>
---------------------------------------

View file

@ -1,14 +0,0 @@
<p>Please enter the e-mail address you most likely used back then when you registered yourself here. An e-mail containing all accounts that were registered with this e-mail address will be sent back to this address.</p>
<form method="post" action="<% response.action %>">
<table border="0" cellspacing="0" cellpadding="3">
<tr>
<td class="small" nowrap="nowrap">e-mail:</td>
<td nowrap="nowrap"><% input type="text" name="email" %></td>
</tr>
<tr>
<td nowrap="nowrap">&nbsp;</td>
<td nowrap="nowrap"><% input type="submit" name="send" value="Send" %>&nbsp;<% input type="submit" name="cancel" value="Cancel" %></td>
</tr>
</table>
</form>

View file

@ -40,6 +40,7 @@ Membership.prototype.constructor = function(user, role) {
Membership.prototype.getPermission = function(action) {
switch (action) {
case "contact":
case "edit":
return this.creator !== session.user;
case "delete":
@ -64,7 +65,7 @@ Membership.prototype.edit_action = function() {
res.data.action = this.href(req.action);
res.data.title = gettext("Edit membership: {0}", this.name);
res.data.body = this.renderSkinAsString("edit");
res.data.body = this.renderSkinAsString("Membership#edit");
this.site.renderSkin("page");
return;
};
@ -85,9 +86,8 @@ Membership.prototype.update = function(data) {
} else if (data.role !== this.role) {
this.role = data.role;
this.touch();
/* FIXME: sendMail(root.sys_email, this.user.email,
getMessage("mail.statusChange", this.site.title),
this.renderSkinAsString("mailstatuschange"));*/
this.notify(req.action, this.creator.email,
gettext("Notification of membership change"));
}
return;
};
@ -98,11 +98,10 @@ Membership.prototype.contact_action = function() {
if (!req.postParams.text) {
throw Error(gettext("Please enter the message text."));
}
var body = this.renderSkinAsString("mailmessage",
{text: req.postParams.text});
sendMail(session.user.email, this.creator.email,
gettext("Message from a {0} user", root.sys_title), body);
res.message = new Message("mailSend");
this.notify(req.action, this.creator.email,
gettext('Message from user {0} of {1}',
session.user.name, root.title));
res.message = gettext("Your message was sent successfully.");
res.redirect(this._parent.href());
} catch(ex) {
res.message = ex;
@ -111,12 +110,27 @@ Membership.prototype.contact_action = function() {
}
res.data.action = this.href(req.action);
res.data.title = gettext("Send e-mail to {0}", this.username);
res.data.body = this.renderSkinAsString("mailto");
res.data.title = gettext('Contact user "{0}"', this.name);
res.data.body = this.renderSkinAsString("Membership#contact");
this.site.renderSkin("page");
return;
};
Membership.prototype.notify = function(action, recipient, subject) {
switch (action) {
case "add":
case "contact":
case "delete":
case "edit":
case "register":
default:
res.handlers.sender = User.getMembership();
sendMail(root.email, recipient, subject,
this.renderSkinAsString("Messages#" + action));
}
return;
};
Membership.prototype.getMacroHandler = function(name) {
switch (name) {
case "creator":
@ -147,22 +161,32 @@ Membership.getByName = function(name) {
return null;
};
Membership.require = function(role) {
Membership.prototype.require = function(role) {
var roles = [Membership.SUBSCRIBER, Membership.CONTRIBUTOR,
Membership.MANAGER, Membership.OWNER];
if (role && res.handlers.membership) {
return roles.indexOf(res.handlers.membership.role) >= roles.indexOf(role);
if (role) {
return roles.indexOf(this.role) >= roles.indexOf(role);
}
return false;
};
Membership.require = function(role) {
if (res.handlers.membership) {
return res.handlers.membership.require(role);
}
return false;
};
Membership.remove = function(membership) {
/*if (!membership) {
throw Error(gettext("Please specify a membership you want to be removed."));
} else if (membership.role === Membership.OWNER) {
throw Error(gettext("Sorry, an owner of a site cannot be removed."));
}*/
membership.remove();
if (membership && membership.constructor === Membership) {
if (!this.getPermission("delete")) {
throw Error(gettext("Sorry, an owner of a site cannot be removed."));
}
var recipient = membership.creator.email;
membership.remove();
this.notify(req.action, recipient,
gettext("Notification of membership cancellation"));
}
return;
};

View file

@ -54,10 +54,28 @@ Logged in as <% membership.name | membership.link %><br />
</tr>
</table>
<% #contact %>
<p>Please enter your message to user "<% membership.name %>" below.
To prevent abuse the sender address and the subject of the e-mail are
predefined. A generic disclaimer will be appended to your text.
Please make sure your own e-mail address in your
<% members.link edit profile %> is up-to-date.</p>
<form method="post" action="<% response.action %>">
<p>
<span class="small">Message:</span><br />
<textarea cols="31" rows="10" class="formText" wrap="virtual"
name="text"><% request.text encoding="form" %></textarea>
</p>
<p>
<button type="submit" name="send" value="1">send</button>
<button type="submit" name="cancel" value="1">cancel</button>
</p>
</form>
<% #edit %>
<p>To change the status of this member, simply choose from the dropdown menu
and click the "Save" button. An e-mail will be sent to the member telling
him/her that you changed the member's role.</p>
<p>To modify the membership, simply choose the desired role from the
drop-down menu and click the "save" button. An e-mail will be sent to the
member informing about the membership change.</p>
<form method="post" action="<% response.action %>">
<table border="0" cellspacing="0" cellpadding="3">
<tr>
@ -71,8 +89,8 @@ him/her that you changed the member's role.</p>
<tr>
<td nowrap="nowrap"> </td>
<td nowrap="nowrap"><br />
<button type="submit" name="save" value="1"><strong>Save</strong></button>
<button type="submit" name="cancel" value="1">Cancel</button>
<button type="submit" name="save" value="1"><strong>save</strong></button>
<button type="submit" name="cancel" value="1">cancel</button>
</td>
</tr>
</table>

View file

@ -0,0 +1,54 @@
<% #contact %>
<% request.text %>
<% gettext
'This message was sent to you by the user "{1}" of the site "{2}" at {3}.
PLEASE DO NOT REPLY TO THIS E-MAIL simply by hitting the "reply" button.
If the user did not include contact data in the message anyway, you can use
the contact form at {4}.'
<% membership.name %> <% sender.name %> <% site.title %>
<% site.href %> <% sender.href contact %> %>
<% #register %>
Welcome to <% root.title %>, <% membership.name %>!
You can edit your profile and change your password at any time.
Just point your browser to <% members.href edit %>.
Have fun!
The Management
<% #add %>
<% gettext 'Dear {0},
the user "{1}" of the site "{2}" at {3} has added your account to the list of members of the site.
Have fun!
The Management'
<% membership.name %> <% sender.name %> <% site.title %> <% site.href %> %>
<% #edit %>
<% gettext 'Dear {0},
the user "{1}" of the site "{2}" at {3} has modified your membership. You are now {4} of the site.
Best regards.
The Management'
<% membership.name %> <% sender.name %> <% site.title %> <% site.href %>
<% gettext <% membership.role %> %> %>
<% #delete %>
<% gettext 'Dear {0},
we are sorry to inform you that the user "{1}" of the site "{2}" at {3} has cancelled your membership.
Best regards.
The Management'
<% membership.name %> <% sender.name %> <% site.title %> <% site.href %>
<% gettext <% membership.role %> %> %>

View file

@ -1,22 +0,0 @@
<p>To change the status of this member, simply choose from the dropdown menu
and click the "Save" button. An e-mail will be sent to the member telling
him/her that you changed the member's role.</p>
<form method="post" action="<% response.action %>">
<table border="0" cellspacing="0" cellpadding="3">
<tr>
<td class="small" nowrap="nowrap">User:</td>
<td nowrap="nowrap"><% membership.name %></td>
</tr>
<tr>
<td class="small" nowrap="nowrap">Role:</td>
<td nowrap="nowrap"><% membership.select role %></td>
</tr>
<tr>
<td nowrap="nowrap"> </td>
<td nowrap="nowrap"><br />
<button type="submit" name="save" value="1"><strong>Save</strong></button>
<button type="submit" name="cancel" value="1">Cancel</button>
</td>
</tr>
</table>
</form>

View file

@ -1,7 +0,0 @@
<% membership.username %>, one of the administrators of '<% site.title %>' (URL: <% site.url %>), sent you the following message:
<% param.text %>
---------------------------------------
<% root.title %> - <% root.url %>
---------------------------------------

View file

@ -1,9 +0,0 @@
The status of your account '<% membership.username %>' as a member of '<% site.title %>' (<% site.url %>) has changed: You are now
<% membership.level %>
Have fun!
---------------------------------------
<% root.title %> - <% root.url %>
---------------------------------------

View file

@ -1,7 +0,0 @@
<p>Please enter your message to <% membership.username %> below. To prevent misuse the subject of the e-mail is predefined and an additional explanation will be appended to your message. Please make sure your own e-mail address in your <% members.link to="edit" text="profile" %> is correct.</p>
<form method="post" action="<% response.action %>">
<p><span class="small">Message:</span><br />
<textarea cols="31" rows="10" class="formText" wrap="virtual" name="text"><% request.text %></textarea></p>
<p><% input type="submit" name="send" value="Send" %>&nbsp;<% input type="submit" name="cancel" value="Cancel" %></p>
</form>

View file

@ -58,6 +58,7 @@ Polls.prototype.create_action = function() {
try {
poll.update(req.postParams);
this.add(poll);
poll.notify(req.action);
res.message = gettext("The poll was created successfully.");
res.redirect(poll.href());
} catch (err) {

View file

@ -25,15 +25,18 @@
Site.getStatus = defineConstants(Site, "blocked", "regular", "trusted");
Site.getModes = defineConstants(Site, "closed", "restricted", "public", "open");
Site.getPageModes = defineConstants(Site, "days", "stories");
Site.getCommentsModes = defineConstants(Site, "disabled", "enabled");
Site.getCommentModes = defineConstants(Site, "disabled", "enabled");
Site.getArchiveModes = defineConstants(Site, "closed", "public");
Site.getNotificationModes = defineConstants(Site, "Nobody",
"Owner", "Manager", "Contributor", "Subscriber" );
this.handleMetadata("archiveMode");
this.handleMetadata("commentsMode");
this.handleMetadata("commentMode");
this.handleMetadata("email");
this.handleMetadata("language");
this.handleMetadata("lastUpdate");
this.handleMetadata("longDateFormat");
this.handleMetadata("notificationMode");
this.handleMetadata("notifiedOfBlocking");
this.handleMetadata("notifiedOfDeletion");
this.handleMetadata("offlineSince");
@ -63,8 +66,9 @@ Site.prototype.constructor = function(name, title) {
mode: Site.CLOSED,
tagline: "",
webHookEnabled: false,
commentsMode: Site.OPEN,
commentMode: Site.OPEN,
archiveMode: Site.PUBLIC,
notificationMode: Site.DISABLED,
pageMode: Site.DAYS,
pageSize: 3,
language: locale.getLanguage(),
@ -151,32 +155,32 @@ Site.prototype.edit_action = function() {
};
Site.prototype.getFormOptions = function(name) {
var options = [];
switch (name) {
case "archiveMode":
options = Site.getArchiveModes(); break;
case "commentsMode":
options = Site.getCommentsModes(); break;
return Site.getArchiveModes();
case "commentMode":
return Site.getCommentModes();
case "language":
options = getLocales(); break;
return getLocales();
case "layout":
options = this.getLayouts(); break;
return this.getLayouts();
case "longDateFormat":
options = getDateFormats("long"); break;
return getDateFormats("long");
case "mode":
options = Site.getModes(); break;
return Site.getModes();
case "notificationMode":
return Site.getNotificationModes();
case "pageMode":
options = Site.getPageModes(); break;
return Site.getPageModes();
case "status":
options = Site.getStatus(); break;
return Site.getStatus();
case "shortDateFormat":
options = getDateFormats("short"); break;
return getDateFormats("short");
case "timeZone":
options = getTimeZones(); break;
return getTimeZones();
default:
return HopObject.prototype.getFormOptions.apply(this, arguments);
}
return options;
};
Site.prototype.update = function(data) {
@ -204,8 +208,9 @@ Site.prototype.update = function(data) {
webHookEnabled: data.webHookEnabled ? true : false,
pageMode: data.pageMode || Site.DAYS,
pageSize: parseInt(data.pageSize, 10) || 3,
commentsMode: data.commentsMode || Site.DISABLED,
commentMode: data.commentMode || Site.DISABLED,
archiveMode: data.archiveMode || Site.CLOSED,
notificationMode: data.notificationMode || Site.DISABLED,
timeZone: data.timeZone,
longDateFormat: data.longDateFormat,
shortDateFormat: data.shortDateFormat,

View file

@ -68,8 +68,8 @@ You can change it anytime you want.</p>
</tr>
<tr>
<td class="small">Comments:</td>
<td><% site.checkbox commentsMode %>
<label for="commentsMode">enabled</label></td>
<td><% site.checkbox commentMode %>
<label for="commentMode">enabled</label></td>
</tr>
<tr>
<td class="small">Archive:</td>
@ -93,12 +93,9 @@ You can change it anytime you want.</p>
<td><% site.select shortDateFormat %></td>
</tr>
<tr>
<!-- FIXME: should site.email be dropped? afaik,
bounces should be sent to sys.email? [tobi] -->
<td class="small" valign="top">e-mail address:</td>
<td><% site.input email %><br />
<span class="small">This e-mail address will be used for sending confirmation
mails, i.e. when a user registers or signs up a site.</span></td>
<td class="small">Notifications:</td>
<td><% site.select notificationMode %></td>
</td>
</tr>
<tr>
<td class="small" valign="top">Web hook:</td>
@ -113,22 +110,9 @@ mails, i.e. when a user registers or signs up a site.</span></td>
<% link layouts "Go to the layouts page" %> to browse, manage or
test-drive the list of available layouts.</span></td>
</tr>
<!--tr>
<td colspan="2"><div class="listSeparator">&nbsp;</div>
<strong><a name="index">Index Maintenance</a></strong></td>
</tr>
<tr>
<td></td>
<td><span class="small">If the search index of your site is corrupt you can
schedule it for rebuilding by klicking on the button below:
<% input type="submit" name="rebuildIndex" value="rebuild index"
style="display:block;margin:5px 0;" %>Please bear in mind that rebuilding the
search index is a quite ressource-intensive operation, so please use this
feature only when it's really necessary (e.g. if you receive an error when
trying to search).</span></td>
</tr>
<tr>
<td colspan="2"><div class="listSeparator">&nbsp;</div>
<strong><a name="spamfilter">Referrer spam filter</a></strong></td>
</tr>
<tr>
@ -139,7 +123,6 @@ per line to be applied on every URL in the referrer and backlink lists.</td>
as="editor" cols="30" rows="7" %></td>
</tr-->
<% site.notification %>
<% site.modulePreferences %>
<tr>

View file

@ -1,11 +1,12 @@
<form action="<% response.action %>" method="get">
<input type="text" name="filter" value="<% request.filter %>" size="30" />
<input type="text" name="filter" value="<% request.filter encoding="form" %>"
size="30" />
<input type="submit" name="submit" value="Filter" />
<input type="button" onclick="document.location='<% site.href
action="referrers" %>';" value="Reset" />
<div class="small">
<input type="checkbox" name="includeSpam" value="checked"
<% request.includeSpam prefix='checked="' suffix='"' %> />
<% request.includeSpam prefix='checked="' suffix='"' encoding="form" %> />
include referrer spam
</div>
<br />

View file

@ -64,6 +64,7 @@ Stories.prototype.create_action = function() {
try {
story.update(req.postParams);
this.add(story);
story.notify(req.action);
res.message = gettext("The story was successfully created.");
res.redirect(story.href());
} catch (ex) {

View file

@ -24,7 +24,7 @@
Story.getStatus = defineConstants(Story, "closed", "public", "shared", "open");
Story.getModes = defineConstants(Story, "hidden", "featured");
Story.getCommentsModes = defineConstants(Story, "closed",
Story.getCommentModes = defineConstants(Story, "closed",
"readonly", "moderated", "open");
this.handleMetadata("title");
@ -50,9 +50,9 @@ Story.prototype.getPermission = function(action) {
this.status !== Story.CLOSED ||
User.require(User.PRIVILEGED);
case "comment":
return this.site.commentsMode === Site.ENABLED &&
this.commentsMode === Story.OPEN ||
this.commentsMode === Story.MODERATED;
return this.site.commentMode === Site.ENABLED &&
this.commentMode === Story.OPEN ||
this.commentMode === Story.MODERATED;
case "delete":
return this.creator === session.user ||
Membership.require(Membership.MANAGER) ||
@ -116,6 +116,7 @@ Story.prototype.edit_action = function() {
if (req.postParams.save) {
//try {
this.update(req.postParams);
this.notify(req.action);
res.message = gettext("The story was successfully updated.");
res.redirect(this.href());
//} catch (ex) {
@ -136,8 +137,8 @@ Story.prototype.getFormValue = function(name) {
return req.postParams[name];
}
switch (name) {
case "commentsMode":
return this.commentsMode || Story.OPEN;
case "commentMode":
return this.commentMode || Story.OPEN;
case "mode":
return this.mode || Story.FEATURED;
case "status":
@ -154,8 +155,8 @@ Story.prototype.getFormOptions = function(name) {
return Story.getModes();
case "status":
return Story.getStatus();
case "commentsMode":
return Story.getCommentsModes();
case "commentMode":
return Story.getCommentModes();
}
return;
}
@ -182,7 +183,7 @@ Story.prototype.update = function(data) {
this.text = data.text;
this.setContent(data);
//this.setTags(data.tags || data.tag_array)
this.commentsMode = data.commentsMode;
this.commentMode = data.commentMode;
this.mode = data.mode;
if (this.status === Story.PRIVATE && data.status !== Story.PRIVATE) {
if (delta > 50) {
@ -191,9 +192,7 @@ Story.prototype.update = function(data) {
}
this.status = data.status;
this.touch();
// FIXME: send e-mail notification
if (false && site.isNotificationEnabled() && newStatus != 0) {
/* if (false && site.isNotificationEnabled() && newStatus != 0) {
// status changes from offline to online
// (this is bad because somebody could send a bunch
// of e-mails simply by toggling the online status.)
@ -202,7 +201,7 @@ Story.prototype.update = function(data) {
// major update of an already online story
if (this.online != 0 && content.isMajorUpdate)
site.sendNotification("update", this);
}
} */
return;
};
@ -251,6 +250,7 @@ Story.prototype.comment_action = function() {
this.add(comment);
// Force addition to aggressively cached subcollection
(this.story || this).comments.add(comment);
comment.notify(req.action);
res.message = gettext("The comment was successfully created.");
res.redirect(comment.href());
} catch (ex) {
@ -300,8 +300,8 @@ Story.prototype.summary_macro = function(param) {
Story.prototype.comments_macro = function(param, mode) {
var story = this.story || this;
if (story.site.commentsMode === Site.DISABLED ||
story.commentsMode === Site.CLOSED) {
if (story.site.commentMode === Site.DISABLED ||
story.commentMode === Site.CLOSED) {
return;
} else if (mode) {
var n = this.comments.size() || 0;

View file

@ -32,7 +32,7 @@ prototype
name
status
mode
commentsMode = comments_mode
commentMode = comment_mode
created
modified

View file

@ -177,7 +177,7 @@ for (var i in referrers) {
<legend class="small">Options</legend>
<p>Tags: <% story.input tags %></p>
<p>The story is <% story.select status %> and <% story.select mode %></p>
<p>Comments of the story are <% story.select commentsMode %></p>
<p>Comments of the story are <% story.select commentMode %></p>
</fieldset></p>
<p class="small">
<% story.creator prefix="Created by " %>

View file

@ -8,7 +8,7 @@
<% #item %>
<li>
<a href="<% tag.href action=<% request.action %> %>"><% tag.name %></a>
<a href="<% tag.href action=<% request.action encoding="form" %> %>"><% tag.name %></a>
</li>
<% #admin %>

15
code/User/Messages.skin Normal file
View file

@ -0,0 +1,15 @@
<% #reset %>
<% gettext 'Dear {0},
You (or someone pretending to be you) requested to reset the password of your
account for the site {1} at {2}.
Below you find a new password that temporarily will give you access to the site.
Please change the password immediately after your next login.
Your temporary password: {3}
Best regards.
The Management'
<% user.name %> <% site.title %> <% site.href %> <% param.password %> %>

View file

@ -53,6 +53,10 @@ User.prototype.constructor = function(data) {
return this;
};
User.prototype.getPermission = function(action) {
return User.require(User.PRIVILEGED);
};
User.prototype.update = function(data) {
if (!data.digest && data.password) {
data.digest = ((data.password + this.salt).md5() +
@ -147,7 +151,7 @@ User.register = function(data) {
if (!data.email) {
throw new Error(gettext("Please enter your e-mail address."));
}
evalEmail(data.email);
validateEmail(data.email);
// Create hash from password for JavaScript-disabled browsers
if (!data.hash) {

View file

@ -140,7 +140,7 @@ var convert = function(type) {
metadata.pageMode = "days";
metadata.timeZone = metadata.timezone || "CET";
metadata.archiveMode = metadata.archive ? "online" : "offline";
metadata.commentsMode = metadata.discussions ? "enabled" : "disabled";
metadata.commentMode = metadata.discussions ? "enabled" : "disabled";
metadata.shortDateFormat = metadata.shortdateformat;
metadata.longDateFormat = metadata.longdateformat;
metadata.offlineSince = rows.getColumnItem("site_lastoffline");

View file

@ -214,9 +214,9 @@ alter table av_text add column mode enum('hidden','featured');
update av_text set mode = 'hidden' where text_isonline = 1;
update av_text set mode = 'featured' where text_isonline = 2;
alter table av_text add column comments_mode enum('closed','readonly','moderated','open');
update av_text set comments_mode = 'closed';
update av_text set comments_mode = 'open' where text_hasdiscussions = 1;
alter table av_text add column comment_mode enum('closed','readonly','moderated','open');
update av_text set comment_mode = 'closed';
update av_text set comment_mode = 'open' where text_hasdiscussions = 1;
alter table av_text change column text_id id mediumint(10);
alter table av_text change column text_alias name varchar(255);