Open invitation setting

Closes #64
This commit is contained in:
Vsevolod Strukchinsky 2014-02-13 15:08:20 +06:00
parent aac473d689
commit 6937b7b21e
11 changed files with 97 additions and 4 deletions

View file

@ -86,6 +86,8 @@ func setupHandlers() {
m.Post("/forgot", handler.ErrorHandler(handler.ForgotPost)) m.Post("/forgot", handler.ErrorHandler(handler.ForgotPost))
m.Get("/reset", handler.ErrorHandler(handler.Reset)) m.Get("/reset", handler.ErrorHandler(handler.Reset))
m.Post("/reset", handler.ErrorHandler(handler.ResetPost)) m.Post("/reset", handler.ErrorHandler(handler.ResetPost))
m.Get("/signup", handler.ErrorHandler(handler.SignUp))
m.Post("/signup", handler.ErrorHandler(handler.SignUpPost))
m.Get("/register", handler.ErrorHandler(handler.Register)) m.Get("/register", handler.ErrorHandler(handler.Register))
m.Post("/register", handler.ErrorHandler(handler.RegisterPost)) m.Post("/register", handler.ErrorHandler(handler.RegisterPost))
m.Get("/accept", handler.UserHandler(handler.TeamMemberAccept)) m.Get("/accept", handler.UserHandler(handler.TeamMemberAccept))

View file

@ -127,6 +127,7 @@ CREATE TABLE settings (
,smtp_password VARCHAR(1024) ,smtp_password VARCHAR(1024)
,hostname VARCHAR(1024) ,hostname VARCHAR(1024)
,scheme VARCHAR(5) ,scheme VARCHAR(5)
,open_invitations INTEGER
); );
` `

View file

@ -112,6 +112,7 @@ CREATE TABLE settings (
,smtp_password VARCHAR(1024) ,smtp_password VARCHAR(1024)
,hostname VARCHAR(1024) ,hostname VARCHAR(1024)
,scheme VARCHAR(5) ,scheme VARCHAR(5)
,open_invitations INTEGER
); );
CREATE UNIQUE INDEX member_uix ON members (team_id, user_id); CREATE UNIQUE INDEX member_uix ON members (team_id, user_id);

View file

@ -11,7 +11,7 @@ const settingsTable = "settings"
// SQL Queries to retrieve the system settings // SQL Queries to retrieve the system settings
const settingsStmt = ` const settingsStmt = `
SELECT id, github_key, github_secret, bitbucket_key, bitbucket_secret, SELECT id, github_key, github_secret, bitbucket_key, bitbucket_secret,
smtp_server, smtp_port, smtp_address, smtp_username, smtp_password, hostname, scheme smtp_server, smtp_port, smtp_address, smtp_username, smtp_password, hostname, scheme, open_invitations
FROM settings WHERE id = 1 FROM settings WHERE id = 1
` `

View file

@ -33,8 +33,7 @@ func AdminUserAdd(w http.ResponseWriter, r *http.Request, u *User) error {
return RenderTemplate(w, "admin_users_add.html", &struct{ User *User }{u}) return RenderTemplate(w, "admin_users_add.html", &struct{ User *User }{u})
} }
// Invite a user to join the system func UserInvite(w http.ResponseWriter, r *http.Request) error {
func AdminUserInvite(w http.ResponseWriter, r *http.Request, u *User) error {
// generate the password reset token // generate the password reset token
email := r.FormValue("email") email := r.FormValue("email")
token := authcookie.New(email, time.Now().Add(12*time.Hour), secret) token := authcookie.New(email, time.Now().Add(12*time.Hour), secret)
@ -66,6 +65,11 @@ func AdminUserInvite(w http.ResponseWriter, r *http.Request, u *User) error {
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK) return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
} }
// Invite a user to join the system
func AdminUserInvite(w http.ResponseWriter, r *http.Request, u *User) error {
return UserInvite(w, r)
}
// Form to edit a user // Form to edit a user
func AdminUserEdit(w http.ResponseWriter, r *http.Request, u *User) error { func AdminUserEdit(w http.ResponseWriter, r *http.Request, u *User) error {
idstr := r.FormValue("id") idstr := r.FormValue("id")
@ -176,6 +180,8 @@ func AdminSettingsUpdate(w http.ResponseWriter, r *http.Request, u *User) error
settings.SmtpUsername = r.FormValue("SmtpUsername") settings.SmtpUsername = r.FormValue("SmtpUsername")
settings.SmtpPassword = r.FormValue("SmtpPassword") settings.SmtpPassword = r.FormValue("SmtpPassword")
settings.OpenInvitations = (r.FormValue("OpenInvitations") == "on")
// persist changes // persist changes
if err := database.SaveSettings(settings); err != nil { if err := database.SaveSettings(settings); err != nil {
return RenderError(w, err, http.StatusBadRequest) return RenderError(w, err, http.StatusBadRequest)

View file

@ -47,7 +47,13 @@ func Index(w http.ResponseWriter, r *http.Request) error {
// Return an HTML form for the User to login. // Return an HTML form for the User to login.
func Login(w http.ResponseWriter, r *http.Request) error { func Login(w http.ResponseWriter, r *http.Request) error {
return RenderTemplate(w, "login.html", nil) var settings = database.SettingsMust()
data := struct {
Settings *Settings
}{settings}
return RenderTemplate(w, "login.html", &data)
} }
// Terminate the User session. // Terminate the User session.
@ -70,6 +76,15 @@ func Reset(w http.ResponseWriter, r *http.Request) error {
return RenderTemplate(w, "reset.html", &struct{ Error string }{""}) return RenderTemplate(w, "reset.html", &struct{ Error string }{""})
} }
// Return an HTML form for the User to signup.
func SignUp(w http.ResponseWriter, r *http.Request) error {
if !database.SettingsMust().OpenInvitations {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return nil
}
return RenderTemplate(w, "signup.html", nil)
}
// Return an HTML form to register for a new account. This // Return an HTML form to register for a new account. This
// page must be visited from a Signup email that contains // page must be visited from a Signup email that contains
// a hash to verify the Email address is correct. // a hash to verify the Email address is correct.
@ -144,6 +159,15 @@ func ResetPost(w http.ResponseWriter, r *http.Request) error {
return nil return nil
} }
func SignUpPost(w http.ResponseWriter, r *http.Request) error {
if !database.SettingsMust().OpenInvitations {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return nil
}
return UserInvite(w, r)
}
func RegisterPost(w http.ResponseWriter, r *http.Request) error { func RegisterPost(w http.ResponseWriter, r *http.Request) error {
// verify the token and extract the username // verify the token and extract the username
token := r.FormValue("token") token := r.FormValue("token")

View file

@ -27,6 +27,8 @@ type Settings struct {
// Scheme of the server, eg https // Scheme of the server, eg https
Scheme string `meddler:"scheme"` Scheme string `meddler:"scheme"`
OpenInvitations bool `meddler:"open_invitations"`
} }
func (s *Settings) URL() *url.URL { func (s *Settings) URL() *url.URL {

View file

@ -33,6 +33,8 @@
{{ end }} {{ end }}
</select> </select>
<input class="form-control form-control-xlarge" type="text" name="Domain" value="{{.Settings.Domain}}" /> <input class="form-control form-control-xlarge" type="text" name="Domain" value="{{.Settings.Domain}}" />
<label>Open invitations:</label>
<input class="form-control form-control-xlarge" type="checkbox" name="OpenInvitations" {{ if .Settings.OpenInvitations }} checked {{ end }} /> enable open invintation requests from users
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="alert">GitHub OAuth Consumer Key and Secret</div> <div class="alert">GitHub OAuth Consumer Key and Secret</div>

View file

@ -10,6 +10,9 @@
<input type="submit" value="Sign in" /> <input type="submit" value="Sign in" />
</div> </div>
<div> <div>
{{ if .Settings.OpenInvitations }}
<a href="/signup">request invitation</a>&nbsp;
{{ end }}
<a href="/forgot">forgot password</a> <a href="/forgot">forgot password</a>
</div> </div>
{{ end }} {{ end }}

View file

@ -0,0 +1,51 @@
{{ define "title" }}Sign up · drone.io{{ end }}
{{ define "content" }}
<h1>Sign up</h1>
<form action="/signup" method="POST" role="form">
<div>
<input type="text" name="email" placeholder="Email address" autocomplete="off" spellcheck="false" class="form-control" />
</div>
<div>
<div class="alert alert-success hide" id="successAlert"></div>
<div class="alert alert-error hide" id="failureAlert"></div>
</div>
<div>
<input type="submit" id="submitButton" value="Request invite" />
</div>
</form>
{{ end }}
{{ define "script" }}
<script>
document.forms[0].onsubmit = function(event) {
$("#successAlert").hide();
$("#failureAlert").hide();
$('#submitButton').button('loading');
var form = event.target
var formData = new FormData(form);
xhr = new XMLHttpRequest();
xhr.open('POST', form.action);
xhr.onload = function() {
if (this.status == 200) {
var msg = "User Invitation was sent successfully";
if (this.responseText != "OK") {
msg = "Email is not currently enabled. In order to invite the user, you'll need to provide them the following link:<br><span class='url'>" + this.responseText + "</span>";
}
$("#successAlert").html(msg);
$("#successAlert").show().removeClass("hide");
$('#submitButton').button('reset')
} else {
$("#failureAlert").text("Failed to send Invitation Email. " + this.response);
$("#failureAlert").show().removeClass("hide");
$('#submitButton').button('reset')
};
};
xhr.send(formData);
return false;
}
</script>
{{ end }}

View file

@ -45,6 +45,7 @@ func init() {
"forgot.html", "forgot.html",
"forgot_sent.html", "forgot_sent.html",
"reset.html", "reset.html",
"signup.html",
"register.html", "register.html",
"install.html", "install.html",