コード例 #1
0
ファイル: config.go プロジェクト: rainycape/gondola
func init() {
	config.RegisterFunc(&logConfig, func() {
		if logConfig.LogDebug {
			Std.SetLevel(LDebug)
		} else {
			// Check if we should send errors to the admin email
			admin := mail.AdminEmail()
			from := mail.DefaultFrom()
			server := mail.DefaultServer()
			if admin != "" && server != "" {
				writer := NewSmtpWriter(LError, server, from, admin)
				Std.AddWriter(writer)
			}
		}
	})
}
コード例 #2
0
ファイル: app.go プロジェクト: rainycape/gondola
func (app *App) logError(ctx *Context, err interface{}) {
	skip, stackSkip, _, _ := runtimeutil.GetPanic()
	var buf bytes.Buffer
	if ctx.R != nil {
		buf.WriteString("Panic serving ")
		buf.WriteString(ctx.R.Method)
		buf.WriteByte(' ')
		buf.WriteString(ctx.R.Host)
		buf.WriteString(ctx.R.URL.Path)
		if rq := ctx.R.URL.RawQuery; rq != "" {
			buf.WriteByte('?')
			buf.WriteString(rq)
		}
		if rf := ctx.R.URL.Fragment; rf != "" {
			buf.WriteByte('#')
			buf.WriteString(rf)
		}
		buf.WriteByte(' ')
		buf.WriteString(ctx.RemoteAddress())
	} else {
		buf.WriteString("Panic")
	}
	elapsed := ctx.Elapsed()
	fmt.Fprintf(&buf, " (after %s): %v\n", elapsed, err)
	stack := runtimeutil.FormatStack(stackSkip)
	location, code := runtimeutil.FormatCaller(skip, 5, true, true)
	if location != "" {
		buf.WriteString("\n At ")
		buf.WriteString(location)
		if code != "" {
			buf.WriteByte('\n')
			buf.WriteString(code)
			buf.WriteByte('\n')
		}
	}
	if stack != "" {
		buf.WriteString("\nStack:\n")
		buf.WriteString(stack)
	}
	req := ""
	if ctx.R != nil {
		dump, derr := httputil.DumpRequest(ctx.R, true)
		if derr == nil {
			// This cleans up empty lines and replaces \r\n with \n
			req = stringutil.Lines(string(dump), 0, 10000, true)
			buf.WriteString("\nRequest:\n")
			buf.WriteString(req)
		}
		// Check if there are any attached files that we might
		// want to send in an email
		if !app.cfg.Debug && mail.AdminEmail() != "" {
			ctx.R.ParseMultipartForm(32 << 20) // 32 MiB, as stdlib
			if form := ctx.R.MultipartForm; form != nil {
				var count int
				var attachments []*mail.Attachment
				var message bytes.Buffer
				if len(form.File) > 0 {
					for k, v := range form.File {
						for _, file := range v {
							f, err := file.Open()
							if err != nil {
								fmt.Fprintf(&message, "%s => error %s", k, err)
								continue
							}
							attachment, err := mail.NewAttachment(file.Filename, f)
							attachment.ContentType = file.Header.Get("Content-Type")
							f.Close()
							if err != nil {
								fmt.Fprintf(&message, "%s => error %s", k, err)
								continue
							}
							count++
							fmt.Fprintf(&message, "%s => %s (%s)", k, attachment.Name, attachment.ContentType)
							attachments = append(attachments, attachment)
						}
					}
					fmt.Fprintf(&message, "\nError:\n%s", buf.String())
					host, _ := os.Hostname()
					from := mail.DefaultFrom()
					if from == "" {
						from = fmt.Sprintf("errors@%s", host)
					}
					msg := &mail.Message{
						From:        from,
						To:          mail.Admin,
						Subject:     fmt.Sprintf("Panic with %d attached files on %s", count, host),
						TextBody:    message.String(),
						Attachments: attachments,
					}
					ctx.SendMail("", nil, msg)
				}
			}
		}
	}
	ctx.Logger().Error(buf.String())
	if app.cfg.Debug {
		app.errorPage(ctx, elapsed, skip, stackSkip, req, err)
	} else {
		app.handleHTTPError(ctx, "Internal Server Error", http.StatusInternalServerError)
	}
}
コード例 #3
0
ファイル: handlers.go プロジェクト: rainycape/gondola
func forgotHandler(ctx *app.Context) {
	d := data(ctx)
	if !d.allowDirectSignIn() {
		ctx.NotFound("")
		return
	}
	var user User
	var isEmail bool
	var sent bool
	var fields struct {
		Username         string `form:",singleline,label=Username or Email"`
		ValidateUsername func(*app.Context) error
	}
	fields.ValidateUsername = func(c *app.Context) error {
		username := Normalize(fields.Username)
		isEmail = strings.Contains(username, "@")
		var field string
		if isEmail {
			field = "User.NormalizedEmail"
		} else {
			field = "User.NormalizedUsername"
		}
		userVal, userIface := newEmptyUser(ctx)
		ok := c.Orm().MustOne(orm.Eq(field, username), userIface)
		if !ok {
			if isEmail {
				return i18n.Errorf("address %q does not belong to any registered user", username)
			}
			return i18n.Errorf("username %q does not belong to any registered user", username)
		}
		user = getUserValue(userVal, "User").(User)
		if user.Email == "" {
			return i18n.Errorf("username %q does not have any registered emails", username)
		}
		return nil
	}
	f := form.New(ctx, &fields)
	if f.Submitted() && f.IsValid() {
		se, err := ctx.App().EncryptSigner(Salt)
		if err != nil {
			panic(err)
		}
		values := make(url.Values)
		values.Add("u", strconv.FormatInt(user.Id(), 36))
		values.Add("t", strconv.FormatInt(time.Now().Unix(), 36))
		values.Add("n", stringutil.Random(64))
		payload := values.Encode()
		p, err := se.EncryptSign([]byte(payload))
		if err != nil {
			panic(err)
		}
		abs := ctx.URL()
		reset := fmt.Sprintf("%s://%s%s?p=%s", abs.Scheme, abs.Host, ctx.MustReverse(ResetHandlerName), p)
		data := map[string]interface{}{
			"URL": reset,
		}
		from := mail.DefaultFrom()
		if from == "" {
			from = fmt.Sprintf("no-reply@%s", abs.Host)
		}
		msg := &mail.Message{
			To:      user.Email,
			From:    from,
			Subject: fmt.Sprintf(ctx.T("Reset your %s password"), d.opts.SiteName),
		}
		ctx.MustSendMail("reset_password.txt", data, msg)
		sent = true
	}
	data := map[string]interface{}{
		"ForgotForm": f,
		"IsEmail":    isEmail,
		"Sent":       sent,
		"User":       user,
	}
	ctx.MustExecute(ForgotTemplateName, data)
}