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

Commit d3a0ffd

Browse files
authored
Merge pull request #44 from gedorinku/users_server
Users server
2 parents 0680ad0 + 5e348d3 commit d3a0ffd

12 files changed

+265
-133
lines changed

api/entries.validator.pb.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/oauth.validator.pb.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/protos/users.proto

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import "type/department.proto";
1414
service UserService {
1515
rpc ListPublicUsers (ListUsersRequest) returns (ListUsersResponse) {
1616
option (google.api.http) = {
17-
get: "/users/public"
17+
get: "/users"
1818
};
1919
}
2020
rpc GetUser (GetUserRequest) returns (User) {
2121
option (google.api.http) = {
22-
get: "/users/{user_id}"
22+
get: "/users/{user_name}"
2323
};
2424
}
2525
rpc CreateUser (CreateUserRequest) returns (User) {
@@ -84,7 +84,7 @@ message ListUsersResponse {
8484
}
8585

8686
message GetUserRequest {
87-
uint32 user_id = 1;
87+
string user_name = 1;
8888
}
8989

9090
message CreateUserRequest {

api/users.pb.go

Lines changed: 89 additions & 88 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/users.pb.gw.go

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/users.swagger.json

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -100,32 +100,6 @@
100100
}
101101
},
102102
"/users": {
103-
"post": {
104-
"operationId": "CreateUser",
105-
"responses": {
106-
"200": {
107-
"description": "",
108-
"schema": {
109-
"$ref": "#/definitions/prolab_accountsUser"
110-
}
111-
}
112-
},
113-
"parameters": [
114-
{
115-
"name": "body",
116-
"in": "body",
117-
"required": true,
118-
"schema": {
119-
"$ref": "#/definitions/prolab_accountsUser"
120-
}
121-
}
122-
],
123-
"tags": [
124-
"UserService"
125-
]
126-
}
127-
},
128-
"/users/public": {
129103
"get": {
130104
"operationId": "ListPublicUsers",
131105
"responses": {
@@ -155,9 +129,33 @@
155129
"tags": [
156130
"UserService"
157131
]
132+
},
133+
"post": {
134+
"operationId": "CreateUser",
135+
"responses": {
136+
"200": {
137+
"description": "",
138+
"schema": {
139+
"$ref": "#/definitions/prolab_accountsUser"
140+
}
141+
}
142+
},
143+
"parameters": [
144+
{
145+
"name": "body",
146+
"in": "body",
147+
"required": true,
148+
"schema": {
149+
"$ref": "#/definitions/prolab_accountsUser"
150+
}
151+
}
152+
],
153+
"tags": [
154+
"UserService"
155+
]
158156
}
159157
},
160-
"/users/{user_id}": {
158+
"/users/{user_name}": {
161159
"get": {
162160
"operationId": "GetUser",
163161
"responses": {
@@ -170,11 +168,10 @@
170168
},
171169
"parameters": [
172170
{
173-
"name": "user_id",
171+
"name": "user_name",
174172
"in": "path",
175173
"required": true,
176-
"type": "integer",
177-
"format": "int64"
174+
"type": "string"
178175
}
179176
],
180177
"tags": [

api/users.validator.pb.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/di/test_store_component.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"log"
77
"strings"
88

9+
"github.com/volatiletech/sqlboiler/boil"
10+
911
"github.com/ProgrammingLab/prolab-accounts/app/config"
1012
"github.com/ProgrammingLab/prolab-accounts/infra/record"
1113
)
@@ -14,6 +16,8 @@ import (
1416
func MustCreateTestStoreComponent(cfg *config.Config) *TestStoreComponent {
1517
db := mustConnectTestRDB(cfg)
1618

19+
boil.SetDB(db)
20+
1721
return &TestStoreComponent{
1822
storeComponentImpl: &storeComponentImpl{
1923
db: db,

app/server/users_server.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,16 @@ func (s *userServiceServerImpl) ListPublicUsers(ctx context.Context, req *api_pb
7777
}
7878

7979
func (s *userServiceServerImpl) GetUser(ctx context.Context, req *api_pb.GetUserRequest) (*api_pb.User, error) {
80-
// TODO: Not yet implemented.
81-
return nil, status.Error(codes.Unimplemented, "TODO: You should implement it!")
80+
us := s.UserStore(ctx)
81+
u, err := us.GetPublicUserByName(req.GetUserName())
82+
if err != nil {
83+
if errors.Cause(err) == sql.ErrNoRows {
84+
return nil, util.ErrNotFound
85+
}
86+
return nil, err
87+
}
88+
89+
return userToResponse(u, false, s.cfg), nil
8290
}
8391

8492
func (s *userServiceServerImpl) CreateUser(ctx context.Context, req *api_pb.CreateUserRequest) (*api_pb.User, error) {
@@ -208,6 +216,7 @@ func userToResponse(user *record.User, includePrivate bool, cfg *config.Config)
208216
u.Left = p.Left
209217
u.TwitterScreenName = p.TwitterScreenName.String
210218
u.GithubUserName = p.GithubUserName.String
219+
u.ProfileScope = profileScopeToResponse(model.ProfileScope(p.ProfileScope.Int))
211220

212221
if r := p.R; p.R != nil {
213222
if role := r.Role; role != nil {
@@ -225,3 +234,15 @@ func userToResponse(user *record.User, includePrivate bool, cfg *config.Config)
225234

226235
return u
227236
}
237+
238+
func profileScopeToResponse(scope model.ProfileScope) api_pb.ProfileScope {
239+
switch scope {
240+
case model.MembersOnly:
241+
return api_pb.ProfileScope_MEMBERS_ONLY
242+
case model.Public:
243+
return api_pb.ProfileScope_PUBLIC
244+
default:
245+
//unknow
246+
return -1
247+
}
248+
}

app/server/users_server_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,94 @@
11
package server
2+
3+
import (
4+
"context"
5+
"log"
6+
"testing"
7+
8+
api_pb "github.com/ProgrammingLab/prolab-accounts/api"
9+
"github.com/ProgrammingLab/prolab-accounts/app/config"
10+
"github.com/ProgrammingLab/prolab-accounts/app/di"
11+
"github.com/ProgrammingLab/prolab-accounts/model"
12+
)
13+
14+
func Test_UsersServer_GetUser(t *testing.T) {
15+
cfg, err := config.LoadConfig("../../.env")
16+
if err != nil {
17+
log.Fatalf("%+v", err)
18+
}
19+
20+
store := di.MustCreateTestStoreComponent(cfg)
21+
defer store.MustClose()
22+
ctx := context.Background()
23+
users, err := CreateTestUsers(ctx, store)
24+
if err != nil {
25+
t.Fatal(err)
26+
}
27+
28+
t.Run("Get public user", func(t *testing.T) {
29+
var req *api_pb.GetUserRequest
30+
for _, u := range users {
31+
if userProfileScope(model.UserID(u.ID)) != model.Public {
32+
continue
33+
}
34+
35+
req = &api_pb.GetUserRequest{
36+
UserName: u.Name,
37+
}
38+
break
39+
}
40+
41+
srv := NewUserServiceServer(store, cfg)
42+
resp, err := srv.GetUser(ctx, req)
43+
44+
if err != nil {
45+
t.Errorf("returned an error %v", err)
46+
}
47+
48+
if resp == nil {
49+
t.Error("response should not nil")
50+
}
51+
52+
if got, want := resp.Email, ""; got != want {
53+
t.Errorf("Email is %v, want %v", got, want)
54+
}
55+
if got, want := resp.FullName, ""; got != want {
56+
t.Errorf("FullName is %v, want %v", got, want)
57+
}
58+
})
59+
60+
t.Run("Get members only user", func(t *testing.T) {
61+
var req *api_pb.GetUserRequest
62+
for _, u := range users {
63+
if userProfileScope(model.UserID(u.ID)) != model.MembersOnly {
64+
continue
65+
}
66+
67+
req = &api_pb.GetUserRequest{
68+
UserName: u.Name,
69+
}
70+
break
71+
}
72+
73+
srv := NewUserServiceServer(store, cfg)
74+
resp, err := srv.GetUser(ctx, req)
75+
76+
if err != nil {
77+
t.Errorf("returned an error %v", err)
78+
}
79+
80+
if resp == nil {
81+
t.Error("response should not nil")
82+
}
83+
84+
if got, want := resp.Email, ""; got != want {
85+
t.Errorf("Email is %v, want %v", got, want)
86+
}
87+
if got, want := resp.FullName, ""; got != want {
88+
t.Errorf("FullName is %v, want %v", got, want)
89+
}
90+
if got, want := resp.Description, ""; got != want {
91+
t.Errorf("Description is %v, want %v", got, want)
92+
}
93+
})
94+
}

infra/store/user/user_store.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,21 @@ func (s *userStoreImpl) CreateUser(user *record.User) error {
4545
return errors.WithStack(err)
4646
}
4747

48+
func (s *userStoreImpl) GetPublicUserByName(name string) (*record.User, error) {
49+
mods := []qm.QueryMod{
50+
qm.Load("Profile", record.ProfileWhere.ProfileScope.EQ(null.IntFrom(int(model.Public)))),
51+
qm.Load("Profile.Role"),
52+
qm.Load("Profile.Department"),
53+
record.UserWhere.Name.EQ(name),
54+
}
55+
u, err := record.Users(mods...).One(s.ctx, s.db)
56+
if err != nil {
57+
return nil, errors.WithStack(err)
58+
}
59+
60+
return u, nil
61+
}
62+
4863
func (s *userStoreImpl) GetUserWithPrivate(userID model.UserID) (*record.User, error) {
4964
mods := []qm.QueryMod{
5065
qm.Load("Profile.Role"),

infra/store/user_store.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
// UserStore accesses users data
99
type UserStore interface {
1010
CreateUser(user *record.User) error
11+
GetPublicUserByName(name string) (*record.User, error)
1112
GetUserWithPrivate(userID model.UserID) (*record.User, error)
1213
ListPublicUsers(minUserID model.UserID, limit int) ([]*record.User, model.UserID, error)
1314
UpdateFullName(userID model.UserID, fullName string) (*record.User, error)

0 commit comments

Comments
 (0)