diff --git a/cmd/server/main.go b/cmd/server/main.go new file mode 100644 index 0000000..43b3026 --- /dev/null +++ b/cmd/server/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "flag" + "fmt" + "log" + "net" + + "git.chrishayward.xyz/x/users/proto" + "github.com/google/uuid" + "google.golang.org/grpc" +) + +var ( + secretDefault = uuid.NewString() + secret = flag.String("secret", secretDefault, "--secret=SECRET") + port = flag.Uint("port", 8080, "--port=8080") +) + +func main() { + // Parse the optional flags. + flag.Parse() + + // If the secret has not been set print it to the console. + if *secret == secretDefault { + fmt.Printf("SECRET=%s", secretDefault) + } + + // Create the network listener. + lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) + if err != nil { + log.Fatalf("Failed to listen: %v", err) + } + + // Start listening for requests. + srv := grpc.NewServer() + proto.RegisterUsersServer(srv, newUsersServer(secret)) + srv.Serve(lis) +} diff --git a/cmd/server/server.go b/cmd/server/server.go new file mode 100644 index 0000000..e082c57 --- /dev/null +++ b/cmd/server/server.go @@ -0,0 +1,192 @@ +package main + +import ( + "context" + "errors" + "log" + "time" + + "github.com/google/uuid" + "golang.org/x/crypto/bcrypt" + + "git.chrishayward.xyz/x/users/proto" +) + +type usersServer struct { + proto.UsersServer + secret *string + users UserDB + tokens TokenDB + resetTokens TokenDB +} + +func newUsersServer(secret *string) proto.UsersServer { + return &usersServer{ + secret: secret, + users: newInMemoryUserDB(), + tokens: newInMemoryTokenDB(), + resetTokens: newInMemoryTokenDB(), + } +} + +func (m *usersServer) Register(ctx context.Context, in *proto.RegisterRequest) (*proto.RegisterResponse, error) { + // Make sure both passwords are included and match. + if in.Form.Password == nil || in.Form.PasswordAgain == nil { + return nil, errors.New("Must include password(s).") + } + + if *in.Form.Password != *in.Form.PasswordAgain { + return nil, errors.New("Passwords do not match.") + } + + // Check for an existing user. + if u, _ := m.users.FindByEmail(in.Form.Email); u != nil { + return nil, errors.New("User already exists.") + } + + // Encode the password. + bytes, err := bcrypt.GenerateFromPassword([]byte(*in.Form.Password), bcrypt.MaxCost) + if err != nil { + log.Fatalf("Failed to encode password: %v", err) + return nil, errors.New("Failed to encode password.") + } + + // Create the new user. + if err := m.users.Save(&User{ + Email: in.Form.Email, + Password: string(bytes), + }); err != nil { + log.Fatalf("Failed to save user: %v", err) + return nil, errors.New("Failed to save user.") + } + + // Return the response. + return &proto.RegisterResponse{}, nil +} + +func (m *usersServer) Login(ctx context.Context, in *proto.LoginRequest) (*proto.LoginResponse, error) { + // Make sure the password is included. + if in.Form.Password == nil { + return nil, errors.New("Password must be included.") + } + + // Find the user. + user, err := m.users.FindByEmail(in.Form.Email) + if err != nil { + return nil, err + } + + // Compare the passwords. + if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(*in.Form.Password)); err != nil { + return nil, errors.New("Passwords do not match.") + } + + // Create a token. + expires := time.Now().AddDate(0, 0, 1) + token := &Token{ + UserID: user.ID, + Token: uuid.NewString(), + Expires: &expires, + } + + // Save the token. + m.tokens.Save(token) + + // Return the response. + expiresNano := expires.UnixNano() + return &proto.LoginResponse{ + Token: &proto.UserToken{ + Token: token.Token, + Expires: &expiresNano, + }, + }, nil +} + +func (m *usersServer) Authorize(ctx context.Context, in *proto.AuthorizeRequest) (*proto.AuthorizeResponse, error) { + // Make sure the secrets match. + if in.Secret != *m.secret { + return nil, errors.New("Secrets do not match.") + } + + // Find the token. + token, err := m.tokens.FindByToken(in.Token.Token) + if err != nil { + return nil, err + } + + // Make sure the token hasn't expired. + if token.Expires.After(time.Now()) { + return nil, errors.New("Token is expired.") + } + + // Return the user ID. + return &proto.AuthorizeResponse{ + User: &proto.UserInfo{ + Id: int64(token.UserID), + }, + }, nil +} + +func (m *usersServer) ResetPassword(ctx context.Context, in *proto.ResetPasswordRequest) (*proto.ResetPasswordResponse, error) { + // Find the user. + user, err := m.users.FindByEmail(in.Form.Email) + if err != nil { + return nil, err + } + + // Generate a reset token. + expires := time.Now().AddDate(0, 0, 1) + token := &Token{ + UserID: user.ID, + Token: uuid.NewString(), + Expires: &expires, + } + + // Save the token. + if err := m.resetTokens.Save(token); err != nil { + return nil, err + } + + // Return the response. + return &proto.ResetPasswordResponse{ + Token: &proto.UserToken{ + Token: token.Token, + }, + }, nil +} + +func (m *usersServer) ChangePassword(ctx context.Context, in *proto.ChangePasswordRequest) (*proto.ChangePasswordResponse, error) { + // Find the reset token. + resetToken, err := m.resetTokens.FindByToken(in.Token.Token) + if err != nil { + return nil, err + } + + // Find the user. + user, err := m.users.FindByID(resetToken.UserID) + if err != nil { + return nil, err + } + + // Update the password. + bytes, err := bcrypt.GenerateFromPassword([]byte(*in.Form.Password), bcrypt.MaxCost) + if err != nil { + log.Fatalf("Failed to encode password: %v", err) + return nil, errors.New("Failed to encode password.") + } + + user.Password = string(bytes) + if err := m.users.Save(user); err != nil { + return nil, err + } + + // Expire current token. + if token, err := m.tokens.FindByUserID(user.ID); token != nil && err == nil { + expires := time.Now() + token.Expires = &expires + _ = m.tokens.Save(token) + } + + // Return the response. + return nil, nil +} diff --git a/cmd/server/token_db.go b/cmd/server/token_db.go new file mode 100644 index 0000000..70227d2 --- /dev/null +++ b/cmd/server/token_db.go @@ -0,0 +1,60 @@ +package main + +import ( + "errors" + "time" +) + +type Token struct { + UserID int64 + Token string + Expires *time.Time +} + +type TokenDB interface { + FindByUserID(id int64) (*Token, error) + FindByToken(token string) (*Token, error) + Save(token *Token) error +} + +type inMemoryTokenDB struct { + tokens []*Token +} + +func newInMemoryTokenDB() *inMemoryTokenDB { + return &inMemoryTokenDB{ + tokens: make([]*Token, 0), + } +} + +func (m *inMemoryTokenDB) FindByUserID(id int64) (*Token, error) { + for _, t := range m.tokens { + if t.UserID == id { + return t, nil + } + } + + return nil, errors.New("Token not found.") +} + +func (m *inMemoryTokenDB) FindByToken(token string) (*Token, error) { + for _, t := range m.tokens { + if t.Token == token { + return t, nil + } + } + + return nil, errors.New("Token not found.") +} + +func (m *inMemoryTokenDB) Save(token *Token) error { + for i, t := range m.tokens { + if t.UserID == token.UserID || t.Token == token.Token { + m.tokens[i] = token + return nil + } + } + + m.tokens = append(m.tokens, token) + return nil +} diff --git a/cmd/server/user_db.go b/cmd/server/user_db.go new file mode 100644 index 0000000..ba95507 --- /dev/null +++ b/cmd/server/user_db.go @@ -0,0 +1,62 @@ +package main + +import "errors" + +type User struct { + ID int64 + Email string + Password string +} + +type UserDB interface { + FindByID(id int64) (*User, error) + FindByEmail(email string) (*User, error) + Save(*User) error +} + +type inMemoryUserDB struct { + UserDB + nextID int + users []*User +} + +func newInMemoryUserDB() *inMemoryUserDB { + return &inMemoryUserDB{ + nextID: 1, + users: make([]*User, 0), + } +} + +func (m *inMemoryUserDB) FindByID(id int64) (*User, error) { + for _, u := range m.users { + if u.ID == id { + return u, nil + } + } + + return nil, errors.New("User not found.") +} + +func (m *inMemoryUserDB) FindByEmail(email string) (*User, error) { + for _, u := range m.users { + if u.Email == email { + return u, nil + } + } + + return nil, errors.New("User not found.") +} + +func (m *inMemoryUserDB) Save(user *User) error { + for i, u := range m.users { + if u.ID == user.ID || u.Email == user.Email { + m.users[i] = user + return nil + } + } + + user.ID = m.nextID + m.users = append(m.users, user) + m.nextID++ + return nil +} diff --git a/go.mod b/go.mod index 6e98647..453ed1b 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,18 @@ module git.chrishayward.xyz/x/users go 1.20 + +require ( + github.com/google/uuid v1.3.0 + golang.org/x/crypto v0.10.0 + google.golang.org/grpc v1.56.1 + google.golang.org/protobuf v1.31.0 +) + +require ( + github.com/golang/protobuf v1.5.3 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/text v0.10.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..354baa0 --- /dev/null +++ b/go.sum @@ -0,0 +1,24 @@ +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ= +google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/proto/users.pb.go b/proto/users.pb.go index 0083cbe..7a61cfc 100644 --- a/proto/users.pb.go +++ b/proto/users.pb.go @@ -466,7 +466,7 @@ func (x *AuthorizeResponse) GetUser() *UserInfo { return nil } -type ChangePasswordRequest struct { +type ResetPasswordRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -474,8 +474,8 @@ type ChangePasswordRequest struct { Form *UserForm `protobuf:"bytes,1,opt,name=form,proto3" json:"form,omitempty"` } -func (x *ChangePasswordRequest) Reset() { - *x = ChangePasswordRequest{} +func (x *ResetPasswordRequest) Reset() { + *x = ResetPasswordRequest{} if protoimpl.UnsafeEnabled { mi := &file_proto_users_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -483,13 +483,13 @@ func (x *ChangePasswordRequest) Reset() { } } -func (x *ChangePasswordRequest) String() string { +func (x *ResetPasswordRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ChangePasswordRequest) ProtoMessage() {} +func (*ResetPasswordRequest) ProtoMessage() {} -func (x *ChangePasswordRequest) ProtoReflect() protoreflect.Message { +func (x *ResetPasswordRequest) ProtoReflect() protoreflect.Message { mi := &file_proto_users_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -501,26 +501,28 @@ func (x *ChangePasswordRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ChangePasswordRequest.ProtoReflect.Descriptor instead. -func (*ChangePasswordRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use ResetPasswordRequest.ProtoReflect.Descriptor instead. +func (*ResetPasswordRequest) Descriptor() ([]byte, []int) { return file_proto_users_proto_rawDescGZIP(), []int{9} } -func (x *ChangePasswordRequest) GetForm() *UserForm { +func (x *ResetPasswordRequest) GetForm() *UserForm { if x != nil { return x.Form } return nil } -type ChangePasswordResponse struct { +type ResetPasswordResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + Token *UserToken `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` } -func (x *ChangePasswordResponse) Reset() { - *x = ChangePasswordResponse{} +func (x *ResetPasswordResponse) Reset() { + *x = ResetPasswordResponse{} if protoimpl.UnsafeEnabled { mi := &file_proto_users_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -528,13 +530,13 @@ func (x *ChangePasswordResponse) Reset() { } } -func (x *ChangePasswordResponse) String() string { +func (x *ResetPasswordResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ChangePasswordResponse) ProtoMessage() {} +func (*ResetPasswordResponse) ProtoMessage() {} -func (x *ChangePasswordResponse) ProtoReflect() protoreflect.Message { +func (x *ResetPasswordResponse) ProtoReflect() protoreflect.Message { mi := &file_proto_users_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -546,21 +548,29 @@ func (x *ChangePasswordResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ChangePasswordResponse.ProtoReflect.Descriptor instead. -func (*ChangePasswordResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use ResetPasswordResponse.ProtoReflect.Descriptor instead. +func (*ResetPasswordResponse) Descriptor() ([]byte, []int) { return file_proto_users_proto_rawDescGZIP(), []int{10} } -type ResetPasswordReqeust struct { +func (x *ResetPasswordResponse) GetToken() *UserToken { + if x != nil { + return x.Token + } + return nil +} + +type ChangePasswordRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Form *UserForm `protobuf:"bytes,1,opt,name=form,proto3" json:"form,omitempty"` + Token *UserToken `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` + Form *UserForm `protobuf:"bytes,2,opt,name=form,proto3" json:"form,omitempty"` } -func (x *ResetPasswordReqeust) Reset() { - *x = ResetPasswordReqeust{} +func (x *ChangePasswordRequest) Reset() { + *x = ChangePasswordRequest{} if protoimpl.UnsafeEnabled { mi := &file_proto_users_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -568,13 +578,13 @@ func (x *ResetPasswordReqeust) Reset() { } } -func (x *ResetPasswordReqeust) String() string { +func (x *ChangePasswordRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ResetPasswordReqeust) ProtoMessage() {} +func (*ChangePasswordRequest) ProtoMessage() {} -func (x *ResetPasswordReqeust) ProtoReflect() protoreflect.Message { +func (x *ChangePasswordRequest) ProtoReflect() protoreflect.Message { mi := &file_proto_users_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -586,26 +596,33 @@ func (x *ResetPasswordReqeust) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ResetPasswordReqeust.ProtoReflect.Descriptor instead. -func (*ResetPasswordReqeust) Descriptor() ([]byte, []int) { +// Deprecated: Use ChangePasswordRequest.ProtoReflect.Descriptor instead. +func (*ChangePasswordRequest) Descriptor() ([]byte, []int) { return file_proto_users_proto_rawDescGZIP(), []int{11} } -func (x *ResetPasswordReqeust) GetForm() *UserForm { +func (x *ChangePasswordRequest) GetToken() *UserToken { + if x != nil { + return x.Token + } + return nil +} + +func (x *ChangePasswordRequest) GetForm() *UserForm { if x != nil { return x.Form } return nil } -type ResetPasswordResponse struct { +type ChangePasswordResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } -func (x *ResetPasswordResponse) Reset() { - *x = ResetPasswordResponse{} +func (x *ChangePasswordResponse) Reset() { + *x = ChangePasswordResponse{} if protoimpl.UnsafeEnabled { mi := &file_proto_users_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -613,13 +630,13 @@ func (x *ResetPasswordResponse) Reset() { } } -func (x *ResetPasswordResponse) String() string { +func (x *ChangePasswordResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ResetPasswordResponse) ProtoMessage() {} +func (*ChangePasswordResponse) ProtoMessage() {} -func (x *ResetPasswordResponse) ProtoReflect() protoreflect.Message { +func (x *ChangePasswordResponse) ProtoReflect() protoreflect.Message { mi := &file_proto_users_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -631,8 +648,8 @@ func (x *ResetPasswordResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ResetPasswordResponse.ProtoReflect.Descriptor instead. -func (*ResetPasswordResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use ChangePasswordResponse.ProtoReflect.Descriptor instead. +func (*ChangePasswordResponse) Descriptor() ([]byte, []int) { return file_proto_users_proto_rawDescGZIP(), []int{12} } @@ -676,17 +693,22 @@ var file_proto_users_proto_rawDesc = []byte{ 0x65, 0x6e, 0x22, 0x38, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x3c, 0x0a, 0x15, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x46, 0x6f, 0x72, 0x6d, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x18, 0x0a, 0x16, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x65, 0x75, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x04, - 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x52, 0x04, 0x66, 0x6f, 0x72, - 0x6d, 0x22, 0x17, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x3b, 0x0a, 0x14, + 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, + 0x6f, 0x72, 0x6d, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x3f, 0x0a, 0x15, 0x52, 0x65, 0x73, + 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x64, 0x0a, 0x15, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x04, 0x66, + 0x6f, 0x72, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6d, + 0x22, 0x18, 0x0a, 0x16, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xdd, 0x02, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x3d, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x16, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, @@ -699,16 +721,16 @@ var file_proto_users_proto_rawDesc = []byte{ 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x12, 0x17, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0e, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1c, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x75, 0x73, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0d, 0x52, + 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1b, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x73, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0e, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1c, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0d, - 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1b, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x65, 0x75, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x73, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x2e, 0x63, 0x68, 0x72, 0x69, 0x73, 0x68, 0x61, 0x79, 0x77, 0x61, 0x72, 0x64, 0x2e, 0x78, 0x79, 0x7a, 0x2f, 0x78, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, @@ -738,10 +760,10 @@ var file_proto_users_proto_goTypes = []interface{}{ (*LoginResponse)(nil), // 6: users.LoginResponse (*AuthorizeRequest)(nil), // 7: users.AuthorizeRequest (*AuthorizeResponse)(nil), // 8: users.AuthorizeResponse - (*ChangePasswordRequest)(nil), // 9: users.ChangePasswordRequest - (*ChangePasswordResponse)(nil), // 10: users.ChangePasswordResponse - (*ResetPasswordReqeust)(nil), // 11: users.ResetPasswordReqeust - (*ResetPasswordResponse)(nil), // 12: users.ResetPasswordResponse + (*ResetPasswordRequest)(nil), // 9: users.ResetPasswordRequest + (*ResetPasswordResponse)(nil), // 10: users.ResetPasswordResponse + (*ChangePasswordRequest)(nil), // 11: users.ChangePasswordRequest + (*ChangePasswordResponse)(nil), // 12: users.ChangePasswordResponse } var file_proto_users_proto_depIdxs = []int32{ 0, // 0: users.RegisterRequest.form:type_name -> users.UserForm @@ -749,23 +771,25 @@ var file_proto_users_proto_depIdxs = []int32{ 1, // 2: users.LoginResponse.token:type_name -> users.UserToken 1, // 3: users.AuthorizeRequest.token:type_name -> users.UserToken 2, // 4: users.AuthorizeResponse.user:type_name -> users.UserInfo - 0, // 5: users.ChangePasswordRequest.form:type_name -> users.UserForm - 0, // 6: users.ResetPasswordReqeust.form:type_name -> users.UserForm - 3, // 7: users.Users.Register:input_type -> users.RegisterRequest - 5, // 8: users.Users.Login:input_type -> users.LoginRequest - 7, // 9: users.Users.Authorize:input_type -> users.AuthorizeRequest - 9, // 10: users.Users.ChangePassword:input_type -> users.ChangePasswordRequest - 11, // 11: users.Users.ResetPassword:input_type -> users.ResetPasswordReqeust - 4, // 12: users.Users.Register:output_type -> users.RegisterResponse - 6, // 13: users.Users.Login:output_type -> users.LoginResponse - 8, // 14: users.Users.Authorize:output_type -> users.AuthorizeResponse - 10, // 15: users.Users.ChangePassword:output_type -> users.ChangePasswordResponse - 12, // 16: users.Users.ResetPassword:output_type -> users.ResetPasswordResponse - 12, // [12:17] is the sub-list for method output_type - 7, // [7:12] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 0, // 5: users.ResetPasswordRequest.form:type_name -> users.UserForm + 1, // 6: users.ResetPasswordResponse.token:type_name -> users.UserToken + 1, // 7: users.ChangePasswordRequest.token:type_name -> users.UserToken + 0, // 8: users.ChangePasswordRequest.form:type_name -> users.UserForm + 3, // 9: users.Users.Register:input_type -> users.RegisterRequest + 5, // 10: users.Users.Login:input_type -> users.LoginRequest + 7, // 11: users.Users.Authorize:input_type -> users.AuthorizeRequest + 9, // 12: users.Users.ResetPassword:input_type -> users.ResetPasswordRequest + 11, // 13: users.Users.ChangePassword:input_type -> users.ChangePasswordRequest + 4, // 14: users.Users.Register:output_type -> users.RegisterResponse + 6, // 15: users.Users.Login:output_type -> users.LoginResponse + 8, // 16: users.Users.Authorize:output_type -> users.AuthorizeResponse + 10, // 17: users.Users.ResetPassword:output_type -> users.ResetPasswordResponse + 12, // 18: users.Users.ChangePassword:output_type -> users.ChangePasswordResponse + 14, // [14:19] is the sub-list for method output_type + 9, // [9:14] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_proto_users_proto_init() } @@ -883,7 +907,7 @@ func file_proto_users_proto_init() { } } file_proto_users_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChangePasswordRequest); i { + switch v := v.(*ResetPasswordRequest); i { case 0: return &v.state case 1: @@ -895,7 +919,7 @@ func file_proto_users_proto_init() { } } file_proto_users_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChangePasswordResponse); i { + switch v := v.(*ResetPasswordResponse); i { case 0: return &v.state case 1: @@ -907,7 +931,7 @@ func file_proto_users_proto_init() { } } file_proto_users_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetPasswordReqeust); i { + switch v := v.(*ChangePasswordRequest); i { case 0: return &v.state case 1: @@ -919,7 +943,7 @@ func file_proto_users_proto_init() { } } file_proto_users_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetPasswordResponse); i { + switch v := v.(*ChangePasswordResponse); i { case 0: return &v.state case 1: diff --git a/proto/users.proto b/proto/users.proto index 9dedb44..62504ae 100644 --- a/proto/users.proto +++ b/proto/users.proto @@ -8,8 +8,8 @@ service Users { rpc Register (RegisterRequest) returns (RegisterResponse) {} rpc Login (LoginRequest) returns (LoginResponse) {} rpc Authorize (AuthorizeRequest) returns (AuthorizeResponse) {} + rpc ResetPassword (ResetPasswordRequest) returns (ResetPasswordResponse) {} rpc ChangePassword (ChangePasswordRequest) returns (ChangePasswordResponse) {} - rpc ResetPassword (ResetPasswordReqeust) returns (ResetPasswordResponse) {} } message UserForm { @@ -52,18 +52,19 @@ message AuthorizeResponse { UserInfo user = 1; } -message ChangePasswordRequest { +message ResetPasswordRequest { UserForm form = 1; } -message ChangePasswordResponse { - +message ResetPasswordResponse { + UserToken token = 1; } -message ResetPasswordReqeust { - UserForm form = 1; +message ChangePasswordRequest { + UserToken token = 1; + UserForm form = 2; } -message ResetPasswordResponse { - +message ChangePasswordResponse { + } diff --git a/proto/users_grpc.pb.go b/proto/users_grpc.pb.go index 146bfd0..daabf99 100644 --- a/proto/users_grpc.pb.go +++ b/proto/users_grpc.pb.go @@ -22,8 +22,8 @@ const ( Users_Register_FullMethodName = "/users.Users/Register" Users_Login_FullMethodName = "/users.Users/Login" Users_Authorize_FullMethodName = "/users.Users/Authorize" - Users_ChangePassword_FullMethodName = "/users.Users/ChangePassword" Users_ResetPassword_FullMethodName = "/users.Users/ResetPassword" + Users_ChangePassword_FullMethodName = "/users.Users/ChangePassword" ) // UsersClient is the client API for Users service. @@ -33,8 +33,8 @@ type UsersClient interface { Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) Authorize(ctx context.Context, in *AuthorizeRequest, opts ...grpc.CallOption) (*AuthorizeResponse, error) + ResetPassword(ctx context.Context, in *ResetPasswordRequest, opts ...grpc.CallOption) (*ResetPasswordResponse, error) ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error) - ResetPassword(ctx context.Context, in *ResetPasswordReqeust, opts ...grpc.CallOption) (*ResetPasswordResponse, error) } type usersClient struct { @@ -72,18 +72,18 @@ func (c *usersClient) Authorize(ctx context.Context, in *AuthorizeRequest, opts return out, nil } -func (c *usersClient) ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error) { - out := new(ChangePasswordResponse) - err := c.cc.Invoke(ctx, Users_ChangePassword_FullMethodName, in, out, opts...) +func (c *usersClient) ResetPassword(ctx context.Context, in *ResetPasswordRequest, opts ...grpc.CallOption) (*ResetPasswordResponse, error) { + out := new(ResetPasswordResponse) + err := c.cc.Invoke(ctx, Users_ResetPassword_FullMethodName, in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *usersClient) ResetPassword(ctx context.Context, in *ResetPasswordReqeust, opts ...grpc.CallOption) (*ResetPasswordResponse, error) { - out := new(ResetPasswordResponse) - err := c.cc.Invoke(ctx, Users_ResetPassword_FullMethodName, in, out, opts...) +func (c *usersClient) ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error) { + out := new(ChangePasswordResponse) + err := c.cc.Invoke(ctx, Users_ChangePassword_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -97,8 +97,8 @@ type UsersServer interface { Register(context.Context, *RegisterRequest) (*RegisterResponse, error) Login(context.Context, *LoginRequest) (*LoginResponse, error) Authorize(context.Context, *AuthorizeRequest) (*AuthorizeResponse, error) + ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error) ChangePassword(context.Context, *ChangePasswordRequest) (*ChangePasswordResponse, error) - ResetPassword(context.Context, *ResetPasswordReqeust) (*ResetPasswordResponse, error) mustEmbedUnimplementedUsersServer() } @@ -115,12 +115,12 @@ func (UnimplementedUsersServer) Login(context.Context, *LoginRequest) (*LoginRes func (UnimplementedUsersServer) Authorize(context.Context, *AuthorizeRequest) (*AuthorizeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Authorize not implemented") } +func (UnimplementedUsersServer) ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ResetPassword not implemented") +} func (UnimplementedUsersServer) ChangePassword(context.Context, *ChangePasswordRequest) (*ChangePasswordResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ChangePassword not implemented") } -func (UnimplementedUsersServer) ResetPassword(context.Context, *ResetPasswordReqeust) (*ResetPasswordResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ResetPassword not implemented") -} func (UnimplementedUsersServer) mustEmbedUnimplementedUsersServer() {} // UnsafeUsersServer may be embedded to opt out of forward compatibility for this service. @@ -188,38 +188,38 @@ func _Users_Authorize_Handler(srv interface{}, ctx context.Context, dec func(int return interceptor(ctx, in, info, handler) } -func _Users_ChangePassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ChangePasswordRequest) +func _Users_ResetPassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResetPasswordRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(UsersServer).ChangePassword(ctx, in) + return srv.(UsersServer).ResetPassword(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Users_ChangePassword_FullMethodName, + FullMethod: Users_ResetPassword_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UsersServer).ChangePassword(ctx, req.(*ChangePasswordRequest)) + return srv.(UsersServer).ResetPassword(ctx, req.(*ResetPasswordRequest)) } return interceptor(ctx, in, info, handler) } -func _Users_ResetPassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ResetPasswordReqeust) +func _Users_ChangePassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ChangePasswordRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(UsersServer).ResetPassword(ctx, in) + return srv.(UsersServer).ChangePassword(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Users_ResetPassword_FullMethodName, + FullMethod: Users_ChangePassword_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UsersServer).ResetPassword(ctx, req.(*ResetPasswordReqeust)) + return srv.(UsersServer).ChangePassword(ctx, req.(*ChangePasswordRequest)) } return interceptor(ctx, in, info, handler) } @@ -243,14 +243,14 @@ var Users_ServiceDesc = grpc.ServiceDesc{ MethodName: "Authorize", Handler: _Users_Authorize_Handler, }, - { - MethodName: "ChangePassword", - Handler: _Users_ChangePassword_Handler, - }, { MethodName: "ResetPassword", Handler: _Users_ResetPassword_Handler, }, + { + MethodName: "ChangePassword", + Handler: _Users_ChangePassword_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/users.proto",