Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 34 additions & 25 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,18 @@ var c Specification
// Specification is the config struct
type Specification struct {
Port string `envconfig:"PORT" required:"true"`
CaptchaSitekey string `required:"true"`
CaptchaSecret string `required:"true"`
CaptchaSitekey string `required:"false"`
CaptchaSecret string `required:"false"`
SlackToken string `required:"true"`
CocUrl string `required:"false" default:"http://coc.golangbridge.org/"`
EnforceHTTPS bool
Debug bool // toggles nlopes/slack client's debug flag
}

func recaptchaEnabled() bool {
return len(c.CaptchaSitekey) > 0 && len(c.CaptchaSecret) > 0
}

func init() {
var showUsage = flag.Bool("h", false, "Show usage")
flag.Parse()
Expand All @@ -81,14 +85,17 @@ func init() {
m.Set("missing_last_name", &missingLastName)
m.Set("missing_email", &missingEmail)
m.Set("missing_coc", &missingCoC)
m.Set("failed_captcha", &failedCaptcha)
m.Set("invalid_captcha", &invalidCaptcha)
m.Set("successful_captcha", &successfulCaptcha)
m.Set("successful_invites", &successfulInvites)
m.Set("active_user_count", &activeUserCount)
m.Set("user_count", &userCount)

captcha = recaptcha.New(c.CaptchaSecret)
if recaptchaEnabled() {
m.Set("failed_captcha", &failedCaptcha)
m.Set("invalid_captcha", &invalidCaptcha)
m.Set("successful_captcha", &successfulCaptcha)
captcha = recaptcha.New(c.CaptchaSecret)
}

api = slack.New(c.SlackToken)

if c.Debug {
Expand Down Expand Up @@ -200,27 +207,29 @@ func handleInvite(w http.ResponseWriter, r *http.Request) {
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
captchaResponse := r.FormValue("g-recaptcha-response")
remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
failedCaptcha.Add(1)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
if recaptchaEnabled() {
captchaResponse := r.FormValue("g-recaptcha-response")
remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
failedCaptcha.Add(1)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}

valid, err := captcha.Verify(captchaResponse, remoteIP)
if err != nil {
failedCaptcha.Add(1)
http.Error(w, "Error validating recaptcha.. Did you click it?", http.StatusPreconditionFailed)
return
}
if !valid {
invalidCaptcha.Add(1)
http.Error(w, "Invalid recaptcha", http.StatusInternalServerError)
return
valid, err := captcha.Verify(captchaResponse, remoteIP)
if err != nil {
failedCaptcha.Add(1)
http.Error(w, "Error validating recaptcha.. Did you click it?", http.StatusPreconditionFailed)
return
}
if !valid {
invalidCaptcha.Add(1)
http.Error(w, "Invalid recaptcha", http.StatusInternalServerError)
return

}
successfulCaptcha.Add(1)
}
successfulCaptcha.Add(1)
fname := r.FormValue("fname")
lname := r.FormValue("lname")
email := r.FormValue("email")
Expand All @@ -245,7 +254,7 @@ func handleInvite(w http.ResponseWriter, r *http.Request) {
http.Error(w, "You need to accept the code of conduct", http.StatusPreconditionFailed)
return
}
err = api.InviteToTeam(ourTeam.Domain(), fname, lname, email)
err := api.InviteToTeam(ourTeam.Domain(), fname, lname, email)
if err != nil {
log.Println("InviteToTeam error:", err)
inviteErrors.Add(1)
Expand Down
4 changes: 3 additions & 1 deletion static/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ var button = body.querySelector('button');
button.className = '';

// capture submit
recaptcha_elem = document.getElementById("g-recaptcha-response");
recaptcha_res = recaptcha_elem === null ? null : recaptcha_elem.value;
body.addEventListener('submit', function(ev){
ev.preventDefault();
button.disabled = true;
button.className = '';
button.innerHTML = 'Please Wait';
invite(coc && coc.checked ? 1 : 0, email.value, first_name.value, last_name.value, document.getElementById("g-recaptcha-response").value, function(err){
invite(coc && coc.checked ? 1 : 0, email.value, first_name.value, last_name.value, recaptcha_res, function(err){
if (err) {
button.removeAttribute('disabled');
button.className = 'error';
Expand Down
4 changes: 4 additions & 0 deletions templates/index.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
<title>Join {{.Team.Name}} on Slack!</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,user-scalable=no">
<link rel="shortcut icon" href="https://slack.global.ssl.fastly.net/272a/img/icons/favicon-32.png">
{{ if .SiteKey }}
<script src="https://www.google.com/recaptcha/api.js"></script>
{{ end }}
</head>
<body>
<div class="splash">
Expand All @@ -24,7 +26,9 @@
<label><input name="coc" type="checkbox" value="1">I agree to
the <a href="{{.CocUrl}}">Code of Conduct</a>.</label>
</div><br>
{{ if .SiteKey }}
<div class="g-recaptcha" data-sitekey="{{.SiteKey}}"></div>
{{ end }}
<button class="loading">Get my Invite</button>
</form>
<p class="signin">or <a href="https://{{.Team.Domain}}.slack.com" target=
Expand Down