userlog.go 1.58 KB
Newer Older
1 2 3 4 5 6 7 8 9
package server

import (
	"context"
	"log"
	"time"

	"git.autistici.org/ai3/go-common/clientutil"
	"git.autistici.org/id/auth"
10
	"git.autistici.org/id/auth/backend"
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
	"git.autistici.org/id/usermetadb"
	"git.autistici.org/id/usermetadb/client"
)

type addLogClient interface {
	AddLog(context.Context, string, *usermetadb.LogEntry) error
}

type logFilter struct {
	client addLogClient
}

func newUserActivityLogFilter(config *clientutil.BackendConfig) (*logFilter, error) {
	c, err := client.New(config)
	if err != nil {
		return nil, err
	}
	return &logFilter{c}, nil
}

31 32
var userLogTimeout = 30 * time.Second

33
func (f *logFilter) Filter(user *backend.User, req *auth.Request, resp *auth.Response) *auth.Response {
34 35 36 37
	if resp.Status != auth.StatusOK {
		return resp
	}

ale's avatar
ale committed
38 39 40 41 42 43 44 45
	// TODO: Figuring this out from the request parameters isn't
	// particularly smart.
	method := usermetadb.LoginMethodPassword
	if req.U2FResponse != nil {
		method = usermetadb.LoginMethodU2F
	} else if req.OTP != "" {
		method = usermetadb.LoginMethodOTP
	}
46 47 48 49 50 51
	entry := usermetadb.LogEntry{
		Timestamp:   time.Now(),
		Username:    user.Name,
		Type:        usermetadb.LogTypeLogin,
		Message:     "successful login",
		Service:     req.Service,
ale's avatar
ale committed
52
		LoginMethod: method,
53 54 55
		DeviceInfo:  req.DeviceInfo,
	}

56 57 58 59 60 61 62 63
	// Make the log RPC in the background, no need to wait for it to complete.
	go func() {
		ctx, cancel := context.WithTimeout(context.Background(), userLogTimeout)
		defer cancel()
		if err := f.client.AddLog(ctx, user.Shard, &entry); err != nil {
			log.Printf("usermetadb.AddLog error for %s: %v", user.Name, err)
		}
	}()
64 65 66

	return resp
}