Users bugfixes + tests (#19)

Co-authored-by: Asim Aslam <asim@aslam.me>
This commit is contained in:
Janos Dobronszki
2020-10-26 17:49:03 +01:00
committed by GitHub
parent 9601ad952c
commit 0e356aef01
9 changed files with 416 additions and 106 deletions

View File

@@ -1,10 +1,10 @@
name: Blog integration tests name: Integration tests
on: [push] on: [push]
jobs: jobs:
test: test:
name: Blog integration tests name: Integration tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up Go 1.13 - name: Set up Go 1.13
@@ -26,7 +26,7 @@ jobs:
with: with:
repository: 'micro/micro' repository: 'micro/micro'
path: 'micro' path: 'micro'
ref: '20cabee1960e6abe8b59d8f178ddf66ad5da1097' ref: 'v3.0.0-beta.7'
- name: Enable caching - name: Enable caching
uses: actions/cache@v2 uses: actions/cache@v2
@@ -52,5 +52,5 @@ jobs:
- name: Test Blog services - name: Test Blog services
working-directory: services/test/integration working-directory: services/test/integration
run: | run: |
go clean -testcache && GOMAXPROCS=4 go test -timeout 15m --tags=blog -v ./... go clean -testcache && GOMAXPROCS=4 go test -timeout 15m --tags=integration -v ./...

6
go.mod
View File

@@ -3,12 +3,12 @@ module github.com/micro/services
go 1.14 go 1.14
require ( require (
github.com/go-sql-driver/mysql v1.5.0 github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/golang/protobuf v1.4.3 github.com/golang/protobuf v1.4.3
github.com/google/uuid v1.1.2 github.com/google/uuid v1.1.2
github.com/gosimple/slug v1.9.0 github.com/gosimple/slug v1.9.0
github.com/micro/dev v0.0.0-20201023140212-49030ae8a31f github.com/micro/dev v0.0.0-20201026103917-a7b0e7877fa5
github.com/micro/go-micro/v2 v2.9.1 github.com/micro/go-micro/v2 v2.9.1 // indirect
github.com/micro/micro/v3 v3.0.0-beta.7 github.com/micro/micro/v3 v3.0.0-beta.7
github.com/miekg/dns v1.1.31 // indirect github.com/miekg/dns v1.1.31 // indirect
github.com/ulikunitz/xz v0.5.8 // indirect github.com/ulikunitz/xz v0.5.8 // indirect

2
go.sum
View File

@@ -332,6 +332,8 @@ github.com/micro/dev v0.0.0-20201022161742-461eaa38c096 h1:rzeONQC+ZgR5otGpJHb0N
github.com/micro/dev v0.0.0-20201022161742-461eaa38c096/go.mod h1:j/8E+ezN/ij7a9BXBHMKmLayFfUW1O4h/Owdv67B0X0= github.com/micro/dev v0.0.0-20201022161742-461eaa38c096/go.mod h1:j/8E+ezN/ij7a9BXBHMKmLayFfUW1O4h/Owdv67B0X0=
github.com/micro/dev v0.0.0-20201023140212-49030ae8a31f h1:V9kC0gSrAUgXT3o5gMzQ3f1ILp8+xNUB53UVuwjH66M= github.com/micro/dev v0.0.0-20201023140212-49030ae8a31f h1:V9kC0gSrAUgXT3o5gMzQ3f1ILp8+xNUB53UVuwjH66M=
github.com/micro/dev v0.0.0-20201023140212-49030ae8a31f/go.mod h1:j/8E+ezN/ij7a9BXBHMKmLayFfUW1O4h/Owdv67B0X0= github.com/micro/dev v0.0.0-20201023140212-49030ae8a31f/go.mod h1:j/8E+ezN/ij7a9BXBHMKmLayFfUW1O4h/Owdv67B0X0=
github.com/micro/dev v0.0.0-20201026103917-a7b0e7877fa5 h1:TKVhBhhLeJyWihKdg7bDd7J+h6MWx2Y0niEMmTfyOOw=
github.com/micro/dev v0.0.0-20201026103917-a7b0e7877fa5/go.mod h1:j/8E+ezN/ij7a9BXBHMKmLayFfUW1O4h/Owdv67B0X0=
github.com/micro/go-micro v1.18.0 h1:gP70EZVHpJuUIT0YWth192JmlIci+qMOEByHm83XE9E= github.com/micro/go-micro v1.18.0 h1:gP70EZVHpJuUIT0YWth192JmlIci+qMOEByHm83XE9E=
github.com/micro/go-micro/v2 v2.9.1 h1:+S9koIrNWARjpP6k2TZ7kt0uC9zUJtNXzIdZTZRms7Q= github.com/micro/go-micro/v2 v2.9.1 h1:+S9koIrNWARjpP6k2TZ7kt0uC9zUJtNXzIdZTZRms7Q=
github.com/micro/go-micro/v2 v2.9.1/go.mod h1:x55ZM3Puy0FyvvkR3e0ha0xsE9DFwfPSUMWAIbFY0SY= github.com/micro/go-micro/v2 v2.9.1/go.mod h1:x55ZM3Puy0FyvvkR3e0ha0xsE9DFwfPSUMWAIbFY0SY=

View File

@@ -1,4 +1,4 @@
// +build blog // +build integration
package signup package signup

View File

@@ -0,0 +1,235 @@
// +build integration
package signup
import (
"encoding/json"
"errors"
"math/rand"
"os"
"os/exec"
"strings"
"testing"
"time"
"github.com/micro/micro/v3/test"
)
const (
retryCount = 1
)
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz")
func randStringRunes(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
func setupUsersTests(serv test.Server, t *test.T) {
envToConfigKey := map[string][]string{}
if err := test.Try("Set up config values", t, func() ([]byte, error) {
for envKey, configKeys := range envToConfigKey {
val := os.Getenv(envKey)
if len(val) == 0 {
t.Fatalf("'%v' flag is missing", envKey)
}
for _, configKey := range configKeys {
outp, err := serv.Command().Exec("config", "set", configKey, val)
if err != nil {
return outp, err
}
}
}
return serv.Command().Exec("config", "set", "micro.billing.max_included_services", "3")
}, 10*time.Second); err != nil {
t.Fatal(err)
return
}
services := []struct {
envVar string
deflt string
}{
{envVar: "POSTS_SVC", deflt: "../../../users"},
}
for _, v := range services {
outp, err := serv.Command().Exec("run", v.deflt)
if err != nil {
t.Fatal(string(outp))
return
}
}
if err := test.Try("Find posts and tags", t, func() ([]byte, error) {
outp, err := serv.Command().Exec("services")
if err != nil {
return outp, err
}
list := []string{"users"}
logOutp := []byte{}
fail := false
for _, s := range list {
if !strings.Contains(string(outp), s) {
o, _ := serv.Command().Exec("logs", s)
logOutp = append(logOutp, o...)
fail = true
}
}
if fail {
return append(outp, logOutp...), errors.New("Can't find required services in list")
}
return outp, err
}, 180*time.Second); err != nil {
return
}
// setup rules
// Adjust rules before we signup into a non admin account
outp, err := serv.Command().Exec("auth", "create", "rule", "--access=granted", "--scope=''", "--resource=\"service:users:*\"", "users")
if err != nil {
t.Fatalf("Error setting up rules: %v", outp)
return
}
// copy the config with the admin logged in so we can use it for reading logs
// we dont want to have an open access rule for logs as it's not how it works in live
confPath := serv.Command().Config
outp, err = exec.Command("cp", "-rf", confPath, confPath+".admin").CombinedOutput()
if err != nil {
t.Fatalf("Error copying config: %v", outp)
return
}
}
func TestUsersService(t *testing.T) {
test.TrySuite(t, testUsers, retryCount)
}
func testUsers(t *test.T) {
t.Parallel()
serv := test.NewServer(t, test.WithLogin())
defer serv.Close()
if err := serv.Run(); err != nil {
return
}
setupUsersTests(serv, t)
cmd := serv.Command()
email := "test@gmail.com"
password := "testPassw"
username := "john"
id := "7"
if err := test.Try("Save user", t, func() ([]byte, error) {
// Attention! The content must be unquoted, don't add quotes.
outp, err := cmd.Exec("users", "create", "--id="+id, "--email="+email, "--password="+password, "--username=john")
if err != nil {
outp1, _ := cmd.Exec("logs", "users")
return append(outp, outp1...), err
}
return outp, err
}, 15*time.Second); err != nil {
return
}
outp, err := cmd.Exec("users", "read", "--id="+id)
if err != nil {
t.Fatal(string(outp), err)
return
}
if !strings.Contains(string(outp), email) ||
!strings.Contains(string(outp), username) ||
!strings.Contains(string(outp), id) {
t.Fatal(string(outp))
return
}
// no password
outp, err = cmd.Exec("users", "login", "--email="+email)
if err == nil {
t.Fatal(string(outp))
return
}
// wrong password
outp, err = cmd.Exec("users", "login", "--email="+email, "--password=somethingincorrect")
if err == nil {
t.Fatal(string(outp))
return
}
outp, err = cmd.Exec("users", "login", "--username="+username, "--password="+password)
if err != nil {
t.Fatal(string(outp), err)
return
}
loginRsp := map[string]interface{}{}
err = json.Unmarshal(outp, &loginRsp)
if err != nil {
t.Fatal(err)
return
}
session, ok := loginRsp["session"].(map[string]interface{})
if !ok {
t.Fatal(string(outp))
return
}
sessionID := session["id"].(string)
sessionUsername := session["username"].(string)
if sessionUsername != username {
t.Fatal(string(outp))
return
}
if len(sessionID) == 0 {
t.Fatal(string(outp))
return
}
outp, err = cmd.Exec("users", "login", "--email="+email, "--password="+password)
if err != nil {
t.Fatal(string(outp), err)
return
}
outp, err = cmd.Exec("users", "login", "--email="+email, "--password="+password)
if err != nil {
t.Fatal(string(outp), err)
return
}
outp, err = cmd.Exec("users", "readSession", "--sessionId="+sessionID)
if err != nil {
t.Fatal(string(outp), err)
return
}
loginRsp = map[string]interface{}{}
err = json.Unmarshal(outp, &loginRsp)
if err != nil {
t.Fatal(err)
return
}
session, ok = loginRsp["session"].(map[string]interface{})
if !ok {
t.Fatal(string(outp))
return
}
sessionID = session["id"].(string)
sessionUsername = session["username"].(string)
if sessionUsername != username {
t.Fatal(string(outp))
return
}
}

View File

@@ -19,18 +19,33 @@ type Dao struct {
users model.Table users model.Table
sessions model.Table sessions model.Table
passwords model.Table passwords model.Table
nameIndex model.Index
emailIndex model.Index
idIndex model.Index
} }
func New() *Dao { func New() *Dao {
nameIndex := model.ByEquality("name") nameIndex := model.ByEquality("username")
nameIndex.Unique = true nameIndex.Unique = true
nameIndex.Order.Type = model.OrderTypeUnordered
emailIndex := model.ByEquality("email") emailIndex := model.ByEquality("email")
emailIndex.Unique = true emailIndex.Unique = true
emailIndex.Order.Type = model.OrderTypeUnordered
// @todo there should be a better way to get the default index from model
// than recreating the options here
idIndex := model.ByEquality("id")
idIndex.Order.Type = model.OrderTypeUnordered
return &Dao{ return &Dao{
users: model.NewTable(store.DefaultStore, "users", model.Indexes(nameIndex, emailIndex), nil), users: model.NewTable(store.DefaultStore, "users", model.Indexes(nameIndex, emailIndex), nil),
sessions: model.NewTable(store.DefaultStore, "sessions", nil, nil), sessions: model.NewTable(store.DefaultStore, "sessions", nil, nil),
passwords: model.NewTable(store.DefaultStore, "passwords", nil, nil), passwords: model.NewTable(store.DefaultStore, "passwords", nil, nil),
nameIndex: nameIndex,
emailIndex: emailIndex,
idIndex: idIndex,
} }
} }
@@ -47,13 +62,13 @@ func (dao *Dao) CreateSession(sess *user.Session) error {
} }
func (dao *Dao) DeleteSession(id string) error { func (dao *Dao) DeleteSession(id string) error {
return dao.sessions.Delete(model.Equals("id", id)) return dao.sessions.Delete(dao.idIndex.ToQuery(id))
} }
func (dao *Dao) ReadSession(id string) (*user.Session, error) { func (dao *Dao) ReadSession(id string) (*user.Session, error) {
sess := &user.Session{} sess := &user.Session{}
// @todo there should be a Read in the model to get rid of this pattern // @todo there should be a Read in the model to get rid of this pattern
return sess, dao.sessions.Read(model.Equals("id", id), &sess) return sess, dao.sessions.Read(dao.idIndex.ToQuery(id), &sess)
} }
func (dao *Dao) Create(user *user.User, salt string, password string) error { func (dao *Dao) Create(user *user.User, salt string, password string) error {
@@ -71,7 +86,7 @@ func (dao *Dao) Create(user *user.User, salt string, password string) error {
} }
func (dao *Dao) Delete(id string) error { func (dao *Dao) Delete(id string) error {
return dao.users.Delete(model.Equals("id", id)) return dao.users.Delete(dao.idIndex.ToQuery(id))
} }
func (dao *Dao) Update(user *user.User) error { func (dao *Dao) Update(user *user.User) error {
@@ -81,15 +96,15 @@ func (dao *Dao) Update(user *user.User) error {
func (dao *Dao) Read(id string) (*user.User, error) { func (dao *Dao) Read(id string) (*user.User, error) {
user := &user.User{} user := &user.User{}
return user, dao.users.Read(model.Equals("id", id), user) return user, dao.users.Read(dao.idIndex.ToQuery(id), user)
} }
func (dao *Dao) Search(username, email string, limit, offset int64) ([]*user.User, error) { func (dao *Dao) Search(username, email string, limit, offset int64) ([]*user.User, error) {
var query model.Query var query model.Query
if len(username) > 0 { if len(username) > 0 {
query = model.Equals("name", username) query = dao.nameIndex.ToQuery(username)
} else if len(email) > 0 { } else if len(email) > 0 {
query = model.Equals("email", email) query = dao.emailIndex.ToQuery(email)
} else { } else {
return nil, errors.New("username and email cannot be blank") return nil, errors.New("username and email cannot be blank")
} }
@@ -109,9 +124,9 @@ func (dao *Dao) UpdatePassword(id string, salt string, password string) error {
func (dao *Dao) SaltAndPassword(username, email string) (string, string, error) { func (dao *Dao) SaltAndPassword(username, email string) (string, string, error) {
var query model.Query var query model.Query
if len(username) > 0 { if len(username) > 0 {
query = model.Equals("name", username) query = dao.nameIndex.ToQuery(username)
} else if len(email) > 0 { } else if len(email) > 0 {
query = model.Equals("email", email) query = dao.emailIndex.ToQuery(email)
} else { } else {
return "", "", errors.New("username and email cannot be blank") return "", "", errors.New("username and email cannot be blank")
} }

View File

@@ -44,16 +44,21 @@ func NewUsers() *Users {
} }
func (s *Users) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error { func (s *Users) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error {
if len(req.Password) < 8 {
return errors.InternalServerError("users.Create.Check", "Password is less than 8 characters")
}
salt := random(16) salt := random(16)
h, err := bcrypt.GenerateFromPassword([]byte(x+salt+req.Password), 10) h, err := bcrypt.GenerateFromPassword([]byte(x+salt+req.Password), 10)
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.srv.user.Create", err.Error()) return errors.InternalServerError("users.Create", err.Error())
} }
pp := base64.StdEncoding.EncodeToString(h) pp := base64.StdEncoding.EncodeToString(h)
req.User.Username = strings.ToLower(req.User.Username) return s.dao.Create(&pb.User{
req.User.Email = strings.ToLower(req.User.Email) Id: req.Id,
return s.dao.Create(req.User, salt, pp) Username: strings.ToLower(req.Username),
Email: strings.ToLower(req.Email),
}, salt, pp)
} }
func (s *Users) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error { func (s *Users) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error {
@@ -66,9 +71,11 @@ func (s *Users) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadRespo
} }
func (s *Users) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error { func (s *Users) Update(ctx context.Context, req *pb.UpdateRequest, rsp *pb.UpdateResponse) error {
req.User.Username = strings.ToLower(req.User.Username) return s.dao.Update(&pb.User{
req.User.Email = strings.ToLower(req.User.Email) Id: req.Id,
return s.dao.Update(req.User) Username: strings.ToLower(req.Username),
Email: strings.ToLower(req.Email),
})
} }
func (s *Users) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.DeleteResponse) error { func (s *Users) Delete(ctx context.Context, req *pb.DeleteRequest, rsp *pb.DeleteResponse) error {
@@ -87,32 +94,35 @@ func (s *Users) Search(ctx context.Context, req *pb.SearchRequest, rsp *pb.Searc
func (s *Users) UpdatePassword(ctx context.Context, req *pb.UpdatePasswordRequest, rsp *pb.UpdatePasswordResponse) error { func (s *Users) UpdatePassword(ctx context.Context, req *pb.UpdatePasswordRequest, rsp *pb.UpdatePasswordResponse) error {
usr, err := s.dao.Read(req.UserId) usr, err := s.dao.Read(req.UserId)
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.srv.user.updatepassword", err.Error()) return errors.InternalServerError("users.updatepassword", err.Error())
}
if req.NewPassword != req.ConfirmPassword {
return errors.InternalServerError("users.updatepassword", "Passwords don't math")
} }
salt, hashed, err := s.dao.SaltAndPassword(usr.Username, usr.Email) salt, hashed, err := s.dao.SaltAndPassword(usr.Username, usr.Email)
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.srv.user.updatepassword", err.Error()) return errors.InternalServerError("users.updatepassword", err.Error())
} }
hh, err := base64.StdEncoding.DecodeString(hashed) hh, err := base64.StdEncoding.DecodeString(hashed)
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.srv.user.updatepassword", err.Error()) return errors.InternalServerError("users.updatepassword", err.Error())
} }
if err := bcrypt.CompareHashAndPassword(hh, []byte(x+salt+req.OldPassword)); err != nil { if err := bcrypt.CompareHashAndPassword(hh, []byte(x+salt+req.OldPassword)); err != nil {
return errors.Unauthorized("go.micro.srv.user.updatepassword", err.Error()) return errors.Unauthorized("users.updatepassword", err.Error())
} }
salt = random(16) salt = random(16)
h, err := bcrypt.GenerateFromPassword([]byte(x+salt+req.NewPassword), 10) h, err := bcrypt.GenerateFromPassword([]byte(x+salt+req.NewPassword), 10)
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.srv.user.updatepassword", err.Error()) return errors.InternalServerError("users.updatepassword", err.Error())
} }
pp := base64.StdEncoding.EncodeToString(h) pp := base64.StdEncoding.EncodeToString(h)
if err := s.dao.UpdatePassword(req.UserId, salt, pp); err != nil { if err := s.dao.UpdatePassword(req.UserId, salt, pp); err != nil {
return errors.InternalServerError("go.micro.srv.user.updatepassword", err.Error()) return errors.InternalServerError("users.updatepassword", err.Error())
} }
return nil return nil
} }
@@ -128,22 +138,23 @@ func (s *Users) Login(ctx context.Context, req *pb.LoginRequest, rsp *pb.LoginRe
hh, err := base64.StdEncoding.DecodeString(hashed) hh, err := base64.StdEncoding.DecodeString(hashed)
if err != nil { if err != nil {
return errors.InternalServerError("go.micro.srv.user.Login", err.Error()) return errors.InternalServerError("users.Login", err.Error())
} }
if err := bcrypt.CompareHashAndPassword(hh, []byte(x+salt+req.Password)); err != nil { if err := bcrypt.CompareHashAndPassword(hh, []byte(x+salt+req.Password)); err != nil {
return errors.Unauthorized("go.micro.srv.user.login", err.Error()) return errors.Unauthorized("users.login", err.Error())
} }
// save session // save session
sess := &pb.Session{ sess := &pb.Session{
Id: random(128), Id: random(128),
Username: username, Username: username,
Email: email,
Created: time.Now().Unix(), Created: time.Now().Unix(),
Expires: time.Now().Add(time.Hour * 24 * 7).Unix(), Expires: time.Now().Add(time.Hour * 24 * 7).Unix(),
} }
if err := s.dao.CreateSession(sess); err != nil { if err := s.dao.CreateSession(sess); err != nil {
return errors.InternalServerError("go.micro.srv.user.Login", err.Error()) return errors.InternalServerError("users.Login", err.Error())
} }
rsp.Session = sess rsp.Session = sess
return nil return nil

View File

@@ -94,8 +94,9 @@ func (m *User) GetUpdated() int64 {
type Session struct { type Session struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
Created int64 `protobuf:"varint,3,opt,name=created,proto3" json:"created,omitempty"` Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
Expires int64 `protobuf:"varint,4,opt,name=expires,proto3" json:"expires,omitempty"` Created int64 `protobuf:"varint,4,opt,name=created,proto3" json:"created,omitempty"`
Expires int64 `protobuf:"varint,5,opt,name=expires,proto3" json:"expires,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@@ -140,6 +141,13 @@ func (m *Session) GetUsername() string {
return "" return ""
} }
func (m *Session) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *Session) GetCreated() int64 { func (m *Session) GetCreated() int64 {
if m != nil { if m != nil {
return m.Created return m.Created
@@ -155,8 +163,10 @@ func (m *Session) GetExpires() int64 {
} }
type CreateRequest struct { type CreateRequest struct {
User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@@ -187,11 +197,25 @@ func (m *CreateRequest) XXX_DiscardUnknown() {
var xxx_messageInfo_CreateRequest proto.InternalMessageInfo var xxx_messageInfo_CreateRequest proto.InternalMessageInfo
func (m *CreateRequest) GetUser() *User { func (m *CreateRequest) GetId() string {
if m != nil { if m != nil {
return m.User return m.Id
} }
return nil return ""
}
func (m *CreateRequest) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *CreateRequest) GetEmail() string {
if m != nil {
return m.Email
}
return ""
} }
func (m *CreateRequest) GetPassword() string { func (m *CreateRequest) GetPassword() string {
@@ -381,7 +405,9 @@ func (m *ReadResponse) GetUser() *User {
} }
type UpdateRequest struct { type UpdateRequest struct {
User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@@ -412,11 +438,25 @@ func (m *UpdateRequest) XXX_DiscardUnknown() {
var xxx_messageInfo_UpdateRequest proto.InternalMessageInfo var xxx_messageInfo_UpdateRequest proto.InternalMessageInfo
func (m *UpdateRequest) GetUser() *User { func (m *UpdateRequest) GetId() string {
if m != nil { if m != nil {
return m.User return m.Id
} }
return nil return ""
}
func (m *UpdateRequest) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *UpdateRequest) GetEmail() string {
if m != nil {
return m.Email
}
return ""
} }
type UpdateResponse struct { type UpdateResponse struct {
@@ -454,7 +494,7 @@ type UpdatePasswordRequest struct {
UserId string `protobuf:"bytes,1,opt,name=userId,proto3" json:"userId,omitempty"` UserId string `protobuf:"bytes,1,opt,name=userId,proto3" json:"userId,omitempty"`
OldPassword string `protobuf:"bytes,2,opt,name=oldPassword,proto3" json:"oldPassword,omitempty"` OldPassword string `protobuf:"bytes,2,opt,name=oldPassword,proto3" json:"oldPassword,omitempty"`
NewPassword string `protobuf:"bytes,3,opt,name=newPassword,proto3" json:"newPassword,omitempty"` NewPassword string `protobuf:"bytes,3,opt,name=newPassword,proto3" json:"newPassword,omitempty"`
ConfirmPassword string `protobuf:"bytes,4,opt,name=confirmPassword,proto3" json:"confirmPassword,omitempty"` ConfirmPassword string `protobuf:"bytes,4,opt,name=confirm_password,json=confirmPassword,proto3" json:"confirm_password,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@@ -911,46 +951,48 @@ func init() {
proto.RegisterType((*LogoutResponse)(nil), "LogoutResponse") proto.RegisterType((*LogoutResponse)(nil), "LogoutResponse")
} }
func init() { proto.RegisterFile("proto/users.proto", fileDescriptor_b1c161a4c7514913) } func init() {
proto.RegisterFile("proto/users.proto", fileDescriptor_b1c161a4c7514913)
}
var fileDescriptor_b1c161a4c7514913 = []byte{ var fileDescriptor_b1c161a4c7514913 = []byte{
// 605 bytes of a gzipped FileDescriptorProto // 600 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0x4f, 0x6f, 0xd3, 0x4e, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x55, 0xcf, 0x6e, 0xd3, 0x4e,
0x10, 0xb5, 0xe3, 0x38, 0x69, 0x27, 0xb1, 0xdd, 0xdf, 0x36, 0xbf, 0x60, 0x0c, 0x88, 0x68, 0x25, 0x10, 0x4e, 0xe2, 0x38, 0x69, 0x27, 0x71, 0xda, 0xdf, 0xb6, 0xbf, 0x60, 0x0c, 0x88, 0x6a, 0x25,
0xa4, 0x00, 0xea, 0x20, 0xa5, 0x27, 0xb8, 0x16, 0x21, 0x21, 0x71, 0xa8, 0x52, 0xf5, 0xc6, 0xc5, 0xa4, 0x56, 0xa8, 0x8b, 0x94, 0x9e, 0xe0, 0x5a, 0x2e, 0x48, 0x1c, 0xc0, 0x55, 0x6f, 0x48, 0xc8,
0xc4, 0x1b, 0xb0, 0x94, 0x78, 0x83, 0xd7, 0x51, 0x39, 0xf0, 0x55, 0xf8, 0x22, 0x7c, 0x3a, 0xb4, 0x24, 0x1b, 0xb0, 0x14, 0x7b, 0x8d, 0xd7, 0x51, 0x39, 0x20, 0xf1, 0x26, 0x3c, 0x08, 0x4f, 0xc7,
0xff, 0x12, 0xdb, 0x6d, 0x80, 0x72, 0xcb, 0xcc, 0xbc, 0xdd, 0x79, 0x3b, 0xf3, 0x9e, 0x03, 0xff, 0xec, 0xbf, 0xc4, 0x36, 0x8d, 0x04, 0xa8, 0xdc, 0x3c, 0x33, 0xdf, 0xec, 0x7c, 0x3b, 0x33, 0xdf,
0x6d, 0x4a, 0x5e, 0xf1, 0x57, 0x5b, 0xc1, 0x4a, 0x81, 0xea, 0x37, 0xfd, 0x0e, 0xdd, 0x6b, 0xc1, 0x1a, 0xfe, 0x2b, 0x4a, 0x51, 0x89, 0x67, 0x6b, 0xc9, 0x4b, 0xc9, 0xf4, 0x37, 0xfd, 0x0a, 0xfd,
0x4a, 0x12, 0x42, 0x27, 0xcf, 0x62, 0x77, 0xe2, 0x4e, 0x8f, 0xe7, 0x9d, 0x3c, 0x23, 0x09, 0x1c, 0x6b, 0x34, 0xc9, 0x04, 0x7a, 0xe9, 0x22, 0xec, 0x9e, 0x74, 0x4f, 0xf7, 0x63, 0xfc, 0x22, 0x11,
0x49, 0x58, 0x91, 0xae, 0x59, 0xdc, 0x51, 0xd9, 0x5d, 0x4c, 0x46, 0xe0, 0xb3, 0x75, 0x9a, 0xaf, 0xec, 0x29, 0x58, 0x9e, 0x64, 0x3c, 0xec, 0x69, 0xef, 0xc6, 0x26, 0xc7, 0xe0, 0xf3, 0x2c, 0x49,
0x62, 0x4f, 0x15, 0x74, 0x40, 0x62, 0xe8, 0x2f, 0x4a, 0x96, 0x56, 0x2c, 0x8b, 0xbb, 0x13, 0x77, 0x57, 0xa1, 0xa7, 0x03, 0xc6, 0x20, 0x21, 0x0c, 0xe7, 0x25, 0x4f, 0x2a, 0xbe, 0x08, 0xfb, 0xe8,
0xea, 0xcd, 0x6d, 0x28, 0x2b, 0xdb, 0x4d, 0xa6, 0x2a, 0xbe, 0xae, 0x98, 0x90, 0xe6, 0xd0, 0xbf, 0xf7, 0x62, 0x67, 0xaa, 0xc8, 0xba, 0x58, 0xe8, 0x88, 0x6f, 0x22, 0xd6, 0xa4, 0xdf, 0x60, 0x78,
0x62, 0x42, 0xe4, 0xbc, 0xb8, 0x17, 0x81, 0x5a, 0x2b, 0xef, 0x56, 0x2b, 0xf6, 0x6d, 0x93, 0x97, 0xc5, 0xa5, 0x4c, 0x45, 0xfe, 0xaf, 0x09, 0xf0, 0x2f, 0x45, 0x5a, 0x72, 0xe9, 0x08, 0x58, 0x93,
0x4c, 0x58, 0x12, 0x26, 0xa4, 0xef, 0x20, 0xb8, 0x50, 0xa0, 0x39, 0xfb, 0xba, 0x65, 0xa2, 0x22, 0x66, 0x10, 0x5c, 0x6a, 0x50, 0xcc, 0x3f, 0xaf, 0xb9, 0xac, 0xee, 0x80, 0x06, 0x66, 0x14, 0x89,
0x0f, 0xa1, 0x2b, 0x2f, 0x54, 0x2d, 0x07, 0x33, 0x1f, 0xe5, 0x18, 0xe6, 0x2a, 0x25, 0x7b, 0x6f, 0x94, 0x37, 0xa2, 0x34, 0x3c, 0x30, 0xc3, 0xd9, 0xf4, 0x10, 0x26, 0xae, 0x9c, 0x2c, 0x44, 0x2e,
0x52, 0x21, 0x6e, 0x78, 0x99, 0xd9, 0xde, 0x36, 0xa6, 0x27, 0x10, 0xda, 0x7b, 0xc4, 0x86, 0x17, 0x39, 0x7d, 0x0c, 0xc1, 0x4b, 0xbe, 0xe2, 0x3b, 0x09, 0xa8, 0x14, 0x07, 0xb0, 0x29, 0x8f, 0x60,
0x82, 0xd1, 0xa7, 0x10, 0xbc, 0x65, 0x2b, 0xb6, 0xbf, 0xb9, 0xf5, 0x14, 0x79, 0xc4, 0x02, 0xcc, 0x14, 0xf3, 0x64, 0xb1, 0x2b, 0xe1, 0x0c, 0xc6, 0x26, 0x6c, 0xe0, 0xe4, 0x3e, 0xf4, 0x15, 0x63,
0x91, 0x27, 0x30, 0x98, 0xb3, 0x34, 0x3b, 0x74, 0xe0, 0x39, 0x0c, 0x75, 0x59, 0xc3, 0x7f, 0x43, 0x8d, 0x18, 0xcd, 0x7c, 0xa6, 0xc6, 0x1d, 0x6b, 0x17, 0x7d, 0x0b, 0xc1, 0xb5, 0x9e, 0xc4, 0x9d,
0x95, 0xbe, 0x80, 0xe0, 0x5a, 0x0d, 0xf3, 0xcf, 0xcf, 0x92, 0x3c, 0x2c, 0xd6, 0xf0, 0xf8, 0xe1, 0xdd, 0x5e, 0xd1, 0x75, 0x47, 0x5a, 0xba, 0xdf, 0xbb, 0xf0, 0xbf, 0x71, 0xbd, 0xb1, 0x6d, 0x70,
0xc2, 0xff, 0x3a, 0x75, 0x69, 0xde, 0x67, 0xaf, 0x19, 0x43, 0x4f, 0x9e, 0x79, 0x6f, 0x69, 0x99, 0xd5, 0xa6, 0x30, 0x50, 0xa7, 0xbd, 0x72, 0x15, 0xad, 0x45, 0x4e, 0x60, 0x24, 0x56, 0x0b, 0x87,
0x88, 0x4c, 0x60, 0xc0, 0x57, 0xd9, 0x65, 0x73, 0x3a, 0xf5, 0x94, 0x44, 0x14, 0xec, 0x66, 0x87, 0xb6, 0x85, 0xeb, 0x2e, 0x85, 0xc8, 0xf9, 0xcd, 0x06, 0x61, 0x18, 0xd4, 0x5d, 0xe4, 0x0c, 0x0e,
0xd0, 0x1a, 0xa9, 0xa7, 0xc8, 0x14, 0xa2, 0x05, 0x2f, 0x96, 0x79, 0xb9, 0xde, 0xa1, 0xba, 0x0a, 0xe7, 0x22, 0x5f, 0xa6, 0x65, 0xf6, 0xbe, 0x35, 0x8d, 0x03, 0xeb, 0x77, 0x50, 0x1a, 0xc2, 0xb4,
0xd5, 0x4e, 0xd3, 0x18, 0xc6, 0x6d, 0x7a, 0x86, 0x39, 0x87, 0xe0, 0x8a, 0xa5, 0xe5, 0xe2, 0x8b, 0xcd, 0xcf, 0x52, 0x17, 0x10, 0x5c, 0xf1, 0xa4, 0x9c, 0x7f, 0x72, 0x8c, 0xeb, 0xfd, 0xe8, 0xee,
0x25, 0x5c, 0xd7, 0x8b, 0x7b, 0x48, 0xb0, 0x9d, 0xba, 0x60, 0x47, 0xe0, 0xaf, 0xf2, 0x75, 0x5e, 0xea, 0x47, 0xaf, 0xbe, 0x0d, 0xe8, 0x5d, 0xa5, 0x59, 0x5a, 0x69, 0x8e, 0x5e, 0x6c, 0x0c, 0x75,
0x19, 0x0d, 0xe9, 0x40, 0x3e, 0x9c, 0x2f, 0x97, 0x82, 0x55, 0x46, 0x40, 0x26, 0xa2, 0x67, 0x10, 0x73, 0xb1, 0x5c, 0x4a, 0x5e, 0xd9, 0x4d, 0xb5, 0x16, 0x3d, 0x87, 0x89, 0x2b, 0x68, 0xa7, 0xf7,
0xda, 0x86, 0x66, 0x2b, 0x8f, 0xc0, 0x57, 0x4e, 0x8a, 0xdd, 0x89, 0xb7, 0x1f, 0xb5, 0xce, 0xd1, 0x00, 0x7c, 0x2d, 0x57, 0x2c, 0xe7, 0x6d, 0xc7, 0x67, 0x7c, 0x74, 0x06, 0x44, 0x8d, 0xda, 0x4a,
0x19, 0x10, 0xb9, 0x42, 0xa3, 0x6e, 0x4b, 0xf2, 0x31, 0x1c, 0x0b, 0x9d, 0xd9, 0x0d, 0x76, 0x9f, 0xc8, 0x91, 0x7c, 0x08, 0xfb, 0xd2, 0x78, 0x36, 0x9d, 0xdd, 0x3a, 0xe8, 0x73, 0x38, 0x6a, 0xe4,
0xa0, 0xaf, 0xe1, 0xb4, 0x71, 0xc6, 0xf4, 0xa1, 0xd0, 0x37, 0x18, 0xb3, 0xd4, 0x23, 0xb4, 0x10, 0xd8, 0x3a, 0x14, 0x86, 0x16, 0x63, 0x17, 0x65, 0x8f, 0x39, 0x88, 0x0b, 0xd0, 0x77, 0x30, 0x7e,
0x5b, 0xa0, 0x1f, 0x61, 0xf8, 0x81, 0x7f, 0xce, 0x8b, 0x7f, 0x9f, 0x46, 0x5d, 0xf3, 0x5e, 0x4b, 0x2d, 0x3e, 0xa6, 0xf9, 0xdf, 0x77, 0xa3, 0xae, 0x0d, 0xaf, 0xa5, 0x8d, 0x0b, 0x08, 0xec, 0xe9,
0xf3, 0xe7, 0x10, 0x98, 0xdb, 0xef, 0x41, 0xe9, 0x4c, 0x1d, 0xe2, 0xdb, 0xea, 0xef, 0x1e, 0x7f, 0x7f, 0x40, 0xe9, 0x5c, 0x27, 0x89, 0x75, 0xf5, 0x7b, 0x97, 0xc7, 0xed, 0x74, 0x70, 0x53, 0x64,
0x02, 0xa1, 0x85, 0xeb, 0x26, 0xb3, 0x9f, 0x1e, 0xf8, 0x72, 0xa4, 0x82, 0xbc, 0x84, 0x9e, 0xf6, 0xf6, 0xc3, 0x03, 0x5f, 0xb5, 0x54, 0x92, 0xa7, 0x30, 0x30, 0xda, 0x24, 0x13, 0xd6, 0x78, 0x13,
0x1c, 0x09, 0xb1, 0x61, 0xe2, 0x24, 0xc2, 0x96, 0x19, 0x1d, 0xf2, 0x0c, 0xba, 0x72, 0x8a, 0x64, 0xa2, 0x03, 0xd6, 0x12, 0x6d, 0x87, 0x3c, 0x81, 0xbe, 0xea, 0x22, 0x19, 0xb3, 0x9a, 0x14, 0xa3,
0x88, 0x35, 0x8b, 0x25, 0x01, 0xd6, 0x1d, 0x45, 0x1d, 0x79, 0xa7, 0x96, 0x16, 0x09, 0xb1, 0xe1, 0x80, 0xd5, 0x95, 0x87, 0x30, 0x3c, 0xd3, 0xac, 0x16, 0x9e, 0xd9, 0x50, 0x1a, 0x9e, 0xd9, 0x92,
0xa0, 0x24, 0xc2, 0x96, 0x4b, 0x14, 0x58, 0x3b, 0x98, 0x84, 0xd8, 0xf0, 0x7a, 0x12, 0x61, 0xcb, 0x89, 0x06, 0x1b, 0xa5, 0x23, 0xb8, 0xf1, 0x26, 0x20, 0xb8, 0xf5, 0x04, 0x68, 0xb0, 0xd9, 0x14,
0xda, 0x0a, 0xac, 0x95, 0x42, 0x42, 0x6c, 0x68, 0x34, 0x89, 0xb0, 0x29, 0x21, 0xea, 0x90, 0x0b, 0x04, 0x37, 0x76, 0x14, 0xc1, 0xcd, 0x15, 0x42, 0xf0, 0xa5, 0x13, 0xe5, 0x46, 0x1e, 0x53, 0x76,
0xeb, 0xc9, 0x9d, 0x3b, 0xc6, 0x78, 0xa7, 0x23, 0x93, 0x07, 0x78, 0xc0, 0x0a, 0x0e, 0x99, 0x82, 0xab, 0x24, 0xa3, 0x7b, 0x6c, 0x87, 0x14, 0x3a, 0xe4, 0x14, 0x7c, 0x3d, 0x1f, 0x12, 0xb0, 0xfa,
0xaf, 0xf6, 0x43, 0x02, 0xac, 0xab, 0x20, 0x09, 0xb1, 0xb1, 0x36, 0xcd, 0x4d, 0x4f, 0x99, 0xa8, 0x16, 0x44, 0x13, 0xd6, 0x18, 0x9b, 0xe1, 0x66, 0xba, 0x4c, 0x74, 0x6c, 0x3b, 0x1d, 0xe4, 0xd6,
0xda, 0x7e, 0x3b, 0x49, 0x84, 0xcd, 0xf1, 0x53, 0x87, 0xbc, 0xd1, 0x5f, 0x29, 0xfb, 0x85, 0x3e, 0x6c, 0x3f, 0x82, 0x5f, 0x98, 0xd7, 0xcc, 0xfd, 0x06, 0x8e, 0xd8, 0xaf, 0x1b, 0x1d, 0x1d, 0xb3,
0xc5, 0xdb, 0x8a, 0x4e, 0x46, 0x78, 0x87, 0x64, 0xa9, 0xf3, 0xa9, 0xa7, 0xfe, 0x5e, 0xce, 0x7f, 0x5b, 0x56, 0x96, 0x76, 0x3e, 0x0c, 0xf4, 0x3f, 0xec, 0xe2, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff,
0x05, 0x00, 0x00, 0xff, 0xff, 0x41, 0x5e, 0x5d, 0x7f, 0x73, 0x06, 0x00, 0x00, 0xc7, 0x99, 0xc1, 0x0c, 0xd8, 0x06, 0x00, 0x00,
} }

View File

@@ -21,15 +21,18 @@ message User {
} }
message Session { message Session {
string id = 1; string id = 1;
string username = 2; string username = 2;
int64 created = 3; // unix string email = 3;
int64 expires = 4; // unix int64 created = 4; // unix
int64 expires = 5; // unix
} }
message CreateRequest { message CreateRequest {
User user = 1; string id = 1; // uuid
string password = 2; string username = 2; // alphanumeric user or org
string email = 3;
string password = 4;
} }
message CreateResponse { message CreateResponse {
@@ -51,17 +54,19 @@ message ReadResponse {
} }
message UpdateRequest { message UpdateRequest {
User user = 1; string id = 1; // uuid
string username = 2; // alphanumeric user or org
string email = 3;
} }
message UpdateResponse { message UpdateResponse {
} }
message UpdatePasswordRequest { message UpdatePasswordRequest {
string userId = 1; string userId = 1;
string oldPassword = 2; string oldPassword = 2;
string newPassword = 3; string newPassword = 3;
string confirmPassword = 4; string confirm_password = 4;
} }
message UpdatePasswordResponse { message UpdatePasswordResponse {
@@ -79,25 +84,25 @@ message SearchResponse {
} }
message ReadSessionRequest { message ReadSessionRequest {
string sessionId = 1; string sessionId = 1;
} }
message ReadSessionResponse { message ReadSessionResponse {
Session session = 1; Session session = 1;
} }
message LoginRequest { message LoginRequest {
string username = 1; string username = 1;
string email = 2; string email = 2;
string password = 3; string password = 3;
} }
message LoginResponse { message LoginResponse {
Session session = 1; Session session = 1;
} }
message LogoutRequest { message LogoutRequest {
string sessionId = 1; string sessionId = 1;
} }
message LogoutResponse { message LogoutResponse {