Skip to content
This repository was archived by the owner on Feb 4, 2021. It is now read-only.

Commit 8d27d30

Browse files
committed
Impl CreateUser
1 parent 215fc85 commit 8d27d30

11 files changed

+214
-116
lines changed

api/entries.validator.pb.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/oauth.validator.pb.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/protos/users.proto

+5-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ service UserService {
2626
rpc CreateUser (CreateUserRequest) returns (User) {
2727
option (google.api.http) = {
2828
post: "/users"
29-
body: "user"
29+
body: "*"
3030
};
3131
}
3232
rpc GetCurrentUser (GetCurrentUserRequest) returns (User) {
@@ -89,8 +89,10 @@ message GetUserRequest {
8989
}
9090

9191
message CreateUserRequest {
92-
User user = 1;
93-
string registeration_token = 2;
92+
string name = 1 [(validator.field) = {regex: "^[A-Za-z0-9_]{1,20}$"}];
93+
string full_name = 2 [(validator.field) = {length_lt: 128}];
94+
string password = 3;
95+
string registeration_token = 4 [(validator.field) = {length_lt: 128}];
9496
}
9597

9698
message GetCurrentUserRequest {}

api/user_blogs.validator.pb.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/users.pb.go

+107-90
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/users.pb.gw.go

+1-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/users.swagger.json

+18-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
"in": "body",
147147
"required": true,
148148
"schema": {
149-
"$ref": "#/definitions/prolab_accountsUser"
149+
"$ref": "#/definitions/prolab_accountsCreateUserRequest"
150150
}
151151
}
152152
],
@@ -181,6 +181,23 @@
181181
}
182182
},
183183
"definitions": {
184+
"prolab_accountsCreateUserRequest": {
185+
"type": "object",
186+
"properties": {
187+
"name": {
188+
"type": "string"
189+
},
190+
"full_name": {
191+
"type": "string"
192+
},
193+
"password": {
194+
"type": "string"
195+
},
196+
"registeration_token": {
197+
"type": "string"
198+
}
199+
}
200+
},
184201
"prolab_accountsDepartment": {
185202
"type": "object",
186203
"properties": {

api/users.validator.pb.go

+12-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/server/users_server.go

+54-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import (
88

99
"github.com/golang/protobuf/ptypes/empty"
1010
"github.com/izumin5210/grapi/pkg/grapiserver"
11-
validator "github.com/mwitkow/go-proto-validators"
1211
"github.com/pkg/errors"
1312
"github.com/volatiletech/null"
13+
"golang.org/x/crypto/bcrypt"
1414
"google.golang.org/grpc/codes"
1515
"google.golang.org/grpc/status"
1616

@@ -42,15 +42,21 @@ type userServiceServerImpl struct {
4242
const (
4343
// MaxIconSize represents max of icon size
4444
MaxIconSize = 1024 * 1024 // 1MiB
45+
// MaxPasswordLength represents max length of password
46+
MaxPasswordLength = 72
4547
)
4648

4749
var (
4850
// ErrPageSizeOutOfRange will be returned when page size is out of range
4951
ErrPageSizeOutOfRange = status.Error(codes.OutOfRange, "page size must be 1 <= size <= 100")
5052
// ErrIconSizeTooLarge will be returned when icon is too large
51-
ErrIconSizeTooLarge = validator.FieldError("Image", fmt.Errorf("image must be smaller than 1MiB"))
53+
ErrIconSizeTooLarge = status.Error(codes.InvalidArgument, "image must be smaller than 1MiB")
5254
// ErrInvalidImageFormat will be returned when image format is invalid
5355
ErrInvalidImageFormat = status.Error(codes.InvalidArgument, "invalid iamge format")
56+
// ErrNameAlreadyInUse is returned when name is already in use
57+
ErrNameAlreadyInUse = status.Error(codes.AlreadyExists, "name is already in use")
58+
// ErrTooLongPassword will be returned when password is too long
59+
ErrTooLongPassword = status.Error(codes.InvalidArgument, fmt.Sprintf("length of password must be less than %v", MaxPasswordLength+1))
5460
)
5561

5662
func (s *userServiceServerImpl) ListPublicUsers(ctx context.Context, req *api_pb.ListUsersRequest) (*api_pb.ListUsersResponse, error) {
@@ -89,8 +95,52 @@ func (s *userServiceServerImpl) GetUser(ctx context.Context, req *api_pb.GetUser
8995
}
9096

9197
func (s *userServiceServerImpl) CreateUser(ctx context.Context, req *api_pb.CreateUserRequest) (*api_pb.User, error) {
92-
// TODO: Not yet implemented.
93-
return nil, status.Error(codes.Unimplemented, "TODO: You should implement it!")
98+
is := s.InvitationStore(ctx)
99+
inv, err := is.GetInvitation(req.GetRegisterationToken())
100+
if err != nil {
101+
if errors.Cause(err) == sql.ErrNoRows {
102+
return nil, util.ErrNotFound
103+
}
104+
return nil, err
105+
}
106+
107+
password := req.GetPassword()
108+
if MaxPasswordLength < len(password) {
109+
return nil, ErrTooLongPassword
110+
}
111+
112+
d, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
113+
if err != nil {
114+
return nil, errors.WithStack(err)
115+
}
116+
117+
u := &record.User{
118+
Name: req.GetName(),
119+
Email: inv.Email,
120+
FullName: req.GetFullName(),
121+
Authority: int(model.Member),
122+
PasswordDigest: string(d),
123+
}
124+
us := s.UserStore(ctx)
125+
_, err = us.GetUserByName(req.GetName())
126+
if err == nil {
127+
return nil, ErrNameAlreadyInUse
128+
}
129+
if errors.Cause(err) != sql.ErrNoRows {
130+
return nil, err
131+
}
132+
133+
err = us.CreateUser(u)
134+
if err != nil {
135+
return nil, err
136+
}
137+
138+
err = is.DeleteInvitation(inv.ID)
139+
if err != nil {
140+
return nil, err
141+
}
142+
143+
return userToResponse(u, true, s.cfg), nil
94144
}
95145

96146
func (s *userServiceServerImpl) GetCurrentUser(ctx context.Context, req *api_pb.GetCurrentUserRequest) (*api_pb.User, error) {

infra/store/user/user_store.go

+12
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ func (s *userStoreImpl) GetPublicUserByName(name string) (*record.User, error) {
6060
return u, nil
6161
}
6262

63+
func (s *userStoreImpl) GetUserByName(name string) (*record.User, error) {
64+
mods := []qm.QueryMod{
65+
record.UserWhere.Name.EQ(name),
66+
}
67+
u, err := record.Users(mods...).One(s.ctx, s.db)
68+
if err != nil {
69+
return nil, errors.WithStack(err)
70+
}
71+
72+
return u, nil
73+
}
74+
6375
func (s *userStoreImpl) GetUserByEmail(email string) (*record.User, error) {
6476
mods := []qm.QueryMod{
6577
record.UserWhere.Email.EQ(email),

infra/store/user_store.go

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
type UserStore interface {
1010
CreateUser(user *record.User) error
1111
GetPublicUserByName(name string) (*record.User, error)
12+
GetUserByName(name string) (*record.User, error)
1213
GetUserByEmail(email string) (*record.User, error)
1314
GetUserWithPrivate(userID model.UserID) (*record.User, error)
1415
ListPublicUsers(minUserID model.UserID, limit int) ([]*record.User, model.UserID, error)

0 commit comments

Comments
 (0)