diff options
Diffstat (limited to 'lib/invite.pm')
| -rw-r--r-- | lib/invite.pm | 485 |
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( · ); + 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> </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: </b></td><td align=left colspan=2>$i->{username}</td></tr>); + print qq(<tr><td align=right width=100><b>realname: </b></td><td align=left colspan=2>$i->{realname}</td></tr>); + print qq(<tr><td align=right width=100><b>email: </b></td><td align=left colspan=2>$i->{email}</td></tr>); + + print qq(<tr>); + print qq(<td> </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( · ); + 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; + |
