Base code for campaigns and users

master
Sven Slootweg 11 years ago
parent 17f7ea929c
commit 6f94521d51

@ -20,6 +20,8 @@
"port": 11211
},
"class_map": {
"user": "User",
"campaign": "Campaign"
},
"components": [
"router",

@ -0,0 +1,55 @@
<?php
/*
* ReDonate is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
if(!isset($_APP)) { die("Unauthorized."); }
class Campaign extends CPHPDatabaseRecordClass
{
public $table_name = "campaigns";
public $fill_query = "SELECT * FROM campaigns WHERE `Id` = :Id";
public $verify_query = "SELECT * FROM campaigns WHERE `Id` = :Id";
public $prototype = array(
'string' => array(
'Name' => "Name",
'UrlName' => "UrlName"
),
'numeric' => array(
'OwnerId' => "UserId"
),
'boolean' => array(
'AllowOneTime' => "AllowOneTime"
),
'user' => array(
'Owner' => "Owner"
)
);
public static function CheckIfUrlNameExists($urlname)
{
try
{
$result = Campaign::FindByUrlName($urlname);
return true;
}
catch (NotFoundException $e)
{
return false;
}
}
public static function FindByUrlName($urlname)
{
return self::CreateFromQuery("SELECT * FROM campaigns WHERE `UrlName` = :UrlName", array(':UrlName' => $urlname), 0, true);
}
}

@ -0,0 +1,155 @@
<?php
/*
* Cryto Team is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
if(!isset($_APP)) { die("Unauthorized."); }
class User extends CPHPDatabaseRecordClass
{
public $table_name = "users";
public $fill_query = "SELECT * FROM users WHERE `Id` = :Id";
public $verify_query = "SELECT * FROM users WHERE `Id` = :Id";
public $prototype = array(
'string' => array(
'Username' => "Username",
'DisplayName' => "DisplayName",
'EmailAddress' => "EmailAddress",
'Hash' => "Hash",
'Salt' => "Salt",
'ActivationKey' => "ActivationKey"
),
'boolean' => array(
'IsAdmin' => "Admin",
'IsActivated' => "Activated"
)
);
public function GenerateSalt()
{
$this->uSalt = random_string(10);
}
public function GenerateHash()
{
if(!empty($this->uSalt))
{
if(!empty($this->uPassword))
{
$this->uHash = $this->CreateHash($this->uPassword);
}
else
{
throw new Exception("User object is missing a password.");
}
}
else
{
throw new Exception("User object is missing a salt.");
}
}
public function CreateHash($input)
{
global $cphp_config;
$hash = crypt($input, "$5\$rounds=50000\${$this->uSalt}{$cphp_config->salt}$");
$parts = explode("$", $hash);
return $parts[4];
}
public function VerifyPassword($password)
{
if($this->CreateHash($password) == $this->sHash)
{
return true;
}
else
{
return false;
}
}
public function Authenticate()
{
$_SESSION['user_id'] = $this->sId;
$_SESSION['logout_key'] = random_string(32);
$_SESSION['is_admin'] = $this->sIsAdmin;
NewTemplater::SetGlobalVariable("logged-in", true);
$this->SetGlobalVariables();
}
public function SetGlobalVariables()
{
NewTemplater::SetGlobalVariable("my-displayname", $this->sDisplayName);
}
public static function CheckIfEmailValid($email)
{
return preg_match("/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}$/i", $email);
}
public static function CheckIfEmailExists($email)
{
try
{
$result = User::FindByEmail($email);
return true;
}
catch (NotFoundException $e)
{
return false;
}
}
public static function CheckIfUsernameExists($username)
{
try
{
$result = User::FindByUsername($username);
return true;
}
catch (NotFoundException $e)
{
return false;
}
}
public static function CheckIfDisplayNameExists($displayname)
{
try
{
$result = User::FindByDisplayName($displayname);
return true;
}
catch (NotFoundException $e)
{
return false;
}
}
public static function FindByEmail($email)
{
return self::CreateFromQuery("SELECT * FROM users WHERE `EmailAddress` = :EmailAddress", array(':EmailAddress' => $email), 0);
}
public static function FindByUsername($username)
{
return self::CreateFromQuery("SELECT * FROM users WHERE `Username` = :Username", array(':Username' => $username), 0);
}
public static function FindByDisplayName($displayname)
{
return self::CreateFromQuery("SELECT * FROM users WHERE `DisplayName` = :DisplayName", array(':DisplayName' => $displayname), 0);
}
}

@ -11,17 +11,4 @@
* licensing text.
*/
$_CPHP = true;
$_CPHP_CONFIG = "../config.json";
require("cphp/base.php");
if(!empty($_GET['type']))
{
$can_once = true;
}
else
{
$can_once = false;
}
echo(NewTemplater::Render("landing", $locale->strings, array('can-donate-once' => $can_once)));
require("rewrite.php");

@ -0,0 +1,26 @@
<?php
/*
* ReDonate is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
if(!isset($_APP)) { die("Unauthorized."); }
try
{
$sCampaign = Campaign::FindByUrlName($router->uParameters[1]);
$sPageTitle = "Contribute to {$sCampaign->sName}";
$sPageContents = NewTemplater::Render("landing", $locale->strings, array("can-donate-once" => true, "project-name" => $sCampaign->sName));
}
catch (NotFoundException $e)
{
$sPageContents = NewTemplater::Render("404", $locale->strings, array());
}

@ -0,0 +1,46 @@
<?php
/*
* ReDonate is more free software. It is licensed under the WTFPL, which
* allows you to do pretty much anything with it, without having to
* ask permission. Commercial use is allowed, and no attribution is
* required. We do politely request that you share your modifications
* to benefit other developers, but you are under no enforced
* obligation to do so :)
*
* Please read the accompanying LICENSE document for the full WTFPL
* licensing text.
*/
$_CPHP = true;
$_CPHP_CONFIG = "../config.json";
require("cphp/base.php");
$_APP = true;
function __autoload($class_name)
{
global $_APP;
$class_name = str_replace("\\", "/", strtolower($class_name));
require_once("classes/{$class_name}.php");
}
$sPageTitle = "";
$sPageContents = "";
$router = new CPHPRouter();
$router->allow_slash = true;
$router->ignore_query = true;
$router->routes = array(
0 => array(
"^/$" => "modules/index.php",
"^/register/$" => "modules/register.php",
"^/login/$" => "modules/login.php",
"^/campaign/([a-zA-Z0-9-]+)" => "modules/landing.php",
"^/campaign/([a-zA-Z0-9-]+)/subscribe" => "modules/subscribe.php",
)
);
$router->RouteRequest();
echo(NewTemplater::Render("layout", $locale->strings, array("contents" => $sPageContents, "title" => $sPageTitle)));

@ -0,0 +1,196 @@
body
{
padding: 0px;
margin: 0px;
background-color: #E5EFD7;
font-family: Lato, sans-serif;
}
.clear
{
clear: both;
}
.wrapper
{
width: 960px;
margin: 0px auto;
}
.header h1
{
color: #7AAA3E;
font-family: Roboto, sans-serif;
font-weight: 500;
font-size: 46px;
margin: 8px 0px;
}
.header h1 .highlight
{
color: #587532;
}
.main
{
background-color: #FCFFF7;
box-shadow: 0px 0px 10px 1px #b0b0b0;
-webkit-box-shadow: 0px 0px 10px 1px #b0b0b0;
-moz-box-shadow: 0px 0px 10px 1px #b0b0b0;
-o-box-shadow: 0px 0px 10px 1px #b0b0b0;
-ms-box-shadow: 0px 0px 10px 1px #b0b0b0;
padding: 16px 20px;
}
.main h2
{
font-size: 32px;
margin: 0px 0px 6px 0px;
color: #3B4A28;
}
.main .details, .main .subscribe
{
margin-top: 16px;
width: 46%;
}
.main .details
{
float: left;
padding-right: 4%;
text-align: justify;
border-right: 1px solid silver;
}
.main .subscribe
{
float: right;
padding-left: 3%;
}
.main h3
{
margin: 0px;
}
.main .subscribe h3
{
margin-bottom: 32px;
}
.main .leader
{
font-size: 18px;
}
.main .more
{
margin-top: 16px;
border-top: 1px solid silver;
padding-top: 32px;
text-align: justify;
}
.main .more .wrapper
{
width: 730px;
margin: 0px auto;
}
.main h3.section
{
margin-top: 16px;
border-top: 1px solid silver;
padding-top: 16px;
}
.subscribe p
{
font-size: 18px;
}
#field_currency
{
text-align: right;
border: 1px solid #6CA825;
border-radius: 1px;
background-color: transparent;
font-size: 18px;
}
#field_amount, #field_email
{
border: 1px solid #6CA825;
border-radius: 1px;
background-color: transparent;
font-size: 18px;
padding: 1px 5px;
}
#field_amount
{
width: 55px;
}
#field_email
{
margin-top: 6px;
width: 335px;
}
.green-button
{
margin-top: 0px;
background: #66CC00;
border-top: 1px solid #529d26;
border-right: 1px solid #2c5615;
border-bottom: 1px solid #1d390e;
border-left: 1px solid #2c5615;
border-radius: 4px;
box-shadow: inset 0 1px 10px 1px #8eff4b,
0px 1px 0 #2c5713,
0 6px 0px #305e14,
0 8px 4px 1px #111111;
color: #fff;
font: bold 20px/1 "helvetica neue",
helvetica,
arial,
sans-serif;
margin-bottom: 15px;
padding: 10px 15px 12px 15px;
text-align: center;
text-shadow: 0px -1px 1px #1e2d4d;
-webkit-background-clip: padding-box; }
.green-button:hover
{
box-shadow: inset 0 0px 20px 1px #bdff87,
0px 1px 0 #324d1d,
0 6px 0px #37531f,
0 8px 4px 1px #111111;
cursor: pointer; }
.green-button:active
{
box-shadow: inset 0 1px 10px 1px #a5df76,
0 1px 0 #203213,
0 2px 0 #223413,
0 4px 3px 0 #111111;
margin-top: 5px;
margin-bottom: 10px;
}
.green-button:disabled
{
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
filter: grayscale(100%);
}
p.pledge
{
padding-left: 15px;
padding-top: 10px;
}

@ -0,0 +1,15 @@
<h2>Page not found.</h2>
<p>
<strong>Sorry, we could not find the page you requested.</strong> But while you're here anyway, why not introduce ourselves?
</p>
<p>
ReDonate is recurring contributions, done right. Set up a campaign, and accept monthly donations from contributors that wish
to support you, without <em>ever</em> automatically charging an account. ReDonate is friendly to you, <em>and</em> your
donors.
</p>
<p>
Gotten curious? <a href="/">Visit our homepage to learn more...</a>
</p>

@ -1,222 +1,15 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href='http://fonts.googleapis.com/css?family=Lato:400,700|Cantarell:400,700|Roboto:500' rel='stylesheet' type='text/css'>
<style>
body
{
padding: 0px;
margin: 0px;
background-color: #E5EFD7;
font-family: Lato, sans-serif;
}
<h2>Contribute to {%?project-name} monthly, no automatic charges.</h2>
.clear
{
clear: both;
}
.wrapper
{
width: 960px;
margin: 0px auto;
}
.header h1
{
color: #7AAA3E;
font-family: Roboto, sans-serif;
font-weight: 500;
font-size: 46px;
margin: 8px 0px;
}
.header h1 .highlight
{
color: #587532;
}
.main
{
background-color: #FCFFF7;
box-shadow: 0px 0px 10px 1px #b0b0b0;
-webkit-box-shadow: 0px 0px 10px 1px #b0b0b0;
-moz-box-shadow: 0px 0px 10px 1px #b0b0b0;
-o-box-shadow: 0px 0px 10px 1px #b0b0b0;
-ms-box-shadow: 0px 0px 10px 1px #b0b0b0;
padding: 16px 20px;
}
.main h2
{
font-size: 32px;
margin: 0px 0px 6px 0px;
color: #3B4A28;
}
.main .details, .main .subscribe
{
margin-top: 16px;
width: 46%;
}
.main .details
{
float: left;
padding-right: 4%;
text-align: justify;
border-right: 1px solid silver;
}
.main .subscribe
{
float: right;
padding-left: 3%;
}
.main h3
{
margin: 0px;
}
.main .subscribe h3
{
margin-bottom: 32px;
}
.main .leader
{
font-size: 18px;
}
.main .more
{
margin-top: 16px;
border-top: 1px solid silver;
padding-top: 32px;
text-align: justify;
}
.main .more .wrapper
{
width: 730px;
margin: 0px auto;
}
.subscribe p
{
font-size: 18px;
}
#field_currency
{
text-align: right;
border: 1px solid #6CA825;
border-radius: 1px;
background-color: transparent;
font-size: 18px;
}
#field_amount, #field_email
{
border: 1px solid #6CA825;
border-radius: 1px;
background-color: transparent;
font-size: 18px;
padding: 1px 5px;
}
#field_amount
{
width: 55px;
}
#field_email
{
margin-top: 6px;
width: 335px;
}
/* Thanks, Ari! */
.green-button
{
margin-top: 0px;
background: #66CC00;
border-top: 1px solid #529d26;
border-right: 1px solid #2c5615;
border-bottom: 1px solid #1d390e;
border-left: 1px solid #2c5615;
border-radius: 4px;
box-shadow: inset 0 1px 10px 1px #8eff4b,
0px 1px 0 #2c5713,
0 6px 0px #305e14,
0 8px 4px 1px #111111;
color: #fff;
font: bold 20px/1 "helvetica neue",
helvetica,
arial,
sans-serif;
margin-bottom: 15px;
padding: 10px 15px 12px 15px;
text-align: center;
text-shadow: 0px -1px 1px #1e2d4d;
-webkit-background-clip: padding-box; }
.green-button:hover
{
box-shadow: inset 0 0px 20px 1px #bdff87,
0px 1px 0 #324d1d,
0 6px 0px #37531f,
0 8px 4px 1px #111111;
cursor: pointer; }
.green-button:active
{
box-shadow: inset 0 1px 10px 1px #a5df76,
0 1px 0 #203213,
0 2px 0 #223413,
0 4px 3px 0 #111111;
margin-top: 5px;
margin-bottom: 10px;
}
.green-button:disabled
{
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
filter: grayscale(100%);
}
p.pledge
{
padding-left: 15px;
padding-top: 10px;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="header">
<h1>
Re<span class="highlight">Donate</span>
</h1>
</div>
<div class="main">
<h2>Contribute to AnonNews monthly, no automatic charges.</h2>
<div class="details">
<div class="details">
<h3>How does it work?</h3>
<p class="leader">
Most recurring services - even charities! - will automatically charge your account every month.
ReDonate is different.
</p>
<p>
When you subscribe to a ReDonate campaign, you only have to tell us how much you want to donate, and provide
your e-mail address. Every month, we will e-mail you to remind you of your pledge. The e-mail you receive will
include a list of payment methods, and an unsubscribe link.
When you subscribe to a ReDonate campaign, you only have to tell us how much you want to donate, and
your e-mail address. Every month, we will e-mail you to remind you of your pledge. The e-mail you
receive will include a list of payment methods, and an unsubscribe link.
</p>
<p>
What this means in simple terms is that you'll <strong>never</strong> be automatically charged for a donation -
@ -232,8 +25,8 @@
donation schedule, and no automatic charges either!
</p>
{%/if}
</div>
<div class="subscribe">
</div>
<div class="subscribe">
<h3>Subscribe to a recurring donation</h3>
<p>
My e-mail address is...
@ -260,9 +53,9 @@
<img src="/static/images/bitcoin.png" style="margin-left: 16px;">
</p>
{%/if}
</div>
<div class="clear"></div>
<div class="more">
</div>
<div class="clear"></div>
<div class="more">
<div class="wrapper">
{%if can-donate-once == false}
<h3>Why use ReDonate?</h3>
@ -289,8 +82,4 @@
e-mail address for anything other than sending you reminders, and every e-mail includes an unsubscribe link.
</p>
</div>
</div>
</div>
</div>
</body>
</html>
</div>

@ -0,0 +1,21 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href='http://fonts.googleapis.com/css?family=Lato:400,700|Cantarell:400,700|Roboto:500' rel='stylesheet' type='text/css'>
<link href="/static/css/style.css" rel="stylesheet">
<title>ReDonate :: {%?title}</title>
</head>
<body>
<div class="wrapper">
<div class="header">
<h1>
Re<span class="highlight">Donate</span>
</h1>
</div>
<div class="main">
{%?contents}
</div>
</div>
</body>
</html>
Loading…
Cancel
Save