update login / register screens

This commit is contained in:
Brad Rydzewski 2021-05-13 13:51:22 -04:00
parent bb7d04b44c
commit 6b8abc32bf
11 changed files with 97 additions and 15 deletions

View file

@ -211,7 +211,6 @@ func provideDatadog(
sink.Config{ sink.Config{
Endpoint: config.Datadog.Endpoint, Endpoint: config.Datadog.Endpoint,
Token: config.Datadog.Token, Token: config.Datadog.Token,
Contact2: config.Server.Email,
License: license.Kind, License: license.Kind,
Licensor: license.Licensor, Licensor: license.Licensor,
Subscription: license.Subscription, Subscription: license.Subscription,

View file

@ -47,6 +47,16 @@ type (
Hash string `json:"-"` Hash string `json:"-"`
} }
// UserParams defines user query parameters.
UserParams struct {
// Sort instructs the system to sort by Login if true,
// else sort by primary key.
Sort bool
Page int64
Size int64
}
// UserStore defines operations for working with users. // UserStore defines operations for working with users.
UserStore interface { UserStore interface {
// Find returns a user from the datastore. // Find returns a user from the datastore.
@ -61,6 +71,9 @@ type (
// List returns a list of users from the datastore. // List returns a list of users from the datastore.
List(context.Context) ([]*User, error) List(context.Context) ([]*User, error)
// ListRange returns a range of users from the datastore.
ListRange(context.Context, UserParams) ([]*User, error)
// Create persists a new user to the datastore. // Create persists a new user to the datastore.
Create(context.Context, *User) error Create(context.Context, *User) error

2
go.mod
View file

@ -15,7 +15,7 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/drone/drone-go v1.4.1-0.20201109202657-b9e58bbbcf27 github.com/drone/drone-go v1.4.1-0.20201109202657-b9e58bbbcf27
github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d
github.com/drone/drone-ui v0.0.0-20210505020539-1b93fc25c7d8 github.com/drone/drone-ui v0.0.0-20210512200715-d96f1e26d448
github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4 github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629
github.com/drone/go-license v1.0.2 github.com/drone/go-license v1.0.2

2
go.sum
View file

@ -116,6 +116,8 @@ github.com/drone/drone-ui v0.0.0-20210427231613-96a9f6e17fb7 h1:EUvu5J51N2diuFqL
github.com/drone/drone-ui v0.0.0-20210427231613-96a9f6e17fb7/go.mod h1:NBtVWW7NNJpD9+huMD/5TAE1db2nrEh0i35/9Rf1MPI= github.com/drone/drone-ui v0.0.0-20210427231613-96a9f6e17fb7/go.mod h1:NBtVWW7NNJpD9+huMD/5TAE1db2nrEh0i35/9Rf1MPI=
github.com/drone/drone-ui v0.0.0-20210505020539-1b93fc25c7d8 h1:mIFBOdP8Tif/4li4bmiVjqp6vbxMpTHOuZR80eypm6A= github.com/drone/drone-ui v0.0.0-20210505020539-1b93fc25c7d8 h1:mIFBOdP8Tif/4li4bmiVjqp6vbxMpTHOuZR80eypm6A=
github.com/drone/drone-ui v0.0.0-20210505020539-1b93fc25c7d8/go.mod h1:NBtVWW7NNJpD9+huMD/5TAE1db2nrEh0i35/9Rf1MPI= github.com/drone/drone-ui v0.0.0-20210505020539-1b93fc25c7d8/go.mod h1:NBtVWW7NNJpD9+huMD/5TAE1db2nrEh0i35/9Rf1MPI=
github.com/drone/drone-ui v0.0.0-20210512200715-d96f1e26d448 h1:skfTTwMRWSSi3Dv5NrpU8mJn7faccG5q+lqiBQikLiw=
github.com/drone/drone-ui v0.0.0-20210512200715-d96f1e26d448/go.mod h1:NBtVWW7NNJpD9+huMD/5TAE1db2nrEh0i35/9Rf1MPI=
github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4 h1:XsstoCeXC2t8lA9OLTdoFwckaptqahxwjCWsenySfX8= github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4 h1:XsstoCeXC2t8lA9OLTdoFwckaptqahxwjCWsenySfX8=
github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10= github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10=
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 h1:rIaZZalMGGPb2cU/+ypuggZ8aMlpa17RUlJUtsMv8pw= github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 h1:rIaZZalMGGPb2cU/+ypuggZ8aMlpa17RUlJUtsMv8pw=

View file

@ -70,11 +70,13 @@ func HandleLogin(
logger := logrus.WithField("login", account.Login) logger := logrus.WithField("login", account.Login)
logger.Debugf("attempting authentication") logger.Debugf("attempting authentication")
redirect := "/"
user, err := users.FindLogin(ctx, account.Login) user, err := users.FindLogin(ctx, account.Login)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
redirect = "/register"
user = &core.User{ user = &core.User{
Login: account.Login, Login: account.Login,
Email: account.Email,
Avatar: account.Avatar, Avatar: account.Avatar,
Admin: false, Admin: false,
Machine: false, Machine: false,
@ -140,7 +142,6 @@ func HandleLogin(
} }
user.Avatar = account.Avatar user.Avatar = account.Avatar
user.Email = account.Email
user.Token = tok.Access user.Token = tok.Access
user.Refresh = tok.Refresh user.Refresh = tok.Refresh
user.LastLogin = time.Now().Unix() user.LastLogin = time.Now().Unix()
@ -169,10 +170,16 @@ func HandleLogin(
go synchronize(ctx, syncer, user) go synchronize(ctx, syncer, user)
} }
// If the user account has not completed registration,
// redirect to the registration form.
if len(user.Email) == 0 && user.Created > 1619841600 {
redirect = "/register"
}
logger.Debugf("authentication successful") logger.Debugf("authentication successful")
session.Create(w, user) session.Create(w, user)
http.Redirect(w, r, "/", 303) http.Redirect(w, r, redirect, 303)
} }
} }

View file

@ -19,8 +19,6 @@ type Config struct {
Endpoint string Endpoint string
Token string Token string
Contact1 string
Contact2 string
License string License string
Licensor string Licensor string
Subscription string Subscription string

View file

@ -90,6 +90,11 @@ func (d *Datadog) do(ctx context.Context, unix int64) error {
if err != nil { if err != nil {
return err return err
} }
userList, _ := d.users.ListRange(ctx, core.UserParams{
Sort: false,
Page: 1,
Size: 5,
})
tags := createTags(d.config) tags := createTags(d.config)
data := new(payload) data := new(payload)
data.Series = []series{ data.Series = []series{
@ -98,7 +103,7 @@ func (d *Datadog) do(ctx context.Context, unix int64) error {
Points: [][]int64{[]int64{unix, users}}, Points: [][]int64{[]int64{unix, users}},
Type: "gauge", Type: "gauge",
Host: d.system.Host, Host: d.system.Host,
Tags: tags, Tags: append(tags, createInstallerTags(userList)...),
}, },
{ {
Metric: "drone.repos", Metric: "drone.repos",

View file

@ -18,6 +18,7 @@ import (
"context" "context"
"testing" "testing"
"github.com/drone/drone/core"
"github.com/drone/drone/mock" "github.com/drone/drone/mock"
"github.com/drone/drone/version" "github.com/drone/drone/version"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
@ -38,6 +39,7 @@ func TestDo(t *testing.T) {
users := mock.NewMockUserStore(controller) users := mock.NewMockUserStore(controller)
users.EXPECT().Count(gomock.Any()).Return(int64(10), nil) users.EXPECT().Count(gomock.Any()).Return(int64(10), nil)
users.EXPECT().ListRange(gomock.Any(), gomock.Any()).Return([]*core.User{{Email: "jane@acme.com"}}, nil)
repos := mock.NewMockRepositoryStore(controller) repos := mock.NewMockRepositoryStore(controller)
repos.EXPECT().Count(gomock.Any()).Return(int64(20), nil) repos.EXPECT().Count(gomock.Any()).Return(int64(20), nil)
@ -73,7 +75,7 @@ var sample = `{
"points": [[915148800, 10]], "points": [[915148800, 10]],
"type": "gauge", "type": "gauge",
"host": "test.example.com", "host": "test.example.com",
"tags": ["version:` + version.Version.String() + `","remote:github:cloud","scheduler:internal:agents","license:trial"] "tags": ["version:` + version.Version.String() + `","remote:github:cloud","scheduler:internal:agents","license:trial","installer:jane@acme.com"]
}, },
{ {
"metric": "drone.repos", "metric": "drone.repos",

View file

@ -17,6 +17,7 @@ package sink
import ( import (
"fmt" "fmt"
"github.com/drone/drone/core"
"github.com/drone/drone/version" "github.com/drone/drone/version"
) )
@ -68,14 +69,21 @@ func createTags(config Config) []string {
tag := fmt.Sprintf("license:%s", config.License) tag := fmt.Sprintf("license:%s", config.License)
tags = append(tags, tag) tags = append(tags, tag)
} }
return tags
}
if config.Contact1 != "" { func createInstallerTags(users []*core.User) []string {
tag := fmt.Sprintf("contact1:%s", config.Contact1) var tags []string
tags = append(tags, tag) for _, user := range users {
} if user.Machine {
if config.Contact2 != "" { continue
tag := fmt.Sprintf("contact2:%s", config.Contact2) }
if len(user.Email) == 0 {
continue
}
tag := fmt.Sprintf("installer:%s", user.Email)
tags = append(tags, tag) tags = append(tags, tag)
break
} }
return tags return tags
} }

View file

@ -2070,6 +2070,21 @@ func (mr *MockUserStoreMockRecorder) List(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockUserStore)(nil).List), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockUserStore)(nil).List), arg0)
} }
// ListRange mocks base method
func (m *MockUserStore) ListRange(arg0 context.Context, arg1 core.UserParams) ([]*core.User, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListRange", arg0, arg1)
ret0, _ := ret[0].([]*core.User)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListRange indicates an expected call of ListRange
func (mr *MockUserStoreMockRecorder) ListRange(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListRange", reflect.TypeOf((*MockUserStore)(nil).ListRange), arg0, arg1)
}
// Update mocks base method // Update mocks base method
func (m *MockUserStore) Update(arg0 context.Context, arg1 *core.User) error { func (m *MockUserStore) Update(arg0 context.Context, arg1 *core.User) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View file

@ -16,6 +16,7 @@ package user
import ( import (
"context" "context"
"fmt"
"github.com/drone/drone/core" "github.com/drone/drone/core"
"github.com/drone/drone/store/shared/db" "github.com/drone/drone/store/shared/db"
@ -91,6 +92,31 @@ func (s *userStore) List(ctx context.Context) ([]*core.User, error) {
return out, err return out, err
} }
// ListRange returns a list of users from the datastore.
func (s *userStore) ListRange(ctx context.Context, params core.UserParams) ([]*core.User, error) {
var out []*core.User
err := s.db.View(func(queryer db.Queryer, binder db.Binder) error {
// this query breaks a rule and uses sprintf to inject parameters
// into the query. Normally this should be avoided, however, in this
// case the parameters are set by the internal system and can
// be considered safe.
query := queryRange
switch {
case params.Sort:
query = fmt.Sprintf(query, "user_login", params.Size, params.Page)
default:
query = fmt.Sprintf(query, "user_id", params.Size, params.Page)
}
rows, err := queryer.Query(query)
if err != nil {
return err
}
out, err = scanRows(s.enc, rows)
return err
})
return out, err
}
// Create persists a new user to the datastore. // Create persists a new user to the datastore.
func (s *userStore) Create(ctx context.Context, user *core.User) error { func (s *userStore) Create(ctx context.Context, user *core.User) error {
if s.db.Driver() == db.Postgres { if s.db.Driver() == db.Postgres {
@ -235,6 +261,13 @@ FROM users
ORDER BY user_login ORDER BY user_login
` `
const queryRange = queryBase + `
FROM users
ORDER BY %s
LIMIT %d
OFFSET %d
`
const stmtUpdate = ` const stmtUpdate = `
UPDATE users UPDATE users
SET SET