summaryrefslogtreecommitdiff
path: root/lib/invite.pm
diff options
context:
space:
mode:
authorJules Laplace <carbon@melanarchy.org>2013-08-02 17:14:41 -0500
committerJules Laplace <carbon@melanarchy.org>2013-08-02 17:14:41 -0500
commite9192b3d42660a5781101df4357d276318151e8a (patch)
tree059eb6ace6147cf9559af74ed1ab5e221c80e280 /lib/invite.pm
parent79670053c7247d3a49b607960efd284e93f057e5 (diff)
cgi-bin & lib
Diffstat (limited to 'lib/invite.pm')
-rw-r--r--lib/invite.pm485
1 files changed, 485 insertions, 0 deletions
diff --git a/lib/invite.pm b/lib/invite.pm
new file mode 100644
index 0000000..96c6de0
--- /dev/null
+++ b/lib/invite.pm
@@ -0,0 +1,485 @@
+
+sub request_invite
+ {
+ my $clean_invite = parse_registration_input();
+ my $result = 0;
+ if ($clean_invite != -1)
+ {
+ new_invite($clean_invite);
+ request_success();
+ }
+ }
+
+sub generate_invite
+ {
+ my $invite_count = count_active_user_invites($USER->{username});
+ my $newhash;
+
+ # don't invite your whole social network
+ if ($invite_count >= 5)
+ { return -1 unless ($USER->{ulevel} == 3); }
+
+ for (my $i = 0; $i < 3; $i++)
+ {
+ $newhash = make_new_hash($USER->{username} . time);
+ my $invite = get_invite_from_hash($hash);
+ last unless (invite_is_active($invite));
+ }
+
+ my $clean_invite = parse_invite_input($newhash);
+ if ($clean_invite != -1)
+ { $result = new_invite($clean_invite); }
+ $result ? return $newhash : return -1;
+ }
+
+sub validate_invite
+ {
+ my ($hash) = @_;
+ my $invite = get_invite_from_hash($hash);
+
+ unless (invite_is_active($invite))
+ { error("Bad invite key!"); }
+
+ my $clean_register = parse_registration_input();
+ if ($clean_register != -1)
+ {
+ my $uid = new_user($clean_register);
+ set_invite_state($invite, $BUCKY_INVITE_REDEEMED);
+ set_invite_username($invite, $clean_register->{username});
+ # auto-op on keywords
+ add_mailbox("$clean_register->{username}.inbox", $clean_register->{username}, 0);
+ add_mailbox("$clean_register->{username}.outbox", $clean_register->{username}, 0);
+ add_mailbox("$clean_register->{username}.drafts", $clean_register->{username}, 1);
+ send_welcome_message($uid);
+ send_invite_receipt($invite->{attest}, $clean_register, $invite);
+ send_invite_receipt($BUCKY_ADMINISTRATOR, $clean_register, $invite);
+ validate_success();
+ }
+ }
+
+sub validate_approve
+ {
+ my ($invite) = @_;
+ my $o =
+ {
+ username => $invite->{username},
+ password => $invite->{password},
+ realname => $invite->{realname},
+ email => $invite->{email},
+ grass => $invite->{grass}
+ };
+ my $uid = new_user($o);
+ $result = set_invite_state($invite, $BUCKY_INVITE_APPROVED);
+ # auto-op on keywords
+ add_mailbox("$o->{username}.inbox", $o->{username}, 0);
+ add_mailbox("$o->{username}.outbox", $o->{username}, 0);
+ add_mailbox("$o->{username}.drafts", $o->{username}, 1);
+ send_welcome_message($uid);
+ return 1;
+ }
+
+sub send_invite_receipt
+ {
+ my ($recipient, $newuser, $invite) = @_;
+ my $mbox = ($recipient eq $BUCKY_ADMINISTRATOR) ? "$recipient.system" : "$recipient.inbox";
+ $transcript =
+ qq(<b>$newuser->{username}</b> has created an account via invite.\n\n) .
+ qq(<b>real name:</b> $newuser->{realname}\n\n) .
+ qq(<b>email:</b> $newuser->{email}\n\n) .
+ qq(<b>invited by:</b> $invite->{attest}\n\n);
+ new_message($mbox,
+ {
+ sender => "system",
+ recipient => $recipient,
+ unread => 1,
+ subject => "New user $newuser->{username} via invite",
+ body => $transcript
+ } );
+ }
+
+#############################
+
+sub validate_success
+ {
+ header("account created!");
+ print qq(<hr noshade color="$BUCKY_COLOR_HR" style="padding: 0px; margin: 2px;"><br><br><br><center><div class=message>);
+ print "Your $BUCKY_NAME account has created!<p>";
+ print "Please <b>log in</b> for the first time.\n";
+ print qq(<hr noshade color="$BUCKY_COLOR_HR">\n\n);
+ login_form();
+ print qq(</div></center>\n\n);
+ footer();
+ }
+
+sub request_success
+ {
+ header("account requested!");
+ print qq(<hr noshade color="$BUCKY_COLOR_HR">\n\n);
+ print "Your request for a $BUCKY_NAME account has been submitted and will be acted upon shortly.<p>";
+ print qq(<big><a href="/">back to $BUCKY_NAME</a></big>);
+ footer();
+ }
+
+#############################
+
+sub registration_form
+ {
+ my ($invite) = @_;
+ my $invited = defined($invite) && $invite != -1;
+
+ if ($invited)
+ { header("create an account"); }
+ else
+ { header("request an account"); }
+
+ print <<adduserform;
+<hr noshade color="$BUCKY_COLOR_HR" style="padding: 0px; margin: 2px;"><br>
+<table width=100%><tr><td align="center">
+<img src="/bucky/newme.jpg" style="border: 2px solid #000; margin-bottom: 3px;"><br><!-- <small>~ OUR FOUNDER ~</small> -->
+<small><span style="color: #dfd6cd;">may i note here . . . that i test this with firefox</span><br></small>
+<table><tr><td class="message" nowrap style="width: 300px;">
+<b>welcome to $BUCKY_NAME!</b>
+<hr noshade color="$BUCKY_COLOR_HR">
+<div align="right" nowrap style="width: 250px;">
+
+<form action="$BUCKY/invite" method="post">
+adduserform
+
+ print qq(<input type="hidden" name="debug" value="1">\n) if ($DEBUG);
+
+ if ($invited)
+ {
+ print qq(<input type="hidden" name="c" value="validate">\n);
+ print qq(<input type="hidden" name="hash" value="$invite->{hash}">\n);
+ }
+ else
+ {
+ print qq(<input type="hidden" name="c" value="request">\n);
+ }
+
+ print <<adduserfoot;
+username <small>(lowercase)</small>: <input type="text" name="username" value="" size=10 maxlength=9><br>
+password: <input type="password" name="pw1" value="" size=13 maxlength=20><br>
+again! <input type="password" name="pw2" value="" size=13 maxlength=20><br>
+real name: <input type="text" name="realname" value="" size=20><br>
+email address: <input type="text" name="email" value="" size=20><br>
+</div>
+adduserfoot
+
+ print <<snark;
+oh <b>h</b>e<b>l</b>l<b>o</b> <b>t</b>h<b>e</b>r<b>e</b> duder, please say hello<br>
+<textarea name="grass" rows="5" style="width: 86%; padding: 0px 1px 1px 1px; font-family: trebuchet ms, sans serif; font-size: 11px;"></textarea>
+snark
+
+ print <<addusereof;
+<div align="center">
+<p>
+
+<input type="submit" value="SUBMIT" class="clicky">
+
+</form>
+</div>
+</td></tr></table>
+</td></tr></table>
+addusereof
+
+ footer();
+ }
+
+#############################
+
+sub parse_invite_input
+ {
+ my ($newhash) = @_;
+ my $safe = 1;
+
+ my $clean =
+ {
+ state => $BUCKY_INVITE_ACTIVE,
+ hash => $newhash,
+ attest => $USER->{username},
+ keywords => scrub($input->{keyword})
+ };
+
+ if ($safe)
+ { return $clean; }
+ else
+ { return -1; }
+ }
+
+sub parse_registration_input
+ {
+ my @error;
+ my $clean;
+
+ if ($input->{username} =~ /(root|system|bucky|$BUCKY_SHORT_NAME)/)
+ { push @error, "Illegal username"; }
+ if ($input->{username} =~ /\s/)
+ { push @error, "Username cannot contain spaces"; }
+ if ($input->{pw1} ne $input->{pw2})
+ { push @error, "Passwords don't match"; }
+ if (get_user($input->{username}) != -1)
+ { push @error, "User already exists"; }
+
+ $clean =
+ {
+ state => $BUCKY_INVITE_REQUEST,
+ username => lc(scrub($input->{username})),
+ password => crypt($input->{pw1}, lc(scrub($input->{username}))),
+ realname => scrub($input->{realname}),
+ email => scrub($input->{email}),
+ grass => scrub($input->{grass})
+ };
+
+ if (@error)
+ {
+ registration_form_error(@error);
+ return -1;
+ }
+ else
+ {
+ return $clean;
+ }
+ }
+
+sub registration_form_error
+ {
+ my (@error) = @_;
+ header("registration form error");
+ print "Sorry, there was an error in your registration:<p>";
+ print "<ul>\n";
+ foreach my $e (@error)
+ {
+ print "<li> $e\n";
+ }
+ print "</ul>\n";
+ print qq(Please <a href="javascript:history.go(-1)">go back and fix it</a> . . .<p>);
+ footer();
+ exit(1);
+ }
+
+#############################
+
+sub invite_result_box
+ {
+ my ($command, $hash, $result) = @_;
+ print qq(<div class="message">);
+ if ($command eq "new")
+ {
+ if ($result)
+ {
+ print qq(<b>invite created!</b><p>);
+ print qq(give the url to your friend!);
+ }
+ else
+ {
+ print qq(you were <b>unable</b> to make a new invite!<p>);
+ print qq(maybe you have been inviting too many people?!);
+ }
+ }
+ else
+ {
+ print qq(<b>$command</b> );
+ print $result ? "succeeded!" : "failed!";
+ }
+ print qq(</div>\n);
+ }
+
+sub invite_create_box
+ {
+ print qq(<div class="message">);
+ print qq(<b>invite</b> whomever..\n<hr noshade color="$BUCKY_COLOR_HR">\n);
+ print qq(only invite goodfellows,<br>my fellow ).$BUCKY_DUDER_NOUN.qq(s.<p>);
+ print qq(<form action="$BUCKY/invite" method="post">\n);
+ print qq(<input type="hidden" name="debug" value="1">\n) if ($DEBUG);
+ print qq(<input type="hidden" name="c" value="new">\n);
+ # keyword_pulldown();
+ print qq(<input type="submit" value="G E N E R A T E" class="clicky">\n);
+ print qq(</form>);
+ print qq(</div>\n);
+ }
+
+#############################
+
+sub display_personal_invites
+ {
+ my $user_invites = get_invites_by_user($USER->{username});
+ return if ($user_invites == -1);
+ print "<big><b>Your invites:</b></big><p>";
+ display_invites_table($user_invites);
+ }
+
+sub display_approve_list
+ {
+ my $invites = get_active_invites();
+ print "<big><b>Active invites and requests:</b></big><p>";
+ display_invites_table($invites);
+ }
+
+{
+my %invites_seen;
+sub display_invites_table
+ {
+ my ($invites) = @_;
+ my $r = 0;
+ print qq(<table border=0 cellpadding=0 cellspacing=0 class="main" width=600>\n);
+
+ foreach my $i (sort { $b->{id} <=> $a->{id} } @$invites)
+ {
+ next if (exists($invites_seen{$i->{id}})); # minimize redundancy in admin list
+ $invites_seen{$i->{id}} = 1;
+ display_single_invite($i, $r);
+ $r = $r ? 0 : 1;
+ }
+
+ print qq(</table>);
+ }
+}
+
+sub display_single_invite
+ {
+ my ($i, $r) = @_;
+
+ print qq(<tr class="row$r">);
+
+ print qq(<td align=center style="border-right: 1px dashed #bbb; width: 80px;">);
+ print qq(<b>) if ($i->{state} == 2);
+ print $BUCKY_INVITE_STATES[$i->{state}];
+ print qq(</b>) if ($i->{state} == 2);
+ print qq(</td>);
+
+ if ($i->{hash})
+ { display_invite_row($i); }
+ else
+ { display_approve_row($i); }
+ print qq(</tr>\n);
+ }
+
+sub display_invite_row
+ {
+ my ($i) = @_;
+
+ if ($i->{state} > 0)
+ {
+ print qq(<td>);
+ print qq(<table cellpadding=0 cellspacing=0 border=0 width=100%);
+
+ print qq(<tr>);
+ print qq(<td align=center colspan=4>);
+ print qq(<a href="$BUCKY/invite?i=$i->{hash}">https://$BUCKY_HOST$BUCKY/invite/$i->{hash}</a>);
+ print qq(</td>);
+ print qq(</tr>);
+
+ print qq(<tr>);
+ print qq(<td align=center>);
+ print qq(<small>invited by ).profile_link($i->{attest}).qq(</small>);
+ print qq(</td>);
+ print qq(<td align=right>);
+ print qq(<small>expires in</small>);
+ print qq(</td>);
+ print qq(<td align=left>);
+ print get_age($i->{expired});
+ print qq(</td>);
+ print qq(<td align=right>);
+ print invite_snuff_link("renew", $i->{id}) . qq( &middot; );
+ print invite_snuff_link("cancel", $i->{id});
+ print qq(</td>);
+ print qq(</tr>);
+
+ print qq(</table>);
+ print qq(</td>);
+ }
+ elsif ($i->{state} == $BUCKY_INVITE_REDEEMED)
+ {
+ print qq(<td>);
+ print qq(<table cellpadding=0 cellspacing=0 border=0 width=100%);
+ print qq(<tr>);
+ print qq(<td align=center width=50%>);
+ print qq(<small>invited by ).profile_link($i->{attest}).qq(</small>);
+ print qq(</td>);
+ print qq(<td align=center width=50%>);
+ print qq(new user: );
+ print profile_link($i->{username});
+ print qq(</td>);
+ print qq(</tr>);
+ print qq(</table>);
+ print qq(</td>);
+ }
+ else
+ {
+ print qq(<td>&nbsp;</td>);
+ }
+ }
+
+# username => lc(scrub($input->{username})),
+# realname => scrub($input->{realname}),
+# email => scrub($input->{email}),
+# grass => scrub($input->{grass})
+
+sub display_approve_row
+ {
+ my ($i) = @_;
+ print qq(<td>);
+ print qq(<table cellpadding=0 cellspacing=0 border=0 width=100%);
+
+ print qq(<tr><td align=right width=100><b>username:&nbsp;</b></td><td align=left colspan=2>$i->{username}</td></tr>);
+ print qq(<tr><td align=right width=100><b>realname:&nbsp;</b></td><td align=left colspan=2>$i->{realname}</td></tr>);
+ print qq(<tr><td align=right width=100><b>email:&nbsp;</b></td><td align=left colspan=2>$i->{email}</td></tr>);
+
+ print qq(<tr>);
+ print qq(<td>&nbsp;</td>);
+ print qq(<td align=left colspan=2>$i->{grass}</td>);
+ print qq(</tr>);
+
+ if ($i->{state} > 0)
+ {
+ print qq(<tr>);
+ print qq(<td align=right>);
+ print qq(<small>expires in</small>);
+ print qq(</td>);
+ print qq(<td align=left>);
+ print get_age($i->{expired});
+ print qq(</td>);
+
+ print qq(<td align=right>);
+ print invite_snuff_link("approve", $i->{id}) . qq( &middot; );
+ print invite_snuff_link("reject", $i->{id});
+ print qq(</td>);
+ print qq(</tr>);
+ }
+
+ print qq(</table>);
+ print qq(</td>);
+ }
+
+sub invite_snuff_link
+ {
+ my ($c, $id) = @_;
+ return qq(<a href="$BUCKY/invite?c=$c&id=$id">$c</a>);
+ }
+
+#############################
+
+sub make_new_hash
+ {
+ my ($string) = @_;
+ $string = length($string) ? $string : time;
+ $hex = md5_hex ($string);
+ return substr $hex, 0, 16; # these will TOTALLY never collide
+ }
+
+sub invite_is_active
+ {
+ my ($invite) = @_;
+ return 0 if ($invite == -1);
+ return 0 if ($invite->{state} < 1);
+ #if ($invite->{expired} < time)
+ # {
+ # set_invite_state($invite, $BUCKY_INVITE_EXPIRED);
+ # return 0;
+ # }
+ return 1;
+ }
+
+1;
+