github.com/kvattikuti/drone@v0.2.1-0.20140603034306-d400229a327a/pkg/handler/app.go (about)

     1  package handler
     2  
     3  import (
     4  	"crypto/rand"
     5  	"io"
     6  	"log"
     7  	"net/http"
     8  	"time"
     9  
    10  	"github.com/dchest/authcookie"
    11  	"github.com/dchest/passwordreset"
    12  	"github.com/drone/drone/pkg/database"
    13  	"github.com/drone/drone/pkg/mail"
    14  	. "github.com/drone/drone/pkg/model"
    15  )
    16  
    17  var (
    18  	// Secret key used to sign auth cookies,
    19  	// password reset tokens, etc.
    20  	secret = generateRandomKey(256)
    21  )
    22  
    23  // GenerateRandomKey creates a random key of size length bytes
    24  func generateRandomKey(strength int) []byte {
    25  	k := make([]byte, strength)
    26  	if _, err := io.ReadFull(rand.Reader, k); err != nil {
    27  		return nil
    28  	}
    29  	return k
    30  }
    31  
    32  // Returns an HTML index.html page if the user is
    33  // not currently authenticated, otherwise redirects
    34  // the user to their personal dashboard screen
    35  func Index(w http.ResponseWriter, r *http.Request) error {
    36  	// is the user already authenticated then
    37  	// redirect to the dashboard page
    38  	if _, err := r.Cookie("_sess"); err == nil {
    39  		http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
    40  		return nil
    41  	}
    42  
    43  	// otherwise redirect to the login page
    44  	http.Redirect(w, r, "/login", http.StatusSeeOther)
    45  	return nil
    46  }
    47  
    48  // Return an HTML form for the User to login.
    49  func Login(w http.ResponseWriter, r *http.Request) error {
    50  	var settings, _ = database.GetSettings()
    51  
    52  	data := struct {
    53  		Settings *Settings
    54  	}{settings}
    55  
    56  	return RenderTemplate(w, "login.html", &data)
    57  }
    58  
    59  // Terminate the User session.
    60  func Logout(w http.ResponseWriter, r *http.Request) error {
    61  	DelCookie(w, r, "_sess")
    62  
    63  	http.Redirect(w, r, "/login", http.StatusSeeOther)
    64  	return nil
    65  }
    66  
    67  // Return an HTML form for the User to request a password reset.
    68  func Forgot(w http.ResponseWriter, r *http.Request) error {
    69  	return RenderTemplate(w, "forgot.html", nil)
    70  }
    71  
    72  // Return an HTML form for the User to perform a password reset.
    73  // This page must be visited from a Password Reset email that
    74  // contains a hash to verify the User's identity.
    75  func Reset(w http.ResponseWriter, r *http.Request) error {
    76  	return RenderTemplate(w, "reset.html", &struct{ Error string }{""})
    77  }
    78  
    79  // Return an HTML form for the User to signup.
    80  func SignUp(w http.ResponseWriter, r *http.Request) error {
    81  	var settings, _ = database.GetSettings()
    82  
    83  	if settings == nil || !settings.OpenInvitations {
    84  		http.Redirect(w, r, "/login", http.StatusSeeOther)
    85  		return nil
    86  	}
    87  
    88  	return RenderTemplate(w, "signup.html", nil)
    89  }
    90  
    91  // Return an HTML form to register for a new account. This
    92  // page must be visited from a Signup email that contains
    93  // a hash to verify the Email address is correct.
    94  func Register(w http.ResponseWriter, r *http.Request) error {
    95  	return RenderTemplate(w, "register.html", &struct{ Error string }{""})
    96  }
    97  
    98  func ForgotPost(w http.ResponseWriter, r *http.Request) error {
    99  	email := r.FormValue("email")
   100  
   101  	// attempt to retrieve the user by email address
   102  	user, err := database.GetUserEmail(email)
   103  	if err != nil {
   104  		log.Printf("could not find user %s to reset password. %s", email, err)
   105  		// if we can't find the email, we still display
   106  		// the template to the user. This prevents someone
   107  		// from trying to guess passwords through trial & error
   108  		return RenderTemplate(w, "forgot_sent.html", nil)
   109  	}
   110  
   111  	// hostname from settings
   112  	hostname := database.SettingsMust().URL().String()
   113  
   114  	// generate the password reset token
   115  	token := passwordreset.NewToken(user.Email, 12*time.Hour, []byte(user.Password), secret)
   116  	data := struct {
   117  		Host  string
   118  		User  *User
   119  		Token string
   120  	}{hostname, user, token}
   121  
   122  	// send the email message async
   123  	go func() {
   124  		if err := mail.SendPassword(email, data); err != nil {
   125  			log.Printf("error sending password reset email to %s. %s", email, err)
   126  		}
   127  	}()
   128  
   129  	// render the template indicating a success
   130  	return RenderTemplate(w, "forgot_sent.html", nil)
   131  }
   132  
   133  func ResetPost(w http.ResponseWriter, r *http.Request) error {
   134  	// verify the token and extract the username
   135  	token := r.FormValue("token")
   136  	email, err := passwordreset.VerifyToken(token, database.GetPassEmail, secret)
   137  	if err != nil {
   138  		return RenderTemplate(w, "reset.html", &struct{ Error string }{"Your password reset request is expired."})
   139  	}
   140  
   141  	// get the user from the database
   142  	user, err := database.GetUserEmail(email)
   143  	if err != nil {
   144  		return RenderTemplate(w, "reset.html", &struct{ Error string }{"Unable to locate user account."})
   145  	}
   146  
   147  	// get the new password
   148  	password := r.FormValue("password")
   149  	if err := user.SetPassword(password); err != nil {
   150  		return RenderTemplate(w, "reset.html", &struct{ Error string }{err.Error()})
   151  	}
   152  
   153  	// save to the database
   154  	if err := database.SaveUser(user); err != nil {
   155  		return RenderTemplate(w, "reset.html", &struct{ Error string }{"Unable to update password. Please try again"})
   156  	}
   157  
   158  	// add the user to the session object
   159  	SetCookie(w, r, "_sess", user.Email)
   160  
   161  	http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
   162  	return nil
   163  }
   164  
   165  func SignUpPost(w http.ResponseWriter, r *http.Request) error {
   166  	// if self-registration is disabled we should display an
   167  	// error message to the user.
   168  	if !database.SettingsMust().OpenInvitations {
   169  		http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
   170  		return nil
   171  	}
   172  
   173  	// generate the password reset token
   174  	email := r.FormValue("email")
   175  	token := authcookie.New(email, time.Now().Add(12*time.Hour), secret)
   176  
   177  	// get the hostname from the database for use in the email
   178  	hostname := database.SettingsMust().URL().String()
   179  
   180  	// data used to generate the email template
   181  	data := struct {
   182  		Host  string
   183  		Email string
   184  		Token string
   185  	}{hostname, email, token}
   186  
   187  	// send the email message async
   188  	go mail.SendActivation(email, data)
   189  
   190  	return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
   191  }
   192  
   193  func RegisterPost(w http.ResponseWriter, r *http.Request) error {
   194  	// verify the token and extract the username
   195  	token := r.FormValue("token")
   196  	email := authcookie.Login(token, secret)
   197  	if len(email) == 0 {
   198  		return RenderTemplate(w, "register.html", &struct{ Error string }{"Your registration email is expired."})
   199  	}
   200  
   201  	// set the email and name
   202  	user := NewUser(r.FormValue("name"), email)
   203  
   204  	// set the new password
   205  	password := r.FormValue("password")
   206  	if err := user.SetPassword(password); err != nil {
   207  		return RenderTemplate(w, "register.html", &struct{ Error string }{err.Error()})
   208  	}
   209  
   210  	// verify fields are correct
   211  	if err := user.Validate(); err != nil {
   212  		return RenderTemplate(w, "register.html", &struct{ Error string }{err.Error()})
   213  	}
   214  
   215  	// save to the database
   216  	if err := database.SaveUser(user); err != nil {
   217  		return err
   218  	}
   219  
   220  	// add the user to the session object
   221  	SetCookie(w, r, "_sess", user.Email)
   222  
   223  	// redirect the user to their dashboard
   224  	http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
   225  	return nil
   226  }