From 31acee9fb6f24c9f3c821337b805174762718be4 Mon Sep 17 00:00:00 2001 From: Christian Carlsson Date: Tue, 26 Nov 2024 18:14:20 +0000 Subject: [PATCH] feat: user search (#105) --- .github/workflows/lint.proto.yml | 26 - .github/workflows/test.proto.yml | 10 +- .../migrations/013_user_search_index.up.sql | 6 + protobufs/api/v1/shared.proto | 10 + protobufs/api/v1/users.proto | 22 + protobufs/api/v1/workouts.proto | 5 +- server/pkg/orm/users.go | 82 ++-- .../pb/api/v1/apiv1connect/users.connect.go | 58 +++ server/pkg/pb/api/v1/routines.pb.go | 8 +- server/pkg/pb/api/v1/shared.pb.go | 152 +++++- server/pkg/pb/api/v1/users.pb.go | 446 ++++++++++++++---- server/pkg/pb/api/v1/workouts.pb.go | 213 +++++---- server/pkg/repo/repo.go | 54 ++- server/rpc/v1/user.go | 57 +++ server/rpc/v1/workout.go | 5 +- web/package-lock.json | 10 + web/package.json | 1 + web/src/clients/clients.ts | 2 + web/src/proto/api/v1/routines_pb.ts | 4 +- web/src/proto/api/v1/shared_pb.ts | 46 +- web/src/proto/api/v1/users_pb.ts | 114 ++++- web/src/proto/api/v1/workouts_pb.ts | 7 +- web/src/router/router.ts | 8 + web/src/stores/auth.ts | 17 +- web/src/types/auth.ts | 5 + web/src/ui/components/CardWorkout.vue | 19 +- web/src/ui/components/UserDashboard.vue | 173 +++---- web/src/ui/profile/ProfileView.vue | 3 + web/src/ui/users/UserView.vue | 104 ++++ 29 files changed, 1260 insertions(+), 407 deletions(-) delete mode 100644 .github/workflows/lint.proto.yml create mode 100644 database/migrations/013_user_search_index.up.sql create mode 100644 web/src/types/auth.ts create mode 100644 web/src/ui/users/UserView.vue diff --git a/.github/workflows/lint.proto.yml b/.github/workflows/lint.proto.yml deleted file mode 100644 index 82c15958..00000000 --- a/.github/workflows/lint.proto.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Lint - -on: - pull_request: - paths: - - 'protobufs/**' - -jobs: - protobufs: - runs-on: ubuntu-latest - - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.23' - - - name: Install protolint - run: go install github.com/yoheimuta/protolint/cmd/protolint@latest - - - name: Run protolint - working-directory: ./protobufs - run: protolint . diff --git a/.github/workflows/test.proto.yml b/.github/workflows/test.proto.yml index 364f75ff..b406fd0e 100644 --- a/.github/workflows/test.proto.yml +++ b/.github/workflows/test.proto.yml @@ -6,6 +6,7 @@ on: - main pull_request: paths: + - 'protobufs/**' - 'buf.yaml' - 'buf.gen.yaml' - 'package.json' @@ -18,7 +19,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Set up Node.js + - name: Set up Node uses: actions/setup-node@v4 with: node-version: '22' @@ -48,3 +49,10 @@ jobs: git diff exit 1 fi + + - name: Install protolint + run: go install github.com/yoheimuta/protolint/cmd/protolint@latest + + - name: Run protolint + working-directory: ./protobufs + run: protolint . diff --git a/database/migrations/013_user_search_index.up.sql b/database/migrations/013_user_search_index.up.sql new file mode 100644 index 00000000..c7692ee9 --- /dev/null +++ b/database/migrations/013_user_search_index.up.sql @@ -0,0 +1,6 @@ +CREATE EXTENSION IF NOT EXISTS pg_trgm; + +ALTER TABLE getstronger.users + ADD COLUMN full_name_search TEXT GENERATED ALWAYS AS (lower(first_name || ' ' || last_name)) STORED NOT NULL; + +CREATE INDEX idx_users_full_name_search ON getstronger.users USING gin (full_name_search gin_trgm_ops); diff --git a/protobufs/api/v1/shared.proto b/protobufs/api/v1/shared.proto index f91af6dc..7b6d4b0a 100644 --- a/protobufs/api/v1/shared.proto +++ b/protobufs/api/v1/shared.proto @@ -25,3 +25,13 @@ message User { string first_name = 2 [(buf.validate.field).string.min_len = 1]; string last_name = 3 [(buf.validate.field).string.min_len = 1]; } + +message PaginationRequest { + int32 page_limit = 1 [(buf.validate.field).int32 = { gte: 1, lte: 100 }]; + bytes page_token = 2; +} + +message PaginationResponse { + int64 total_results = 1; + bytes next_page_token = 2; +} diff --git a/protobufs/api/v1/users.proto b/protobufs/api/v1/users.proto index 7f62d9ae..50a1510a 100644 --- a/protobufs/api/v1/users.proto +++ b/protobufs/api/v1/users.proto @@ -8,6 +8,9 @@ import "api/v1/shared.proto"; import "buf/validate/validate.proto"; service UserService { + rpc Get(GetUserRequest) returns (GetUserResponse) { + option (auth) = true; + } rpc Follow(FollowRequest) returns (FollowResponse) { option (auth) = true; } @@ -20,6 +23,16 @@ service UserService { rpc ListFollowees(ListFolloweesRequest) returns (ListFolloweesResponse) { option (auth) = true; } + rpc Search(SearchRequest) returns (SearchResponse) { + option (auth) = true; + } +} + +message GetUserRequest { + string id = 1 [(buf.validate.field).string.uuid = true]; +} +message GetUserResponse { + User user = 1; } message FollowRequest { @@ -45,3 +58,12 @@ message ListFolloweesRequest { message ListFolloweesResponse { repeated User followees = 1; } + +message SearchRequest { + string query = 1 [(buf.validate.field).string.min_len = 3]; + PaginationRequest pagination = 2 [(buf.validate.field).required = true]; +} +message SearchResponse { + repeated User users = 1; + PaginationResponse pagination = 2; +} diff --git a/protobufs/api/v1/workouts.proto b/protobufs/api/v1/workouts.proto index c4914b7c..bd97c79c 100644 --- a/protobufs/api/v1/workouts.proto +++ b/protobufs/api/v1/workouts.proto @@ -51,8 +51,9 @@ message CreateWorkoutResponse { } message ListWorkoutsRequest { - int32 page_size = 1 [(buf.validate.field).int32 = { gte: 1, lte: 100 }]; - bytes page_token = 2; + repeated string user_ids = 1 [(buf.validate.field).repeated = { min_items: 1, items: { string: { uuid: true }}}]; + int32 page_size = 2 [(buf.validate.field).int32 = { gte: 1, lte: 100 }]; + bytes page_token = 3; } message ListWorkoutsResponse { repeated Workout workouts = 1; diff --git a/server/pkg/orm/users.go b/server/pkg/orm/users.go index 390f6c24..a35746d2 100644 --- a/server/pkg/orm/users.go +++ b/server/pkg/orm/users.go @@ -23,51 +23,58 @@ import ( // User is an object representing the database table. type User struct { - ID string `boil:"id" json:"id" toml:"id" yaml:"id"` - FirstName string `boil:"first_name" json:"first_name" toml:"first_name" yaml:"first_name"` - LastName string `boil:"last_name" json:"last_name" toml:"last_name" yaml:"last_name"` - CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` + ID string `boil:"id" json:"id" toml:"id" yaml:"id"` + FirstName string `boil:"first_name" json:"first_name" toml:"first_name" yaml:"first_name"` + LastName string `boil:"last_name" json:"last_name" toml:"last_name" yaml:"last_name"` + CreatedAt time.Time `boil:"created_at" json:"created_at" toml:"created_at" yaml:"created_at"` + FullNameSearch string `boil:"full_name_search" json:"full_name_search" toml:"full_name_search" yaml:"full_name_search"` R *userR `boil:"-" json:"-" toml:"-" yaml:"-"` L userL `boil:"-" json:"-" toml:"-" yaml:"-"` } var UserColumns = struct { - ID string - FirstName string - LastName string - CreatedAt string + ID string + FirstName string + LastName string + CreatedAt string + FullNameSearch string }{ - ID: "id", - FirstName: "first_name", - LastName: "last_name", - CreatedAt: "created_at", + ID: "id", + FirstName: "first_name", + LastName: "last_name", + CreatedAt: "created_at", + FullNameSearch: "full_name_search", } var UserTableColumns = struct { - ID string - FirstName string - LastName string - CreatedAt string + ID string + FirstName string + LastName string + CreatedAt string + FullNameSearch string }{ - ID: "users.id", - FirstName: "users.first_name", - LastName: "users.last_name", - CreatedAt: "users.created_at", + ID: "users.id", + FirstName: "users.first_name", + LastName: "users.last_name", + CreatedAt: "users.created_at", + FullNameSearch: "users.full_name_search", } // Generated where var UserWhere = struct { - ID whereHelperstring - FirstName whereHelperstring - LastName whereHelperstring - CreatedAt whereHelpertime_Time + ID whereHelperstring + FirstName whereHelperstring + LastName whereHelperstring + CreatedAt whereHelpertime_Time + FullNameSearch whereHelperstring }{ - ID: whereHelperstring{field: "\"getstronger\".\"users\".\"id\""}, - FirstName: whereHelperstring{field: "\"getstronger\".\"users\".\"first_name\""}, - LastName: whereHelperstring{field: "\"getstronger\".\"users\".\"last_name\""}, - CreatedAt: whereHelpertime_Time{field: "\"getstronger\".\"users\".\"created_at\""}, + ID: whereHelperstring{field: "\"getstronger\".\"users\".\"id\""}, + FirstName: whereHelperstring{field: "\"getstronger\".\"users\".\"first_name\""}, + LastName: whereHelperstring{field: "\"getstronger\".\"users\".\"last_name\""}, + CreatedAt: whereHelpertime_Time{field: "\"getstronger\".\"users\".\"created_at\""}, + FullNameSearch: whereHelperstring{field: "\"getstronger\".\"users\".\"full_name_search\""}, } // UserRels is where relationship names are stored. @@ -158,11 +165,11 @@ func (r *userR) GetWorkouts() WorkoutSlice { type userL struct{} var ( - userAllColumns = []string{"id", "first_name", "last_name", "created_at"} + userAllColumns = []string{"id", "first_name", "last_name", "created_at", "full_name_search"} userColumnsWithoutDefault = []string{"id", "first_name", "last_name"} - userColumnsWithDefault = []string{"created_at"} + userColumnsWithDefault = []string{"created_at", "full_name_search"} userPrimaryKeyColumns = []string{"id"} - userGeneratedColumns = []string{} + userGeneratedColumns = []string{"full_name_search"} ) type ( @@ -855,7 +862,7 @@ func (userL) LoadFollowerUsers(ctx context.Context, e boil.ContextExecutor, sing } query := NewQuery( - qm.Select("\"getstronger\".\"users\".\"id\", \"getstronger\".\"users\".\"first_name\", \"getstronger\".\"users\".\"last_name\", \"getstronger\".\"users\".\"created_at\", \"a\".\"followee_id\""), + qm.Select("\"getstronger\".\"users\".\"id\", \"getstronger\".\"users\".\"first_name\", \"getstronger\".\"users\".\"last_name\", \"getstronger\".\"users\".\"created_at\", \"getstronger\".\"users\".\"full_name_search\", \"a\".\"followee_id\""), qm.From("\"getstronger\".\"users\""), qm.InnerJoin("\"getstronger\".\"followers\" as \"a\" on \"getstronger\".\"users\".\"id\" = \"a\".\"follower_id\""), qm.WhereIn("\"a\".\"followee_id\" in ?", argsSlice...), @@ -876,7 +883,7 @@ func (userL) LoadFollowerUsers(ctx context.Context, e boil.ContextExecutor, sing one := new(User) var localJoinCol string - err = results.Scan(&one.ID, &one.FirstName, &one.LastName, &one.CreatedAt, &localJoinCol) + err = results.Scan(&one.ID, &one.FirstName, &one.LastName, &one.CreatedAt, &one.FullNameSearch, &localJoinCol) if err != nil { return errors.Wrap(err, "failed to scan eager loaded results for users") } @@ -985,7 +992,7 @@ func (userL) LoadFolloweeUsers(ctx context.Context, e boil.ContextExecutor, sing } query := NewQuery( - qm.Select("\"getstronger\".\"users\".\"id\", \"getstronger\".\"users\".\"first_name\", \"getstronger\".\"users\".\"last_name\", \"getstronger\".\"users\".\"created_at\", \"a\".\"follower_id\""), + qm.Select("\"getstronger\".\"users\".\"id\", \"getstronger\".\"users\".\"first_name\", \"getstronger\".\"users\".\"last_name\", \"getstronger\".\"users\".\"created_at\", \"getstronger\".\"users\".\"full_name_search\", \"a\".\"follower_id\""), qm.From("\"getstronger\".\"users\""), qm.InnerJoin("\"getstronger\".\"followers\" as \"a\" on \"getstronger\".\"users\".\"id\" = \"a\".\"followee_id\""), qm.WhereIn("\"a\".\"follower_id\" in ?", argsSlice...), @@ -1006,7 +1013,7 @@ func (userL) LoadFolloweeUsers(ctx context.Context, e boil.ContextExecutor, sing one := new(User) var localJoinCol string - err = results.Scan(&one.ID, &one.FirstName, &one.LastName, &one.CreatedAt, &localJoinCol) + err = results.Scan(&one.ID, &one.FirstName, &one.LastName, &one.CreatedAt, &one.FullNameSearch, &localJoinCol) if err != nil { return errors.Wrap(err, "failed to scan eager loaded results for users") } @@ -2023,6 +2030,7 @@ func (o *User) Insert(ctx context.Context, exec boil.ContextExecutor, columns bo userColumnsWithoutDefault, nzDefaults, ) + wl = strmangle.SetComplement(wl, userGeneratedColumns) cache.valueMapping, err = queries.BindMapping(userType, userMapping, wl) if err != nil { @@ -2093,6 +2101,7 @@ func (o *User) Update(ctx context.Context, exec boil.ContextExecutor, columns bo userAllColumns, userPrimaryKeyColumns, ) + wl = strmangle.SetComplement(wl, userGeneratedColumns) if !columns.IsWhitelist() { wl = strmangle.SetComplement(wl, []string{"created_at"}) @@ -2270,6 +2279,9 @@ func (o *User) Upsert(ctx context.Context, exec boil.ContextExecutor, updateOnCo userPrimaryKeyColumns, ) + insert = strmangle.SetComplement(insert, userGeneratedColumns) + update = strmangle.SetComplement(update, userGeneratedColumns) + if updateOnConflict && len(update) == 0 { return errors.New("orm: unable to upsert users, could not build update column list") } diff --git a/server/pkg/pb/api/v1/apiv1connect/users.connect.go b/server/pkg/pb/api/v1/apiv1connect/users.connect.go index 3d7d1dd8..4ed5a642 100644 --- a/server/pkg/pb/api/v1/apiv1connect/users.connect.go +++ b/server/pkg/pb/api/v1/apiv1connect/users.connect.go @@ -34,6 +34,8 @@ const ( // reflection-formatted method names, remove the leading slash and convert the remaining slash to a // period. const ( + // UserServiceGetProcedure is the fully-qualified name of the UserService's Get RPC. + UserServiceGetProcedure = "/api.v1.UserService/Get" // UserServiceFollowProcedure is the fully-qualified name of the UserService's Follow RPC. UserServiceFollowProcedure = "/api.v1.UserService/Follow" // UserServiceUnfollowProcedure is the fully-qualified name of the UserService's Unfollow RPC. @@ -44,23 +46,29 @@ const ( // UserServiceListFolloweesProcedure is the fully-qualified name of the UserService's ListFollowees // RPC. UserServiceListFolloweesProcedure = "/api.v1.UserService/ListFollowees" + // UserServiceSearchProcedure is the fully-qualified name of the UserService's Search RPC. + UserServiceSearchProcedure = "/api.v1.UserService/Search" ) // These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. var ( userServiceServiceDescriptor = v1.File_api_v1_users_proto.Services().ByName("UserService") + userServiceGetMethodDescriptor = userServiceServiceDescriptor.Methods().ByName("Get") userServiceFollowMethodDescriptor = userServiceServiceDescriptor.Methods().ByName("Follow") userServiceUnfollowMethodDescriptor = userServiceServiceDescriptor.Methods().ByName("Unfollow") userServiceListFollowersMethodDescriptor = userServiceServiceDescriptor.Methods().ByName("ListFollowers") userServiceListFolloweesMethodDescriptor = userServiceServiceDescriptor.Methods().ByName("ListFollowees") + userServiceSearchMethodDescriptor = userServiceServiceDescriptor.Methods().ByName("Search") ) // UserServiceClient is a client for the api.v1.UserService service. type UserServiceClient interface { + Get(context.Context, *connect.Request[v1.GetUserRequest]) (*connect.Response[v1.GetUserResponse], error) Follow(context.Context, *connect.Request[v1.FollowRequest]) (*connect.Response[v1.FollowResponse], error) Unfollow(context.Context, *connect.Request[v1.UnfollowRequest]) (*connect.Response[v1.UnfollowResponse], error) ListFollowers(context.Context, *connect.Request[v1.ListFollowersRequest]) (*connect.Response[v1.ListFollowersResponse], error) ListFollowees(context.Context, *connect.Request[v1.ListFolloweesRequest]) (*connect.Response[v1.ListFolloweesResponse], error) + Search(context.Context, *connect.Request[v1.SearchRequest]) (*connect.Response[v1.SearchResponse], error) } // NewUserServiceClient constructs a client for the api.v1.UserService service. By default, it uses @@ -73,6 +81,12 @@ type UserServiceClient interface { func NewUserServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) UserServiceClient { baseURL = strings.TrimRight(baseURL, "/") return &userServiceClient{ + get: connect.NewClient[v1.GetUserRequest, v1.GetUserResponse]( + httpClient, + baseURL+UserServiceGetProcedure, + connect.WithSchema(userServiceGetMethodDescriptor), + connect.WithClientOptions(opts...), + ), follow: connect.NewClient[v1.FollowRequest, v1.FollowResponse]( httpClient, baseURL+UserServiceFollowProcedure, @@ -97,15 +111,28 @@ func NewUserServiceClient(httpClient connect.HTTPClient, baseURL string, opts .. connect.WithSchema(userServiceListFolloweesMethodDescriptor), connect.WithClientOptions(opts...), ), + search: connect.NewClient[v1.SearchRequest, v1.SearchResponse]( + httpClient, + baseURL+UserServiceSearchProcedure, + connect.WithSchema(userServiceSearchMethodDescriptor), + connect.WithClientOptions(opts...), + ), } } // userServiceClient implements UserServiceClient. type userServiceClient struct { + get *connect.Client[v1.GetUserRequest, v1.GetUserResponse] follow *connect.Client[v1.FollowRequest, v1.FollowResponse] unfollow *connect.Client[v1.UnfollowRequest, v1.UnfollowResponse] listFollowers *connect.Client[v1.ListFollowersRequest, v1.ListFollowersResponse] listFollowees *connect.Client[v1.ListFolloweesRequest, v1.ListFolloweesResponse] + search *connect.Client[v1.SearchRequest, v1.SearchResponse] +} + +// Get calls api.v1.UserService.Get. +func (c *userServiceClient) Get(ctx context.Context, req *connect.Request[v1.GetUserRequest]) (*connect.Response[v1.GetUserResponse], error) { + return c.get.CallUnary(ctx, req) } // Follow calls api.v1.UserService.Follow. @@ -128,12 +155,19 @@ func (c *userServiceClient) ListFollowees(ctx context.Context, req *connect.Requ return c.listFollowees.CallUnary(ctx, req) } +// Search calls api.v1.UserService.Search. +func (c *userServiceClient) Search(ctx context.Context, req *connect.Request[v1.SearchRequest]) (*connect.Response[v1.SearchResponse], error) { + return c.search.CallUnary(ctx, req) +} + // UserServiceHandler is an implementation of the api.v1.UserService service. type UserServiceHandler interface { + Get(context.Context, *connect.Request[v1.GetUserRequest]) (*connect.Response[v1.GetUserResponse], error) Follow(context.Context, *connect.Request[v1.FollowRequest]) (*connect.Response[v1.FollowResponse], error) Unfollow(context.Context, *connect.Request[v1.UnfollowRequest]) (*connect.Response[v1.UnfollowResponse], error) ListFollowers(context.Context, *connect.Request[v1.ListFollowersRequest]) (*connect.Response[v1.ListFollowersResponse], error) ListFollowees(context.Context, *connect.Request[v1.ListFolloweesRequest]) (*connect.Response[v1.ListFolloweesResponse], error) + Search(context.Context, *connect.Request[v1.SearchRequest]) (*connect.Response[v1.SearchResponse], error) } // NewUserServiceHandler builds an HTTP handler from the service implementation. It returns the path @@ -142,6 +176,12 @@ type UserServiceHandler interface { // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. func NewUserServiceHandler(svc UserServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + userServiceGetHandler := connect.NewUnaryHandler( + UserServiceGetProcedure, + svc.Get, + connect.WithSchema(userServiceGetMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) userServiceFollowHandler := connect.NewUnaryHandler( UserServiceFollowProcedure, svc.Follow, @@ -166,8 +206,16 @@ func NewUserServiceHandler(svc UserServiceHandler, opts ...connect.HandlerOption connect.WithSchema(userServiceListFolloweesMethodDescriptor), connect.WithHandlerOptions(opts...), ) + userServiceSearchHandler := connect.NewUnaryHandler( + UserServiceSearchProcedure, + svc.Search, + connect.WithSchema(userServiceSearchMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) return "/api.v1.UserService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { + case UserServiceGetProcedure: + userServiceGetHandler.ServeHTTP(w, r) case UserServiceFollowProcedure: userServiceFollowHandler.ServeHTTP(w, r) case UserServiceUnfollowProcedure: @@ -176,6 +224,8 @@ func NewUserServiceHandler(svc UserServiceHandler, opts ...connect.HandlerOption userServiceListFollowersHandler.ServeHTTP(w, r) case UserServiceListFolloweesProcedure: userServiceListFolloweesHandler.ServeHTTP(w, r) + case UserServiceSearchProcedure: + userServiceSearchHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -185,6 +235,10 @@ func NewUserServiceHandler(svc UserServiceHandler, opts ...connect.HandlerOption // UnimplementedUserServiceHandler returns CodeUnimplemented from all methods. type UnimplementedUserServiceHandler struct{} +func (UnimplementedUserServiceHandler) Get(context.Context, *connect.Request[v1.GetUserRequest]) (*connect.Response[v1.GetUserResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("api.v1.UserService.Get is not implemented")) +} + func (UnimplementedUserServiceHandler) Follow(context.Context, *connect.Request[v1.FollowRequest]) (*connect.Response[v1.FollowResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("api.v1.UserService.Follow is not implemented")) } @@ -200,3 +254,7 @@ func (UnimplementedUserServiceHandler) ListFollowers(context.Context, *connect.R func (UnimplementedUserServiceHandler) ListFollowees(context.Context, *connect.Request[v1.ListFolloweesRequest]) (*connect.Response[v1.ListFolloweesResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("api.v1.UserService.ListFollowees is not implemented")) } + +func (UnimplementedUserServiceHandler) Search(context.Context, *connect.Request[v1.SearchRequest]) (*connect.Response[v1.SearchResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("api.v1.UserService.Search is not implemented")) +} diff --git a/server/pkg/pb/api/v1/routines.pb.go b/server/pkg/pb/api/v1/routines.pb.go index ea04388f..bdee6757 100644 --- a/server/pkg/pb/api/v1/routines.pb.go +++ b/server/pkg/pb/api/v1/routines.pb.go @@ -838,9 +838,9 @@ var File_api_v1_routines_proto protoreflect.FileDescriptor var file_api_v1_routines_proto_rawDesc = []byte{ 0x0a, 0x15, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x1a, - 0x13, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, + 0x14, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x68, + 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, @@ -1048,8 +1048,8 @@ func file_api_v1_routines_proto_init() { if File_api_v1_routines_proto != nil { return } - file_api_v1_shared_proto_init() file_api_v1_options_proto_init() + file_api_v1_shared_proto_init() type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/server/pkg/pb/api/v1/shared.pb.go b/server/pkg/pb/api/v1/shared.pb.go index 8f0c2428..6cd87943 100644 --- a/server/pkg/pb/api/v1/shared.pb.go +++ b/server/pkg/pb/api/v1/shared.pb.go @@ -250,6 +250,112 @@ func (x *User) GetLastName() string { return "" } +type PaginationRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PageLimit int32 `protobuf:"varint,1,opt,name=page_limit,json=pageLimit,proto3" json:"page_limit,omitempty"` + PageToken []byte `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` +} + +func (x *PaginationRequest) Reset() { + *x = PaginationRequest{} + mi := &file_api_v1_shared_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PaginationRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PaginationRequest) ProtoMessage() {} + +func (x *PaginationRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_shared_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PaginationRequest.ProtoReflect.Descriptor instead. +func (*PaginationRequest) Descriptor() ([]byte, []int) { + return file_api_v1_shared_proto_rawDescGZIP(), []int{4} +} + +func (x *PaginationRequest) GetPageLimit() int32 { + if x != nil { + return x.PageLimit + } + return 0 +} + +func (x *PaginationRequest) GetPageToken() []byte { + if x != nil { + return x.PageToken + } + return nil +} + +type PaginationResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TotalResults int64 `protobuf:"varint,1,opt,name=total_results,json=totalResults,proto3" json:"total_results,omitempty"` + NextPageToken []byte `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` +} + +func (x *PaginationResponse) Reset() { + *x = PaginationResponse{} + mi := &file_api_v1_shared_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PaginationResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PaginationResponse) ProtoMessage() {} + +func (x *PaginationResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_shared_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PaginationResponse.ProtoReflect.Descriptor instead. +func (*PaginationResponse) Descriptor() ([]byte, []int) { + return file_api_v1_shared_proto_rawDescGZIP(), []int{5} +} + +func (x *PaginationResponse) GetTotalResults() int64 { + if x != nil { + return x.TotalResults + } + return 0 +} + +func (x *PaginationResponse) GetNextPageToken() []byte { + if x != nil { + return x.NextPageToken + } + return nil +} + var File_api_v1_shared_proto protoreflect.FileDescriptor var file_api_v1_shared_proto_rawDesc = []byte{ @@ -279,16 +385,28 @@ var file_api_v1_shared_proto_rawDesc = []byte{ 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x6c, - 0x61, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x8c, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x73, 0x6e, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x74, 0x72, 0x6f, - 0x6e, 0x67, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x70, 0x62, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, - 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x06, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, - 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5c, 0x0a, 0x11, 0x50, 0x61, 0x67, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0a, + 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, + 0x42, 0x09, 0xba, 0x48, 0x06, 0x1a, 0x04, 0x18, 0x64, 0x28, 0x01, 0x52, 0x09, 0x70, 0x61, 0x67, + 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x61, 0x0a, 0x12, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, + 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, + 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x8c, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x73, 0x6e, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x74, 0x72, + 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, + 0x2f, 0x70, 0x62, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, + 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, + 0x02, 0x06, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x70, 0x69, 0x5c, 0x56, + 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, + 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -303,12 +421,14 @@ func file_api_v1_shared_proto_rawDescGZIP() []byte { return file_api_v1_shared_proto_rawDescData } -var file_api_v1_shared_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_api_v1_shared_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_api_v1_shared_proto_goTypes = []any{ - (*ExerciseSets)(nil), // 0: api.v1.ExerciseSets - (*Exercise)(nil), // 1: api.v1.Exercise - (*Set)(nil), // 2: api.v1.Set - (*User)(nil), // 3: api.v1.User + (*ExerciseSets)(nil), // 0: api.v1.ExerciseSets + (*Exercise)(nil), // 1: api.v1.Exercise + (*Set)(nil), // 2: api.v1.Set + (*User)(nil), // 3: api.v1.User + (*PaginationRequest)(nil), // 4: api.v1.PaginationRequest + (*PaginationResponse)(nil), // 5: api.v1.PaginationResponse } var file_api_v1_shared_proto_depIdxs = []int32{ 1, // 0: api.v1.ExerciseSets.exercise:type_name -> api.v1.Exercise @@ -331,7 +451,7 @@ func file_api_v1_shared_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_v1_shared_proto_rawDesc, NumEnums: 0, - NumMessages: 4, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/server/pkg/pb/api/v1/users.pb.go b/server/pkg/pb/api/v1/users.pb.go index b89840e2..290533dc 100644 --- a/server/pkg/pb/api/v1/users.pb.go +++ b/server/pkg/pb/api/v1/users.pb.go @@ -22,6 +22,96 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type GetUserRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *GetUserRequest) Reset() { + *x = GetUserRequest{} + mi := &file_api_v1_users_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetUserRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserRequest) ProtoMessage() {} + +func (x *GetUserRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_users_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUserRequest.ProtoReflect.Descriptor instead. +func (*GetUserRequest) Descriptor() ([]byte, []int) { + return file_api_v1_users_proto_rawDescGZIP(), []int{0} +} + +func (x *GetUserRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type GetUserResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"` +} + +func (x *GetUserResponse) Reset() { + *x = GetUserResponse{} + mi := &file_api_v1_users_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetUserResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserResponse) ProtoMessage() {} + +func (x *GetUserResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_users_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetUserResponse.ProtoReflect.Descriptor instead. +func (*GetUserResponse) Descriptor() ([]byte, []int) { + return file_api_v1_users_proto_rawDescGZIP(), []int{1} +} + +func (x *GetUserResponse) GetUser() *User { + if x != nil { + return x.User + } + return nil +} + type FollowRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -32,7 +122,7 @@ type FollowRequest struct { func (x *FollowRequest) Reset() { *x = FollowRequest{} - mi := &file_api_v1_users_proto_msgTypes[0] + mi := &file_api_v1_users_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -44,7 +134,7 @@ func (x *FollowRequest) String() string { func (*FollowRequest) ProtoMessage() {} func (x *FollowRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_users_proto_msgTypes[0] + mi := &file_api_v1_users_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -57,7 +147,7 @@ func (x *FollowRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FollowRequest.ProtoReflect.Descriptor instead. func (*FollowRequest) Descriptor() ([]byte, []int) { - return file_api_v1_users_proto_rawDescGZIP(), []int{0} + return file_api_v1_users_proto_rawDescGZIP(), []int{2} } func (x *FollowRequest) GetFollowId() string { @@ -75,7 +165,7 @@ type FollowResponse struct { func (x *FollowResponse) Reset() { *x = FollowResponse{} - mi := &file_api_v1_users_proto_msgTypes[1] + mi := &file_api_v1_users_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -87,7 +177,7 @@ func (x *FollowResponse) String() string { func (*FollowResponse) ProtoMessage() {} func (x *FollowResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_users_proto_msgTypes[1] + mi := &file_api_v1_users_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -100,7 +190,7 @@ func (x *FollowResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FollowResponse.ProtoReflect.Descriptor instead. func (*FollowResponse) Descriptor() ([]byte, []int) { - return file_api_v1_users_proto_rawDescGZIP(), []int{1} + return file_api_v1_users_proto_rawDescGZIP(), []int{3} } type UnfollowRequest struct { @@ -113,7 +203,7 @@ type UnfollowRequest struct { func (x *UnfollowRequest) Reset() { *x = UnfollowRequest{} - mi := &file_api_v1_users_proto_msgTypes[2] + mi := &file_api_v1_users_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -125,7 +215,7 @@ func (x *UnfollowRequest) String() string { func (*UnfollowRequest) ProtoMessage() {} func (x *UnfollowRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_users_proto_msgTypes[2] + mi := &file_api_v1_users_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -138,7 +228,7 @@ func (x *UnfollowRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnfollowRequest.ProtoReflect.Descriptor instead. func (*UnfollowRequest) Descriptor() ([]byte, []int) { - return file_api_v1_users_proto_rawDescGZIP(), []int{2} + return file_api_v1_users_proto_rawDescGZIP(), []int{4} } func (x *UnfollowRequest) GetUnfollowId() string { @@ -156,7 +246,7 @@ type UnfollowResponse struct { func (x *UnfollowResponse) Reset() { *x = UnfollowResponse{} - mi := &file_api_v1_users_proto_msgTypes[3] + mi := &file_api_v1_users_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -168,7 +258,7 @@ func (x *UnfollowResponse) String() string { func (*UnfollowResponse) ProtoMessage() {} func (x *UnfollowResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_users_proto_msgTypes[3] + mi := &file_api_v1_users_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -181,7 +271,7 @@ func (x *UnfollowResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnfollowResponse.ProtoReflect.Descriptor instead. func (*UnfollowResponse) Descriptor() ([]byte, []int) { - return file_api_v1_users_proto_rawDescGZIP(), []int{3} + return file_api_v1_users_proto_rawDescGZIP(), []int{5} } type ListFollowersRequest struct { @@ -194,7 +284,7 @@ type ListFollowersRequest struct { func (x *ListFollowersRequest) Reset() { *x = ListFollowersRequest{} - mi := &file_api_v1_users_proto_msgTypes[4] + mi := &file_api_v1_users_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -206,7 +296,7 @@ func (x *ListFollowersRequest) String() string { func (*ListFollowersRequest) ProtoMessage() {} func (x *ListFollowersRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_users_proto_msgTypes[4] + mi := &file_api_v1_users_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -219,7 +309,7 @@ func (x *ListFollowersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListFollowersRequest.ProtoReflect.Descriptor instead. func (*ListFollowersRequest) Descriptor() ([]byte, []int) { - return file_api_v1_users_proto_rawDescGZIP(), []int{4} + return file_api_v1_users_proto_rawDescGZIP(), []int{6} } func (x *ListFollowersRequest) GetFollowerId() string { @@ -239,7 +329,7 @@ type ListFollowersResponse struct { func (x *ListFollowersResponse) Reset() { *x = ListFollowersResponse{} - mi := &file_api_v1_users_proto_msgTypes[5] + mi := &file_api_v1_users_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -251,7 +341,7 @@ func (x *ListFollowersResponse) String() string { func (*ListFollowersResponse) ProtoMessage() {} func (x *ListFollowersResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_users_proto_msgTypes[5] + mi := &file_api_v1_users_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -264,7 +354,7 @@ func (x *ListFollowersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListFollowersResponse.ProtoReflect.Descriptor instead. func (*ListFollowersResponse) Descriptor() ([]byte, []int) { - return file_api_v1_users_proto_rawDescGZIP(), []int{5} + return file_api_v1_users_proto_rawDescGZIP(), []int{7} } func (x *ListFollowersResponse) GetFollowers() []*User { @@ -284,7 +374,7 @@ type ListFolloweesRequest struct { func (x *ListFolloweesRequest) Reset() { *x = ListFolloweesRequest{} - mi := &file_api_v1_users_proto_msgTypes[6] + mi := &file_api_v1_users_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -296,7 +386,7 @@ func (x *ListFolloweesRequest) String() string { func (*ListFolloweesRequest) ProtoMessage() {} func (x *ListFolloweesRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_users_proto_msgTypes[6] + mi := &file_api_v1_users_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -309,7 +399,7 @@ func (x *ListFolloweesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListFolloweesRequest.ProtoReflect.Descriptor instead. func (*ListFolloweesRequest) Descriptor() ([]byte, []int) { - return file_api_v1_users_proto_rawDescGZIP(), []int{6} + return file_api_v1_users_proto_rawDescGZIP(), []int{8} } func (x *ListFolloweesRequest) GetFolloweeId() string { @@ -329,7 +419,7 @@ type ListFolloweesResponse struct { func (x *ListFolloweesResponse) Reset() { *x = ListFolloweesResponse{} - mi := &file_api_v1_users_proto_msgTypes[7] + mi := &file_api_v1_users_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -341,7 +431,7 @@ func (x *ListFolloweesResponse) String() string { func (*ListFolloweesResponse) ProtoMessage() {} func (x *ListFolloweesResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v1_users_proto_msgTypes[7] + mi := &file_api_v1_users_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -354,7 +444,7 @@ func (x *ListFolloweesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListFolloweesResponse.ProtoReflect.Descriptor instead. func (*ListFolloweesResponse) Descriptor() ([]byte, []int) { - return file_api_v1_users_proto_rawDescGZIP(), []int{7} + return file_api_v1_users_proto_rawDescGZIP(), []int{9} } func (x *ListFolloweesResponse) GetFollowees() []*User { @@ -364,6 +454,112 @@ func (x *ListFolloweesResponse) GetFollowees() []*User { return nil } +type SearchRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` + Pagination *PaginationRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (x *SearchRequest) Reset() { + *x = SearchRequest{} + mi := &file_api_v1_users_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SearchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchRequest) ProtoMessage() {} + +func (x *SearchRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_users_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead. +func (*SearchRequest) Descriptor() ([]byte, []int) { + return file_api_v1_users_proto_rawDescGZIP(), []int{10} +} + +func (x *SearchRequest) GetQuery() string { + if x != nil { + return x.Query + } + return "" +} + +func (x *SearchRequest) GetPagination() *PaginationRequest { + if x != nil { + return x.Pagination + } + return nil +} + +type SearchResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Users []*User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` + Pagination *PaginationResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (x *SearchResponse) Reset() { + *x = SearchResponse{} + mi := &file_api_v1_users_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SearchResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchResponse) ProtoMessage() {} + +func (x *SearchResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v1_users_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead. +func (*SearchResponse) Descriptor() ([]byte, []int) { + return file_api_v1_users_proto_rawDescGZIP(), []int{11} +} + +func (x *SearchResponse) GetUsers() []*User { + if x != nil { + return x.Users + } + return nil +} + +func (x *SearchResponse) GetPagination() *PaginationResponse { + if x != nil { + return x.Pagination + } + return nil +} + var File_api_v1_users_proto protoreflect.FileDescriptor var file_api_v1_users_proto_rawDesc = []byte{ @@ -373,63 +569,91 @@ var file_api_v1_users_proto_rawDesc = []byte{ 0x74, 0x6f, 0x1a, 0x13, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x36, 0x0a, 0x0d, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, - 0x01, 0x01, 0x52, 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x22, 0x10, 0x0a, 0x0e, - 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, - 0x0a, 0x0f, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x75, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x2a, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, + 0x22, 0x33, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x36, 0x0a, 0x0d, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, + 0xb0, 0x01, 0x01, 0x52, 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x22, 0x10, 0x0a, + 0x0e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x3c, 0x0a, 0x0f, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x75, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, + 0x01, 0x52, 0x0a, 0x75, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x22, 0x12, 0x0a, + 0x10, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x41, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x66, 0x6f, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, + 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x72, 0x49, 0x64, 0x22, 0x43, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, + 0x6f, 0x77, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, + 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x09, + 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x22, 0x41, 0x0a, 0x14, 0x4c, 0x69, 0x73, + 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, - 0x52, 0x0a, 0x75, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x22, 0x12, 0x0a, 0x10, - 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x41, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x66, 0x6f, 0x6c, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, - 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0x49, 0x64, 0x22, 0x43, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, - 0x77, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x09, - 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x09, 0x66, - 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x22, 0x41, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, - 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x29, 0x0a, 0x0b, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, - 0x0a, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x49, 0x64, 0x22, 0x43, 0x0a, 0x15, 0x4c, - 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, - 0x32, 0xb9, 0x02, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x3d, 0x0a, 0x06, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, - 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x12, - 0x43, 0x0a, 0x08, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x17, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, - 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, - 0x88, 0xb5, 0x18, 0x01, 0x12, 0x52, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x52, 0x0a, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x49, 0x64, 0x22, 0x43, 0x0a, 0x15, + 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x09, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, + 0x73, 0x22, 0x71, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x03, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x12, 0x41, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x70, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xb6, 0x03, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x16, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, + 0x88, 0xb5, 0x18, 0x01, 0x12, 0x3d, 0x0a, 0x06, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x15, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, + 0xb5, 0x18, 0x01, 0x12, 0x43, 0x0a, 0x08, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x12, + 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x12, 0x52, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, - 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, + 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x42, 0x8b, 0x01, 0x0a, - 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x55, 0x73, 0x65, - 0x72, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x73, 0x6e, 0x2f, 0x67, 0x65, 0x74, - 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, - 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x70, 0x69, 0x2e, - 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x70, - 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x07, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x12, 0x52, 0x0a, 0x0d, + 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x65, 0x73, 0x12, 0x1c, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, + 0x12, 0x3d, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x42, + 0x8b, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0a, + 0x55, 0x73, 0x65, 0x72, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, 0x73, 0x6e, 0x2f, + 0x67, 0x65, 0x74, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, + 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, + 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, + 0x12, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -444,34 +668,48 @@ func file_api_v1_users_proto_rawDescGZIP() []byte { return file_api_v1_users_proto_rawDescData } -var file_api_v1_users_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_api_v1_users_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_api_v1_users_proto_goTypes = []any{ - (*FollowRequest)(nil), // 0: api.v1.FollowRequest - (*FollowResponse)(nil), // 1: api.v1.FollowResponse - (*UnfollowRequest)(nil), // 2: api.v1.UnfollowRequest - (*UnfollowResponse)(nil), // 3: api.v1.UnfollowResponse - (*ListFollowersRequest)(nil), // 4: api.v1.ListFollowersRequest - (*ListFollowersResponse)(nil), // 5: api.v1.ListFollowersResponse - (*ListFolloweesRequest)(nil), // 6: api.v1.ListFolloweesRequest - (*ListFolloweesResponse)(nil), // 7: api.v1.ListFolloweesResponse - (*User)(nil), // 8: api.v1.User + (*GetUserRequest)(nil), // 0: api.v1.GetUserRequest + (*GetUserResponse)(nil), // 1: api.v1.GetUserResponse + (*FollowRequest)(nil), // 2: api.v1.FollowRequest + (*FollowResponse)(nil), // 3: api.v1.FollowResponse + (*UnfollowRequest)(nil), // 4: api.v1.UnfollowRequest + (*UnfollowResponse)(nil), // 5: api.v1.UnfollowResponse + (*ListFollowersRequest)(nil), // 6: api.v1.ListFollowersRequest + (*ListFollowersResponse)(nil), // 7: api.v1.ListFollowersResponse + (*ListFolloweesRequest)(nil), // 8: api.v1.ListFolloweesRequest + (*ListFolloweesResponse)(nil), // 9: api.v1.ListFolloweesResponse + (*SearchRequest)(nil), // 10: api.v1.SearchRequest + (*SearchResponse)(nil), // 11: api.v1.SearchResponse + (*User)(nil), // 12: api.v1.User + (*PaginationRequest)(nil), // 13: api.v1.PaginationRequest + (*PaginationResponse)(nil), // 14: api.v1.PaginationResponse } var file_api_v1_users_proto_depIdxs = []int32{ - 8, // 0: api.v1.ListFollowersResponse.followers:type_name -> api.v1.User - 8, // 1: api.v1.ListFolloweesResponse.followees:type_name -> api.v1.User - 0, // 2: api.v1.UserService.Follow:input_type -> api.v1.FollowRequest - 2, // 3: api.v1.UserService.Unfollow:input_type -> api.v1.UnfollowRequest - 4, // 4: api.v1.UserService.ListFollowers:input_type -> api.v1.ListFollowersRequest - 6, // 5: api.v1.UserService.ListFollowees:input_type -> api.v1.ListFolloweesRequest - 1, // 6: api.v1.UserService.Follow:output_type -> api.v1.FollowResponse - 3, // 7: api.v1.UserService.Unfollow:output_type -> api.v1.UnfollowResponse - 5, // 8: api.v1.UserService.ListFollowers:output_type -> api.v1.ListFollowersResponse - 7, // 9: api.v1.UserService.ListFollowees:output_type -> api.v1.ListFolloweesResponse - 6, // [6:10] is the sub-list for method output_type - 2, // [2:6] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 12, // 0: api.v1.GetUserResponse.user:type_name -> api.v1.User + 12, // 1: api.v1.ListFollowersResponse.followers:type_name -> api.v1.User + 12, // 2: api.v1.ListFolloweesResponse.followees:type_name -> api.v1.User + 13, // 3: api.v1.SearchRequest.pagination:type_name -> api.v1.PaginationRequest + 12, // 4: api.v1.SearchResponse.users:type_name -> api.v1.User + 14, // 5: api.v1.SearchResponse.pagination:type_name -> api.v1.PaginationResponse + 0, // 6: api.v1.UserService.Get:input_type -> api.v1.GetUserRequest + 2, // 7: api.v1.UserService.Follow:input_type -> api.v1.FollowRequest + 4, // 8: api.v1.UserService.Unfollow:input_type -> api.v1.UnfollowRequest + 6, // 9: api.v1.UserService.ListFollowers:input_type -> api.v1.ListFollowersRequest + 8, // 10: api.v1.UserService.ListFollowees:input_type -> api.v1.ListFolloweesRequest + 10, // 11: api.v1.UserService.Search:input_type -> api.v1.SearchRequest + 1, // 12: api.v1.UserService.Get:output_type -> api.v1.GetUserResponse + 3, // 13: api.v1.UserService.Follow:output_type -> api.v1.FollowResponse + 5, // 14: api.v1.UserService.Unfollow:output_type -> api.v1.UnfollowResponse + 7, // 15: api.v1.UserService.ListFollowers:output_type -> api.v1.ListFollowersResponse + 9, // 16: api.v1.UserService.ListFollowees:output_type -> api.v1.ListFolloweesResponse + 11, // 17: api.v1.UserService.Search:output_type -> api.v1.SearchResponse + 12, // [12:18] is the sub-list for method output_type + 6, // [6:12] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_api_v1_users_proto_init() } @@ -487,7 +725,7 @@ func file_api_v1_users_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_v1_users_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/server/pkg/pb/api/v1/workouts.pb.go b/server/pkg/pb/api/v1/workouts.pb.go index 9436ed16..fc9a7947 100644 --- a/server/pkg/pb/api/v1/workouts.pb.go +++ b/server/pkg/pb/api/v1/workouts.pb.go @@ -143,8 +143,9 @@ type ListWorkoutsRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - PageToken []byte `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + UserIds []string `protobuf:"bytes,1,rep,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + PageToken []byte `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` } func (x *ListWorkoutsRequest) Reset() { @@ -177,6 +178,13 @@ func (*ListWorkoutsRequest) Descriptor() ([]byte, []int) { return file_api_v1_workouts_proto_rawDescGZIP(), []int{2} } +func (x *ListWorkoutsRequest) GetUserIds() []string { + if x != nil { + return x.UserIds + } + return nil +} + func (x *ListWorkoutsRequest) GetPageSize() int32 { if x != nil { return x.PageSize @@ -701,106 +709,109 @@ var file_api_v1_workouts_proto_rawDesc = []byte{ 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x49, - 0x64, 0x22, 0x5c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, - 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x42, 0x09, 0xba, 0x48, 0x06, - 0x1a, 0x04, 0x18, 0x64, 0x28, 0x01, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, - 0x6b, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6f, - 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, - 0x6f, 0x75, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, - 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6e, - 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x2d, 0x0a, 0x11, - 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, - 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3f, 0x0a, 0x12, 0x47, - 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x29, 0x0a, 0x07, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x6f, 0x75, 0x74, 0x52, 0x07, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x22, 0x30, 0x0a, 0x14, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x17, - 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x60, 0x0a, 0x12, 0x50, 0x6f, 0x73, 0x74, 0x43, - 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, - 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x09, 0x77, 0x6f, 0x72, - 0x6b, 0x6f, 0x75, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x47, 0x0a, 0x13, 0x50, 0x6f, 0x73, - 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x30, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6f, - 0x75, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, - 0x6e, 0x74, 0x22, 0xa8, 0x02, 0x0a, 0x07, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x12, 0x18, + 0x64, 0x22, 0x88, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x08, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0f, 0xba, 0x48, 0x0c, + 0x92, 0x01, 0x09, 0x08, 0x01, 0x22, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x26, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x42, 0x09, 0xba, 0x48, 0x06, 0x1a, 0x04, 0x18, + 0x64, 0x28, 0x01, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x6b, 0x0a, 0x14, + 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, + 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, + 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x2d, 0x0a, 0x11, 0x47, 0x65, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, - 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, - 0x43, 0x0a, 0x0d, 0x65, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x65, 0x53, 0x65, 0x74, 0x73, 0x42, 0x08, 0xba, 0x48, - 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x0c, 0x65, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x65, - 0x53, 0x65, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x43, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x69, - 0x73, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, - 0x01, 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74, 0x22, 0xba, 0x01, - 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, - 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x75, 0x73, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x41, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, - 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x32, 0x85, 0x03, 0x0a, 0x0e, 0x57, - 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4b, 0x0a, - 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x12, 0x42, 0x0a, 0x03, 0x47, 0x65, - 0x74, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, - 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x12, 0x47, - 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x12, 0x4b, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, - 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, - 0x88, 0xb5, 0x18, 0x01, 0x12, 0x4c, 0x0a, 0x0b, 0x50, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x73, - 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, - 0x18, 0x01, 0x42, 0x8e, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x42, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, - 0x72, 0x6c, 0x73, 0x73, 0x6e, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x65, - 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, - 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x70, - 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x70, 0x69, 0x3a, - 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3f, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x57, + 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, + 0x0a, 0x07, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, + 0x52, 0x07, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x22, 0x30, 0x0a, 0x14, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, + 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x60, 0x0a, 0x12, 0x50, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0a, 0x77, 0x6f, + 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, + 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6f, 0x75, + 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x63, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x47, 0x0a, 0x13, 0x50, 0x6f, 0x73, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, + 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x43, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, + 0xa8, 0x02, 0x0a, 0x07, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, + 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x42, 0x06, + 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0d, + 0x65, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, + 0x72, 0x63, 0x69, 0x73, 0x65, 0x53, 0x65, 0x74, 0x73, 0x42, 0x08, 0xba, 0x48, 0x05, 0x92, 0x01, + 0x02, 0x08, 0x01, 0x52, 0x0c, 0x65, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x65, 0x53, 0x65, 0x74, + 0x73, 0x12, 0x32, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, + 0x6b, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x43, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0a, + 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x0e, 0x57, + 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, + 0xb0, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x75, 0x73, 0x65, + 0x72, 0x12, 0x21, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x63, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x41, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x09, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x32, 0x85, 0x03, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6b, + 0x6f, 0x75, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4b, 0x0a, 0x06, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x12, 0x42, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x19, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, + 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x12, 0x47, 0x0a, 0x04, 0x4c, + 0x69, 0x73, 0x74, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, + 0x88, 0xb5, 0x18, 0x01, 0x12, 0x4b, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1c, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, + 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, + 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, + 0x01, 0x12, 0x4c, 0x0a, 0x0b, 0x50, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x88, 0xb5, 0x18, 0x01, 0x42, + 0x8e, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0d, + 0x57, 0x6f, 0x72, 0x6b, 0x6f, 0x75, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 0x6c, 0x73, + 0x73, 0x6e, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x2f, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, + 0x02, 0x06, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x70, 0x69, 0x5c, 0x56, + 0x31, 0xe2, 0x02, 0x12, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/server/pkg/repo/repo.go b/server/pkg/repo/repo.go index 4be01fb6..5a63c330 100644 --- a/server/pkg/repo/repo.go +++ b/server/pkg/repo/repo.go @@ -5,6 +5,7 @@ import ( "database/sql" "encoding/json" "fmt" + "strings" "time" "github.com/volatiletech/null/v8" @@ -561,10 +562,10 @@ func ListWorkoutsWithSets() ListWorkoutsOpt { } } -func ListWorkoutsWithUserID(userID string) ListWorkoutsOpt { +func ListWorkoutsWithUserIDs(userIDs []string) ListWorkoutsOpt { return func() ([]qm.QueryMod, error) { return []qm.QueryMod{ - orm.WorkoutWhere.UserID.EQ(userID), + orm.WorkoutWhere.UserID.IN(userIDs), }, nil } } @@ -850,18 +851,37 @@ func (r *Repo) GetUser(ctx context.Context, opts ...GetUserOpt) (*orm.User, erro return user, nil } -type ListUsersOpt func() qm.QueryMod +type ListUsersOpt func() []qm.QueryMod func ListUsersWithIDs(ids []string) ListUsersOpt { - return func() qm.QueryMod { - return orm.UserWhere.ID.IN(ids) + return func() []qm.QueryMod { + return []qm.QueryMod{ + orm.UserWhere.ID.IN(ids), + } + } +} + +func ListUsersWithNameMatching(query string) ListUsersOpt { + return func() []qm.QueryMod { + return []qm.QueryMod{ + orm.UserWhere.FullNameSearch.LIKE(fmt.Sprintf("%%%s%%", strings.ToLower(query))), + qm.OrderBy(fmt.Sprintf("similarity(full_name_search, '%s') DESC", query)), + } + } +} + +func ListUsersWithLimit(limit int) ListUsersOpt { + return func() []qm.QueryMod { + return []qm.QueryMod{ + qm.Limit(limit), + } } } func (r *Repo) ListUsers(ctx context.Context, opts ...ListUsersOpt) (orm.UserSlice, error) { query := make([]qm.QueryMod, 0, len(opts)) for _, opt := range opts { - query = append(query, opt()) + query = append(query, opt()...) } users, err := orm.Users(query...).All(ctx, r.executor()) @@ -891,3 +911,25 @@ func (r *Repo) CreateWorkoutComment(ctx context.Context, p CreateWorkoutCommentP return comment, nil } + +type CountUsersOpt func() qm.QueryMod + +func CountUsersWithNameMatching(query string) CountUsersOpt { + return func() qm.QueryMod { + return orm.UserWhere.FullNameSearch.LIKE(fmt.Sprintf("%%%s%%", strings.ToLower(query))) + } +} + +func (r *Repo) CountUsers(ctx context.Context, opts ...CountUsersOpt) (int64, error) { + query := make([]qm.QueryMod, 0, len(opts)) + for _, opt := range opts { + query = append(query, opt()) + } + + count, err := orm.Users(query...).Count(ctx, r.executor()) + if err != nil { + return 0, fmt.Errorf("users count: %w", err) + } + + return count, nil +} diff --git a/server/rpc/v1/user.go b/server/rpc/v1/user.go index 2bc8584e..86e109ab 100644 --- a/server/rpc/v1/user.go +++ b/server/rpc/v1/user.go @@ -2,10 +2,12 @@ package v1 import ( "context" + "time" "connectrpc.com/connect" "go.uber.org/zap" + "github.com/crlssn/getstronger/server/pkg/orm" v1 "github.com/crlssn/getstronger/server/pkg/pb/api/v1" "github.com/crlssn/getstronger/server/pkg/pb/api/v1/apiv1connect" "github.com/crlssn/getstronger/server/pkg/repo" @@ -18,6 +20,61 @@ type userHandler struct { repo *repo.Repo } +func (h *userHandler) Get(ctx context.Context, req *connect.Request[v1.GetUserRequest]) (*connect.Response[v1.GetUserResponse], error) { + log := xcontext.MustExtractLogger(ctx) + + user, err := h.repo.GetUser(ctx, repo.GetUserWithID(req.Msg.GetId())) + if err != nil { + log.Error("failed to get user", zap.Error(err)) + return nil, connect.NewError(connect.CodeInternal, nil) + } + + return &connect.Response[v1.GetUserResponse]{ + Msg: &v1.GetUserResponse{ + User: parseUserToPB(user), + }, + }, nil +} + +func (h *userHandler) Search(ctx context.Context, req *connect.Request[v1.SearchRequest]) (*connect.Response[v1.SearchResponse], error) { + log := xcontext.MustExtractLogger(ctx) + + count, err := h.repo.CountUsers(ctx, repo.CountUsersWithNameMatching(req.Msg.GetQuery())) + if err != nil { + log.Error("failed to count users", zap.Error(err)) + return nil, connect.NewError(connect.CodeInternal, nil) + } + + limit := int(req.Msg.GetPagination().GetPageLimit()) + users, err := h.repo.ListUsers(ctx, + repo.ListUsersWithLimit(limit+1), + repo.ListUsersWithNameMatching(req.Msg.GetQuery()), + ) + if err != nil { + log.Error("failed to list users", zap.Error(err)) + return nil, connect.NewError(connect.CodeInternal, nil) + } + + pagination, err := repo.PaginateSlice(users, limit, func(user *orm.User) time.Time { + return user.CreatedAt + }) + if err != nil { + log.Error("failed to paginate users", zap.Error(err)) + return nil, connect.NewError(connect.CodeInternal, nil) + } + + log.Info("searched users") + return &connect.Response[v1.SearchResponse]{ + Msg: &v1.SearchResponse{ + Users: parseUserSliceToPB(pagination.Items), + Pagination: &v1.PaginationResponse{ + TotalResults: count, + NextPageToken: pagination.NextPageToken, + }, + }, + }, nil +} + func NewUserHandler(r *repo.Repo) apiv1connect.UserServiceHandler { return &userHandler{r} } diff --git a/server/rpc/v1/workout.go b/server/rpc/v1/workout.go index 47937fb5..c8f72809 100644 --- a/server/rpc/v1/workout.go +++ b/server/rpc/v1/workout.go @@ -115,13 +115,12 @@ func (h *workoutHandler) Get(ctx context.Context, req *connect.Request[v1.GetWor func (h *workoutHandler) List(ctx context.Context, req *connect.Request[v1.ListWorkoutsRequest]) (*connect.Response[v1.ListWorkoutsResponse], error) { log := xcontext.MustExtractLogger(ctx) - userID := xcontext.MustExtractUserID(ctx) limit := int(req.Msg.GetPageSize()) workouts, err := h.repo.ListWorkouts(ctx, repo.ListWorkoutsWithSets(), repo.ListWorkoutsWithLimit(limit+1), - repo.ListWorkoutsWithUserID(userID), + repo.ListWorkoutsWithUserIDs(req.Msg.GetUserIds()), repo.ListWorkoutsWithComments(), repo.ListWorkoutsWithPageToken(req.Msg.GetPageToken()), ) @@ -155,7 +154,7 @@ func (h *workoutHandler) List(ctx context.Context, req *connect.Request[v1.ListW return nil, connect.NewError(connect.CodeInternal, nil) } - users, err := h.repo.ListUsers(ctx, repo.ListUsersWithIDs(append(userIDs, userID))) + users, err := h.repo.ListUsers(ctx, repo.ListUsersWithIDs(userIDs)) if err != nil { log.Error("failed to list users", zap.Error(err)) return nil, connect.NewError(connect.CodeInternal, nil) diff --git a/web/package-lock.json b/web/package-lock.json index 88fc1859..ae072060 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -16,6 +16,7 @@ "@vueuse/core": "11.3.0", "@vueuse/head": "2.0.0", "@vueuse/integrations": "11.3.0", + "jwt-decode": "^4.0.0", "luxon": "3.5.0", "pinia": "2.2.6", "pinia-plugin-persistedstate": "4.1.2", @@ -6561,6 +6562,15 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/web/package.json b/web/package.json index ecb43eb1..75967a7c 100644 --- a/web/package.json +++ b/web/package.json @@ -22,6 +22,7 @@ "@vueuse/core": "11.3.0", "@vueuse/head": "2.0.0", "@vueuse/integrations": "11.3.0", + "jwt-decode": "^4.0.0", "luxon": "3.5.0", "pinia": "2.2.6", "pinia-plugin-persistedstate": "4.1.2", diff --git a/web/src/clients/clients.ts b/web/src/clients/clients.ts index d58f9fb5..c783178a 100644 --- a/web/src/clients/clients.ts +++ b/web/src/clients/clients.ts @@ -1,6 +1,7 @@ import { createClient } from '@connectrpc/connect' import { auth, logger } from '@/clients/interceptors' import { AuthService } from '@/proto/api/v1/auth_pb.ts' +import { UserService } from '@/proto/api/v1/users_pb.ts' import { RoutineService } from '@/proto/api/v1/routines_pb.ts' import { WorkoutService } from '@/proto/api/v1/workouts_pb.ts' import { ExerciseService } from '@/proto/api/v1/exercise_pb.ts' @@ -16,6 +17,7 @@ const transport = createConnectTransport({ }) export const AuthClient = createClient(AuthService, transport) +export const UserClient = createClient(UserService, transport) export const RoutineClient = createClient(RoutineService, transport) export const WorkoutClient = createClient(WorkoutService, transport) export const ExerciseClient = createClient(ExerciseService, transport) diff --git a/web/src/proto/api/v1/routines_pb.ts b/web/src/proto/api/v1/routines_pb.ts index 89a33577..c38d3359 100644 --- a/web/src/proto/api/v1/routines_pb.ts +++ b/web/src/proto/api/v1/routines_pb.ts @@ -4,9 +4,9 @@ import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv1"; import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1"; +import { file_api_v1_options } from "./options_pb"; import type { Exercise } from "./shared_pb"; import { file_api_v1_shared } from "./shared_pb"; -import { file_api_v1_options } from "./options_pb"; import type { FieldMask } from "@bufbuild/protobuf/wkt"; import { file_google_protobuf_field_mask, file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt"; import { file_buf_validate_validate } from "../../buf/validate/validate_pb"; @@ -16,7 +16,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file api/v1/routines.proto. */ export const file_api_v1_routines: GenFile = /*@__PURE__*/ - fileDesc("ChVhcGkvdjEvcm91dGluZXMucHJvdG8SBmFwaS52MSJNChRDcmVhdGVSb3V0aW5lUmVxdWVzdBIVCgRuYW1lGAEgASgJQge6SARyAhABEh4KDGV4ZXJjaXNlX2lkcxgCIAMoCUIIukgFkgECCAEiIwoVQ3JlYXRlUm91dGluZVJlc3BvbnNlEgoKAmlkGAEgASgJIikKEUdldFJvdXRpbmVSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASI2ChJHZXRSb3V0aW5lUmVzcG9uc2USIAoHcm91dGluZRgBIAEoCzIPLmFwaS52MS5Sb3V0aW5lInEKFFVwZGF0ZVJvdXRpbmVSZXF1ZXN0EigKB3JvdXRpbmUYASABKAsyDy5hcGkudjEuUm91dGluZUIGukgDyAEBEi8KC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFzayI5ChVVcGRhdGVSb3V0aW5lUmVzcG9uc2USIAoHcm91dGluZRgBIAEoCzIPLmFwaS52MS5Sb3V0aW5lIiwKFERlbGV0ZVJvdXRpbmVSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASIXChVEZWxldGVSb3V0aW5lUmVzcG9uc2UiVgoTTGlzdFJvdXRpbmVzUmVxdWVzdBIMCgRuYW1lGAEgASgJEh0KCnBhZ2VfbGltaXQYAiABKAVCCbpIBhoEGGQoARISCgpwYWdlX3Rva2VuGAMgASgMIlIKFExpc3RSb3V0aW5lc1Jlc3BvbnNlEiEKCHJvdXRpbmVzGAEgAygLMg8uYXBpLnYxLlJvdXRpbmUSFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgMIlEKEkFkZEV4ZXJjaXNlUmVxdWVzdBIcCgpyb3V0aW5lX2lkGAEgASgJQgi6SAVyA7ABARIdCgtleGVyY2lzZV9pZBgCIAEoCUIIukgFcgOwAQEiFQoTQWRkRXhlcmNpc2VSZXNwb25zZSJUChVSZW1vdmVFeGVyY2lzZVJlcXVlc3QSHAoKcm91dGluZV9pZBgBIAEoCUIIukgFcgOwAQESHQoLZXhlcmNpc2VfaWQYAiABKAlCCLpIBXIDsAEBIhgKFlJlbW92ZUV4ZXJjaXNlUmVzcG9uc2UiWgoaVXBkYXRlRXhlcmNpc2VPcmRlclJlcXVlc3QSHAoKcm91dGluZV9pZBgBIAEoCUIIukgFcgOwAQESHgoMZXhlcmNpc2VfaWRzGAIgAygJQgi6SAWSAQIIASIdChtVcGRhdGVFeGVyY2lzZU9yZGVyUmVzcG9uc2UiSAoHUm91dGluZRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJEiMKCWV4ZXJjaXNlcxgDIAMoCzIQLmFwaS52MS5FeGVyY2lzZTKPBQoOUm91dGluZVNlcnZpY2USSwoGQ3JlYXRlEhwuYXBpLnYxLkNyZWF0ZVJvdXRpbmVSZXF1ZXN0Gh0uYXBpLnYxLkNyZWF0ZVJvdXRpbmVSZXNwb25zZSIEiLUYARJCCgNHZXQSGS5hcGkudjEuR2V0Um91dGluZVJlcXVlc3QaGi5hcGkudjEuR2V0Um91dGluZVJlc3BvbnNlIgSItRgBEksKBlVwZGF0ZRIcLmFwaS52MS5VcGRhdGVSb3V0aW5lUmVxdWVzdBodLmFwaS52MS5VcGRhdGVSb3V0aW5lUmVzcG9uc2UiBIi1GAESSwoGRGVsZXRlEhwuYXBpLnYxLkRlbGV0ZVJvdXRpbmVSZXF1ZXN0Gh0uYXBpLnYxLkRlbGV0ZVJvdXRpbmVSZXNwb25zZSIEiLUYARJHCgRMaXN0EhsuYXBpLnYxLkxpc3RSb3V0aW5lc1JlcXVlc3QaHC5hcGkudjEuTGlzdFJvdXRpbmVzUmVzcG9uc2UiBIi1GAESTAoLQWRkRXhlcmNpc2USGi5hcGkudjEuQWRkRXhlcmNpc2VSZXF1ZXN0GhsuYXBpLnYxLkFkZEV4ZXJjaXNlUmVzcG9uc2UiBIi1GAESVQoOUmVtb3ZlRXhlcmNpc2USHS5hcGkudjEuUmVtb3ZlRXhlcmNpc2VSZXF1ZXN0Gh4uYXBpLnYxLlJlbW92ZUV4ZXJjaXNlUmVzcG9uc2UiBIi1GAESZAoTVXBkYXRlRXhlcmNpc2VPcmRlchIiLmFwaS52MS5VcGRhdGVFeGVyY2lzZU9yZGVyUmVxdWVzdBojLmFwaS52MS5VcGRhdGVFeGVyY2lzZU9yZGVyUmVzcG9uc2UiBIi1GAFCjgEKCmNvbS5hcGkudjFCDVJvdXRpbmVzUHJvdG9QAVo4Z2l0aHViLmNvbS9jcmxzc24vZ2V0c3Ryb25nZXIvc2VydmVyL3BrZy9wYi9hcGkvdjE7YXBpdjGiAgNBWFiqAgZBcGkuVjHKAgZBcGlcVjHiAhJBcGlcVjFcR1BCTWV0YWRhdGHqAgdBcGk6OlYxYgZwcm90bzM", [file_api_v1_shared, file_api_v1_options, file_google_protobuf_field_mask, file_google_protobuf_timestamp, file_buf_validate_validate]); + fileDesc("ChVhcGkvdjEvcm91dGluZXMucHJvdG8SBmFwaS52MSJNChRDcmVhdGVSb3V0aW5lUmVxdWVzdBIVCgRuYW1lGAEgASgJQge6SARyAhABEh4KDGV4ZXJjaXNlX2lkcxgCIAMoCUIIukgFkgECCAEiIwoVQ3JlYXRlUm91dGluZVJlc3BvbnNlEgoKAmlkGAEgASgJIikKEUdldFJvdXRpbmVSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASI2ChJHZXRSb3V0aW5lUmVzcG9uc2USIAoHcm91dGluZRgBIAEoCzIPLmFwaS52MS5Sb3V0aW5lInEKFFVwZGF0ZVJvdXRpbmVSZXF1ZXN0EigKB3JvdXRpbmUYASABKAsyDy5hcGkudjEuUm91dGluZUIGukgDyAEBEi8KC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFzayI5ChVVcGRhdGVSb3V0aW5lUmVzcG9uc2USIAoHcm91dGluZRgBIAEoCzIPLmFwaS52MS5Sb3V0aW5lIiwKFERlbGV0ZVJvdXRpbmVSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASIXChVEZWxldGVSb3V0aW5lUmVzcG9uc2UiVgoTTGlzdFJvdXRpbmVzUmVxdWVzdBIMCgRuYW1lGAEgASgJEh0KCnBhZ2VfbGltaXQYAiABKAVCCbpIBhoEGGQoARISCgpwYWdlX3Rva2VuGAMgASgMIlIKFExpc3RSb3V0aW5lc1Jlc3BvbnNlEiEKCHJvdXRpbmVzGAEgAygLMg8uYXBpLnYxLlJvdXRpbmUSFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgMIlEKEkFkZEV4ZXJjaXNlUmVxdWVzdBIcCgpyb3V0aW5lX2lkGAEgASgJQgi6SAVyA7ABARIdCgtleGVyY2lzZV9pZBgCIAEoCUIIukgFcgOwAQEiFQoTQWRkRXhlcmNpc2VSZXNwb25zZSJUChVSZW1vdmVFeGVyY2lzZVJlcXVlc3QSHAoKcm91dGluZV9pZBgBIAEoCUIIukgFcgOwAQESHQoLZXhlcmNpc2VfaWQYAiABKAlCCLpIBXIDsAEBIhgKFlJlbW92ZUV4ZXJjaXNlUmVzcG9uc2UiWgoaVXBkYXRlRXhlcmNpc2VPcmRlclJlcXVlc3QSHAoKcm91dGluZV9pZBgBIAEoCUIIukgFcgOwAQESHgoMZXhlcmNpc2VfaWRzGAIgAygJQgi6SAWSAQIIASIdChtVcGRhdGVFeGVyY2lzZU9yZGVyUmVzcG9uc2UiSAoHUm91dGluZRIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJEiMKCWV4ZXJjaXNlcxgDIAMoCzIQLmFwaS52MS5FeGVyY2lzZTKPBQoOUm91dGluZVNlcnZpY2USSwoGQ3JlYXRlEhwuYXBpLnYxLkNyZWF0ZVJvdXRpbmVSZXF1ZXN0Gh0uYXBpLnYxLkNyZWF0ZVJvdXRpbmVSZXNwb25zZSIEiLUYARJCCgNHZXQSGS5hcGkudjEuR2V0Um91dGluZVJlcXVlc3QaGi5hcGkudjEuR2V0Um91dGluZVJlc3BvbnNlIgSItRgBEksKBlVwZGF0ZRIcLmFwaS52MS5VcGRhdGVSb3V0aW5lUmVxdWVzdBodLmFwaS52MS5VcGRhdGVSb3V0aW5lUmVzcG9uc2UiBIi1GAESSwoGRGVsZXRlEhwuYXBpLnYxLkRlbGV0ZVJvdXRpbmVSZXF1ZXN0Gh0uYXBpLnYxLkRlbGV0ZVJvdXRpbmVSZXNwb25zZSIEiLUYARJHCgRMaXN0EhsuYXBpLnYxLkxpc3RSb3V0aW5lc1JlcXVlc3QaHC5hcGkudjEuTGlzdFJvdXRpbmVzUmVzcG9uc2UiBIi1GAESTAoLQWRkRXhlcmNpc2USGi5hcGkudjEuQWRkRXhlcmNpc2VSZXF1ZXN0GhsuYXBpLnYxLkFkZEV4ZXJjaXNlUmVzcG9uc2UiBIi1GAESVQoOUmVtb3ZlRXhlcmNpc2USHS5hcGkudjEuUmVtb3ZlRXhlcmNpc2VSZXF1ZXN0Gh4uYXBpLnYxLlJlbW92ZUV4ZXJjaXNlUmVzcG9uc2UiBIi1GAESZAoTVXBkYXRlRXhlcmNpc2VPcmRlchIiLmFwaS52MS5VcGRhdGVFeGVyY2lzZU9yZGVyUmVxdWVzdBojLmFwaS52MS5VcGRhdGVFeGVyY2lzZU9yZGVyUmVzcG9uc2UiBIi1GAFCjgEKCmNvbS5hcGkudjFCDVJvdXRpbmVzUHJvdG9QAVo4Z2l0aHViLmNvbS9jcmxzc24vZ2V0c3Ryb25nZXIvc2VydmVyL3BrZy9wYi9hcGkvdjE7YXBpdjGiAgNBWFiqAgZBcGkuVjHKAgZBcGlcVjHiAhJBcGlcVjFcR1BCTWV0YWRhdGHqAgdBcGk6OlYxYgZwcm90bzM", [file_api_v1_options, file_api_v1_shared, file_google_protobuf_field_mask, file_google_protobuf_timestamp, file_buf_validate_validate]); /** * @generated from message api.v1.CreateRoutineRequest diff --git a/web/src/proto/api/v1/shared_pb.ts b/web/src/proto/api/v1/shared_pb.ts index d7282161..e33fc2de 100644 --- a/web/src/proto/api/v1/shared_pb.ts +++ b/web/src/proto/api/v1/shared_pb.ts @@ -11,7 +11,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file api/v1/shared.proto. */ export const file_api_v1_shared: GenFile = /*@__PURE__*/ - fileDesc("ChNhcGkvdjEvc2hhcmVkLnByb3RvEgZhcGkudjEiXwoMRXhlcmNpc2VTZXRzEioKCGV4ZXJjaXNlGAEgASgLMhAuYXBpLnYxLkV4ZXJjaXNlQga6SAPIAQESIwoEc2V0cxgCIAMoCzILLmFwaS52MS5TZXRCCLpIBZIBAggBIj0KCEV4ZXJjaXNlEhQKAmlkGAEgASgJQgi6SAVyA7ABARIMCgRuYW1lGAIgASgJEg0KBWxhYmVsGAMgASgJIiwKA1NldBIOCgZ3ZWlnaHQYASABKAESFQoEcmVwcxgCIAEoBUIHukgEGgIoASJVCgRVc2VyEhQKAmlkGAEgASgJQgi6SAVyA7ABARIbCgpmaXJzdF9uYW1lGAIgASgJQge6SARyAhABEhoKCWxhc3RfbmFtZRgDIAEoCUIHukgEcgIQAUKMAQoKY29tLmFwaS52MUILU2hhcmVkUHJvdG9QAVo4Z2l0aHViLmNvbS9jcmxzc24vZ2V0c3Ryb25nZXIvc2VydmVyL3BrZy9wYi9hcGkvdjE7YXBpdjGiAgNBWFiqAgZBcGkuVjHKAgZBcGlcVjHiAhJBcGlcVjFcR1BCTWV0YWRhdGHqAgdBcGk6OlYxYgZwcm90bzM", [file_buf_validate_validate]); + fileDesc("ChNhcGkvdjEvc2hhcmVkLnByb3RvEgZhcGkudjEiXwoMRXhlcmNpc2VTZXRzEioKCGV4ZXJjaXNlGAEgASgLMhAuYXBpLnYxLkV4ZXJjaXNlQga6SAPIAQESIwoEc2V0cxgCIAMoCzILLmFwaS52MS5TZXRCCLpIBZIBAggBIj0KCEV4ZXJjaXNlEhQKAmlkGAEgASgJQgi6SAVyA7ABARIMCgRuYW1lGAIgASgJEg0KBWxhYmVsGAMgASgJIiwKA1NldBIOCgZ3ZWlnaHQYASABKAESFQoEcmVwcxgCIAEoBUIHukgEGgIoASJVCgRVc2VyEhQKAmlkGAEgASgJQgi6SAVyA7ABARIbCgpmaXJzdF9uYW1lGAIgASgJQge6SARyAhABEhoKCWxhc3RfbmFtZRgDIAEoCUIHukgEcgIQASJGChFQYWdpbmF0aW9uUmVxdWVzdBIdCgpwYWdlX2xpbWl0GAEgASgFQgm6SAYaBBhkKAESEgoKcGFnZV90b2tlbhgCIAEoDCJEChJQYWdpbmF0aW9uUmVzcG9uc2USFQoNdG90YWxfcmVzdWx0cxgBIAEoAxIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAxCjAEKCmNvbS5hcGkudjFCC1NoYXJlZFByb3RvUAFaOGdpdGh1Yi5jb20vY3Jsc3NuL2dldHN0cm9uZ2VyL3NlcnZlci9wa2cvcGIvYXBpL3YxO2FwaXYxogIDQVhYqgIGQXBpLlYxygIGQXBpXFYx4gISQXBpXFYxXEdQQk1ldGFkYXRh6gIHQXBpOjpWMWIGcHJvdG8z", [file_buf_validate_validate]); /** * @generated from message api.v1.ExerciseSets @@ -113,3 +113,47 @@ export type User = Message<"api.v1.User"> & { export const UserSchema: GenMessage = /*@__PURE__*/ messageDesc(file_api_v1_shared, 3); +/** + * @generated from message api.v1.PaginationRequest + */ +export type PaginationRequest = Message<"api.v1.PaginationRequest"> & { + /** + * @generated from field: int32 page_limit = 1; + */ + pageLimit: number; + + /** + * @generated from field: bytes page_token = 2; + */ + pageToken: Uint8Array; +}; + +/** + * Describes the message api.v1.PaginationRequest. + * Use `create(PaginationRequestSchema)` to create a new message. + */ +export const PaginationRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1_shared, 4); + +/** + * @generated from message api.v1.PaginationResponse + */ +export type PaginationResponse = Message<"api.v1.PaginationResponse"> & { + /** + * @generated from field: int64 total_results = 1; + */ + totalResults: bigint; + + /** + * @generated from field: bytes next_page_token = 2; + */ + nextPageToken: Uint8Array; +}; + +/** + * Describes the message api.v1.PaginationResponse. + * Use `create(PaginationResponseSchema)` to create a new message. + */ +export const PaginationResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1_shared, 5); + diff --git a/web/src/proto/api/v1/users_pb.ts b/web/src/proto/api/v1/users_pb.ts index 29c48a8a..d74be878 100644 --- a/web/src/proto/api/v1/users_pb.ts +++ b/web/src/proto/api/v1/users_pb.ts @@ -5,7 +5,7 @@ import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv1"; import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1"; import { file_api_v1_options } from "./options_pb"; -import type { User } from "./shared_pb"; +import type { PaginationRequest, PaginationResponse, User } from "./shared_pb"; import { file_api_v1_shared } from "./shared_pb"; import { file_buf_validate_validate } from "../../buf/validate/validate_pb"; import type { Message } from "@bufbuild/protobuf"; @@ -14,7 +14,41 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file api/v1/users.proto. */ export const file_api_v1_users: GenFile = /*@__PURE__*/ - fileDesc("ChJhcGkvdjEvdXNlcnMucHJvdG8SBmFwaS52MSIsCg1Gb2xsb3dSZXF1ZXN0EhsKCWZvbGxvd19pZBgBIAEoCUIIukgFcgOwAQEiEAoORm9sbG93UmVzcG9uc2UiMAoPVW5mb2xsb3dSZXF1ZXN0Eh0KC3VuZm9sbG93X2lkGAEgASgJQgi6SAVyA7ABASISChBVbmZvbGxvd1Jlc3BvbnNlIjUKFExpc3RGb2xsb3dlcnNSZXF1ZXN0Eh0KC2ZvbGxvd2VyX2lkGAEgASgJQgi6SAVyA7ABASI4ChVMaXN0Rm9sbG93ZXJzUmVzcG9uc2USHwoJZm9sbG93ZXJzGAEgAygLMgwuYXBpLnYxLlVzZXIiNQoUTGlzdEZvbGxvd2Vlc1JlcXVlc3QSHQoLZm9sbG93ZWVfaWQYASABKAlCCLpIBXIDsAEBIjgKFUxpc3RGb2xsb3dlZXNSZXNwb25zZRIfCglmb2xsb3dlZXMYASADKAsyDC5hcGkudjEuVXNlcjK5AgoLVXNlclNlcnZpY2USPQoGRm9sbG93EhUuYXBpLnYxLkZvbGxvd1JlcXVlc3QaFi5hcGkudjEuRm9sbG93UmVzcG9uc2UiBIi1GAESQwoIVW5mb2xsb3cSFy5hcGkudjEuVW5mb2xsb3dSZXF1ZXN0GhguYXBpLnYxLlVuZm9sbG93UmVzcG9uc2UiBIi1GAESUgoNTGlzdEZvbGxvd2VycxIcLmFwaS52MS5MaXN0Rm9sbG93ZXJzUmVxdWVzdBodLmFwaS52MS5MaXN0Rm9sbG93ZXJzUmVzcG9uc2UiBIi1GAESUgoNTGlzdEZvbGxvd2VlcxIcLmFwaS52MS5MaXN0Rm9sbG93ZWVzUmVxdWVzdBodLmFwaS52MS5MaXN0Rm9sbG93ZWVzUmVzcG9uc2UiBIi1GAFCiwEKCmNvbS5hcGkudjFCClVzZXJzUHJvdG9QAVo4Z2l0aHViLmNvbS9jcmxzc24vZ2V0c3Ryb25nZXIvc2VydmVyL3BrZy9wYi9hcGkvdjE7YXBpdjGiAgNBWFiqAgZBcGkuVjHKAgZBcGlcVjHiAhJBcGlcVjFcR1BCTWV0YWRhdGHqAgdBcGk6OlYxYgZwcm90bzM", [file_api_v1_options, file_api_v1_shared, file_buf_validate_validate]); + fileDesc("ChJhcGkvdjEvdXNlcnMucHJvdG8SBmFwaS52MSImCg5HZXRVc2VyUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQEiLQoPR2V0VXNlclJlc3BvbnNlEhoKBHVzZXIYASABKAsyDC5hcGkudjEuVXNlciIsCg1Gb2xsb3dSZXF1ZXN0EhsKCWZvbGxvd19pZBgBIAEoCUIIukgFcgOwAQEiEAoORm9sbG93UmVzcG9uc2UiMAoPVW5mb2xsb3dSZXF1ZXN0Eh0KC3VuZm9sbG93X2lkGAEgASgJQgi6SAVyA7ABASISChBVbmZvbGxvd1Jlc3BvbnNlIjUKFExpc3RGb2xsb3dlcnNSZXF1ZXN0Eh0KC2ZvbGxvd2VyX2lkGAEgASgJQgi6SAVyA7ABASI4ChVMaXN0Rm9sbG93ZXJzUmVzcG9uc2USHwoJZm9sbG93ZXJzGAEgAygLMgwuYXBpLnYxLlVzZXIiNQoUTGlzdEZvbGxvd2Vlc1JlcXVlc3QSHQoLZm9sbG93ZWVfaWQYASABKAlCCLpIBXIDsAEBIjgKFUxpc3RGb2xsb3dlZXNSZXNwb25zZRIfCglmb2xsb3dlZXMYASADKAsyDC5hcGkudjEuVXNlciJeCg1TZWFyY2hSZXF1ZXN0EhYKBXF1ZXJ5GAEgASgJQge6SARyAhADEjUKCnBhZ2luYXRpb24YAiABKAsyGS5hcGkudjEuUGFnaW5hdGlvblJlcXVlc3RCBrpIA8gBASJdCg5TZWFyY2hSZXNwb25zZRIbCgV1c2VycxgBIAMoCzIMLmFwaS52MS5Vc2VyEi4KCnBhZ2luYXRpb24YAiABKAsyGi5hcGkudjEuUGFnaW5hdGlvblJlc3BvbnNlMrYDCgtVc2VyU2VydmljZRI8CgNHZXQSFi5hcGkudjEuR2V0VXNlclJlcXVlc3QaFy5hcGkudjEuR2V0VXNlclJlc3BvbnNlIgSItRgBEj0KBkZvbGxvdxIVLmFwaS52MS5Gb2xsb3dSZXF1ZXN0GhYuYXBpLnYxLkZvbGxvd1Jlc3BvbnNlIgSItRgBEkMKCFVuZm9sbG93EhcuYXBpLnYxLlVuZm9sbG93UmVxdWVzdBoYLmFwaS52MS5VbmZvbGxvd1Jlc3BvbnNlIgSItRgBElIKDUxpc3RGb2xsb3dlcnMSHC5hcGkudjEuTGlzdEZvbGxvd2Vyc1JlcXVlc3QaHS5hcGkudjEuTGlzdEZvbGxvd2Vyc1Jlc3BvbnNlIgSItRgBElIKDUxpc3RGb2xsb3dlZXMSHC5hcGkudjEuTGlzdEZvbGxvd2Vlc1JlcXVlc3QaHS5hcGkudjEuTGlzdEZvbGxvd2Vlc1Jlc3BvbnNlIgSItRgBEj0KBlNlYXJjaBIVLmFwaS52MS5TZWFyY2hSZXF1ZXN0GhYuYXBpLnYxLlNlYXJjaFJlc3BvbnNlIgSItRgBQosBCgpjb20uYXBpLnYxQgpVc2Vyc1Byb3RvUAFaOGdpdGh1Yi5jb20vY3Jsc3NuL2dldHN0cm9uZ2VyL3NlcnZlci9wa2cvcGIvYXBpL3YxO2FwaXYxogIDQVhYqgIGQXBpLlYxygIGQXBpXFYx4gISQXBpXFYxXEdQQk1ldGFkYXRh6gIHQXBpOjpWMWIGcHJvdG8z", [file_api_v1_options, file_api_v1_shared, file_buf_validate_validate]); + +/** + * @generated from message api.v1.GetUserRequest + */ +export type GetUserRequest = Message<"api.v1.GetUserRequest"> & { + /** + * @generated from field: string id = 1; + */ + id: string; +}; + +/** + * Describes the message api.v1.GetUserRequest. + * Use `create(GetUserRequestSchema)` to create a new message. + */ +export const GetUserRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1_users, 0); + +/** + * @generated from message api.v1.GetUserResponse + */ +export type GetUserResponse = Message<"api.v1.GetUserResponse"> & { + /** + * @generated from field: api.v1.User user = 1; + */ + user?: User; +}; + +/** + * Describes the message api.v1.GetUserResponse. + * Use `create(GetUserResponseSchema)` to create a new message. + */ +export const GetUserResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1_users, 1); /** * @generated from message api.v1.FollowRequest @@ -31,7 +65,7 @@ export type FollowRequest = Message<"api.v1.FollowRequest"> & { * Use `create(FollowRequestSchema)` to create a new message. */ export const FollowRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1_users, 0); + messageDesc(file_api_v1_users, 2); /** * @generated from message api.v1.FollowResponse @@ -44,7 +78,7 @@ export type FollowResponse = Message<"api.v1.FollowResponse"> & { * Use `create(FollowResponseSchema)` to create a new message. */ export const FollowResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1_users, 1); + messageDesc(file_api_v1_users, 3); /** * @generated from message api.v1.UnfollowRequest @@ -61,7 +95,7 @@ export type UnfollowRequest = Message<"api.v1.UnfollowRequest"> & { * Use `create(UnfollowRequestSchema)` to create a new message. */ export const UnfollowRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1_users, 2); + messageDesc(file_api_v1_users, 4); /** * @generated from message api.v1.UnfollowResponse @@ -74,7 +108,7 @@ export type UnfollowResponse = Message<"api.v1.UnfollowResponse"> & { * Use `create(UnfollowResponseSchema)` to create a new message. */ export const UnfollowResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1_users, 3); + messageDesc(file_api_v1_users, 5); /** * @generated from message api.v1.ListFollowersRequest @@ -91,7 +125,7 @@ export type ListFollowersRequest = Message<"api.v1.ListFollowersRequest"> & { * Use `create(ListFollowersRequestSchema)` to create a new message. */ export const ListFollowersRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1_users, 4); + messageDesc(file_api_v1_users, 6); /** * @generated from message api.v1.ListFollowersResponse @@ -108,7 +142,7 @@ export type ListFollowersResponse = Message<"api.v1.ListFollowersResponse"> & { * Use `create(ListFollowersResponseSchema)` to create a new message. */ export const ListFollowersResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1_users, 5); + messageDesc(file_api_v1_users, 7); /** * @generated from message api.v1.ListFolloweesRequest @@ -125,7 +159,7 @@ export type ListFolloweesRequest = Message<"api.v1.ListFolloweesRequest"> & { * Use `create(ListFolloweesRequestSchema)` to create a new message. */ export const ListFolloweesRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1_users, 6); + messageDesc(file_api_v1_users, 8); /** * @generated from message api.v1.ListFolloweesResponse @@ -142,12 +176,64 @@ export type ListFolloweesResponse = Message<"api.v1.ListFolloweesResponse"> & { * Use `create(ListFolloweesResponseSchema)` to create a new message. */ export const ListFolloweesResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_api_v1_users, 7); + messageDesc(file_api_v1_users, 9); + +/** + * @generated from message api.v1.SearchRequest + */ +export type SearchRequest = Message<"api.v1.SearchRequest"> & { + /** + * @generated from field: string query = 1; + */ + query: string; + + /** + * @generated from field: api.v1.PaginationRequest pagination = 2; + */ + pagination?: PaginationRequest; +}; + +/** + * Describes the message api.v1.SearchRequest. + * Use `create(SearchRequestSchema)` to create a new message. + */ +export const SearchRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1_users, 10); + +/** + * @generated from message api.v1.SearchResponse + */ +export type SearchResponse = Message<"api.v1.SearchResponse"> & { + /** + * @generated from field: repeated api.v1.User users = 1; + */ + users: User[]; + + /** + * @generated from field: api.v1.PaginationResponse pagination = 2; + */ + pagination?: PaginationResponse; +}; + +/** + * Describes the message api.v1.SearchResponse. + * Use `create(SearchResponseSchema)` to create a new message. + */ +export const SearchResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_api_v1_users, 11); /** * @generated from service api.v1.UserService */ export const UserService: GenService<{ + /** + * @generated from rpc api.v1.UserService.Get + */ + get: { + methodKind: "unary"; + input: typeof GetUserRequestSchema; + output: typeof GetUserResponseSchema; + }, /** * @generated from rpc api.v1.UserService.Follow */ @@ -180,6 +266,14 @@ export const UserService: GenService<{ input: typeof ListFolloweesRequestSchema; output: typeof ListFolloweesResponseSchema; }, + /** + * @generated from rpc api.v1.UserService.Search + */ + search: { + methodKind: "unary"; + input: typeof SearchRequestSchema; + output: typeof SearchResponseSchema; + }, }> = /*@__PURE__*/ serviceDesc(file_api_v1_users, 0); diff --git a/web/src/proto/api/v1/workouts_pb.ts b/web/src/proto/api/v1/workouts_pb.ts index 496e922e..7f351321 100644 --- a/web/src/proto/api/v1/workouts_pb.ts +++ b/web/src/proto/api/v1/workouts_pb.ts @@ -16,7 +16,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file api/v1/workouts.proto. */ export const file_api_v1_workouts: GenFile = /*@__PURE__*/ - fileDesc("ChVhcGkvdjEvd29ya291dHMucHJvdG8SBmFwaS52MSLcAQoUQ3JlYXRlV29ya291dFJlcXVlc3QSHAoKcm91dGluZV9pZBgBIAEoCUIIukgFcgOwAQESNQoNZXhlcmNpc2Vfc2V0cxgCIAMoCzIULmFwaS52MS5FeGVyY2lzZVNldHNCCLpIBZIBAggBEjYKCnN0YXJ0ZWRfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQga6SAPIAQESNwoLZmluaXNoZWRfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQga6SAPIAQEiKwoVQ3JlYXRlV29ya291dFJlc3BvbnNlEhIKCndvcmtvdXRfaWQYASABKAkiRwoTTGlzdFdvcmtvdXRzUmVxdWVzdBIcCglwYWdlX3NpemUYAiABKAVCCbpIBhoEGGQoARISCgpwYWdlX3Rva2VuGAMgASgMIlIKFExpc3RXb3Jrb3V0c1Jlc3BvbnNlEiEKCHdvcmtvdXRzGAEgAygLMg8uYXBpLnYxLldvcmtvdXQSFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgMIikKEUdldFdvcmtvdXRSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASI2ChJHZXRXb3Jrb3V0UmVzcG9uc2USIAoHd29ya291dBgBIAEoCzIPLmFwaS52MS5Xb3Jrb3V0IiwKFERlbGV0ZVdvcmtvdXRSZXF1ZXN0EhQKAmlkGAEgASgJQgi6SAVyA7ABASIXChVEZWxldGVXb3Jrb3V0UmVzcG9uc2UiTAoSUG9zdENvbW1lbnRSZXF1ZXN0EhwKCndvcmtvdXRfaWQYASABKAlCCLpIBXIDsAEBEhgKB2NvbW1lbnQYAiABKAlCB7pIBHICEAEiPgoTUG9zdENvbW1lbnRSZXNwb25zZRInCgdjb21tZW50GAEgASgLMhYuYXBpLnYxLldvcmtvdXRDb21tZW50IvQBCgdXb3Jrb3V0EhQKAmlkGAEgASgJQgi6SAVyA7ABARIVCgRuYW1lGAIgASgJQge6SARyAhABEiIKBHVzZXIYAyABKAsyDC5hcGkudjEuVXNlckIGukgDyAEBEjUKDWV4ZXJjaXNlX3NldHMYBCADKAsyFC5hcGkudjEuRXhlcmNpc2VTZXRzQgi6SAWSAQIIARIoCghjb21tZW50cxgFIAMoCzIWLmFwaS52MS5Xb3Jrb3V0Q29tbWVudBI3CgtmaW5pc2hlZF9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCBrpIA8gBASKcAQoOV29ya291dENvbW1lbnQSFAoCaWQYASABKAlCCLpIBXIDsAEBEiIKBHVzZXIYAiABKAsyDC5hcGkudjEuVXNlckIGukgDyAEBEhgKB2NvbW1lbnQYBCABKAlCB7pIBHICEAESNgoKY3JlYXRlZF9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCBrpIA8gBATKFAwoOV29ya291dFNlcnZpY2USSwoGQ3JlYXRlEhwuYXBpLnYxLkNyZWF0ZVdvcmtvdXRSZXF1ZXN0Gh0uYXBpLnYxLkNyZWF0ZVdvcmtvdXRSZXNwb25zZSIEiLUYARJCCgNHZXQSGS5hcGkudjEuR2V0V29ya291dFJlcXVlc3QaGi5hcGkudjEuR2V0V29ya291dFJlc3BvbnNlIgSItRgBEkcKBExpc3QSGy5hcGkudjEuTGlzdFdvcmtvdXRzUmVxdWVzdBocLmFwaS52MS5MaXN0V29ya291dHNSZXNwb25zZSIEiLUYARJLCgZEZWxldGUSHC5hcGkudjEuRGVsZXRlV29ya291dFJlcXVlc3QaHS5hcGkudjEuRGVsZXRlV29ya291dFJlc3BvbnNlIgSItRgBEkwKC1Bvc3RDb21tZW50EhouYXBpLnYxLlBvc3RDb21tZW50UmVxdWVzdBobLmFwaS52MS5Qb3N0Q29tbWVudFJlc3BvbnNlIgSItRgBQo4BCgpjb20uYXBpLnYxQg1Xb3Jrb3V0c1Byb3RvUAFaOGdpdGh1Yi5jb20vY3Jsc3NuL2dldHN0cm9uZ2VyL3NlcnZlci9wa2cvcGIvYXBpL3YxO2FwaXYxogIDQVhYqgIGQXBpLlYxygIGQXBpXFYx4gISQXBpXFYxXEdQQk1ldGFkYXRh6gIHQXBpOjpWMWIGcHJvdG8z", [file_api_v1_options, file_api_v1_shared, file_google_protobuf_field_mask, file_google_protobuf_timestamp, file_buf_validate_validate]); + fileDesc("ChVhcGkvdjEvd29ya291dHMucHJvdG8SBmFwaS52MSLcAQoUQ3JlYXRlV29ya291dFJlcXVlc3QSHAoKcm91dGluZV9pZBgBIAEoCUIIukgFcgOwAQESNQoNZXhlcmNpc2Vfc2V0cxgCIAMoCzIULmFwaS52MS5FeGVyY2lzZVNldHNCCLpIBZIBAggBEjYKCnN0YXJ0ZWRfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQga6SAPIAQESNwoLZmluaXNoZWRfYXQYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQga6SAPIAQEiKwoVQ3JlYXRlV29ya291dFJlc3BvbnNlEhIKCndvcmtvdXRfaWQYASABKAkiagoTTGlzdFdvcmtvdXRzUmVxdWVzdBIhCgh1c2VyX2lkcxgBIAMoCUIPukgMkgEJCAEiBXIDsAEBEhwKCXBhZ2Vfc2l6ZRgCIAEoBUIJukgGGgQYZCgBEhIKCnBhZ2VfdG9rZW4YAyABKAwiUgoUTGlzdFdvcmtvdXRzUmVzcG9uc2USIQoId29ya291dHMYASADKAsyDy5hcGkudjEuV29ya291dBIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAwiKQoRR2V0V29ya291dFJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBIjYKEkdldFdvcmtvdXRSZXNwb25zZRIgCgd3b3Jrb3V0GAEgASgLMg8uYXBpLnYxLldvcmtvdXQiLAoURGVsZXRlV29ya291dFJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBIhcKFURlbGV0ZVdvcmtvdXRSZXNwb25zZSJMChJQb3N0Q29tbWVudFJlcXVlc3QSHAoKd29ya291dF9pZBgBIAEoCUIIukgFcgOwAQESGAoHY29tbWVudBgCIAEoCUIHukgEcgIQASI+ChNQb3N0Q29tbWVudFJlc3BvbnNlEicKB2NvbW1lbnQYASABKAsyFi5hcGkudjEuV29ya291dENvbW1lbnQi9AEKB1dvcmtvdXQSFAoCaWQYASABKAlCCLpIBXIDsAEBEhUKBG5hbWUYAiABKAlCB7pIBHICEAESIgoEdXNlchgDIAEoCzIMLmFwaS52MS5Vc2VyQga6SAPIAQESNQoNZXhlcmNpc2Vfc2V0cxgEIAMoCzIULmFwaS52MS5FeGVyY2lzZVNldHNCCLpIBZIBAggBEigKCGNvbW1lbnRzGAUgAygLMhYuYXBpLnYxLldvcmtvdXRDb21tZW50EjcKC2ZpbmlzaGVkX2F0GAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEIGukgDyAEBIpwBCg5Xb3Jrb3V0Q29tbWVudBIUCgJpZBgBIAEoCUIIukgFcgOwAQESIgoEdXNlchgCIAEoCzIMLmFwaS52MS5Vc2VyQga6SAPIAQESGAoHY29tbWVudBgEIAEoCUIHukgEcgIQARI2CgpjcmVhdGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEIGukgDyAEBMoUDCg5Xb3Jrb3V0U2VydmljZRJLCgZDcmVhdGUSHC5hcGkudjEuQ3JlYXRlV29ya291dFJlcXVlc3QaHS5hcGkudjEuQ3JlYXRlV29ya291dFJlc3BvbnNlIgSItRgBEkIKA0dldBIZLmFwaS52MS5HZXRXb3Jrb3V0UmVxdWVzdBoaLmFwaS52MS5HZXRXb3Jrb3V0UmVzcG9uc2UiBIi1GAESRwoETGlzdBIbLmFwaS52MS5MaXN0V29ya291dHNSZXF1ZXN0GhwuYXBpLnYxLkxpc3RXb3Jrb3V0c1Jlc3BvbnNlIgSItRgBEksKBkRlbGV0ZRIcLmFwaS52MS5EZWxldGVXb3Jrb3V0UmVxdWVzdBodLmFwaS52MS5EZWxldGVXb3Jrb3V0UmVzcG9uc2UiBIi1GAESTAoLUG9zdENvbW1lbnQSGi5hcGkudjEuUG9zdENvbW1lbnRSZXF1ZXN0GhsuYXBpLnYxLlBvc3RDb21tZW50UmVzcG9uc2UiBIi1GAFCjgEKCmNvbS5hcGkudjFCDVdvcmtvdXRzUHJvdG9QAVo4Z2l0aHViLmNvbS9jcmxzc24vZ2V0c3Ryb25nZXIvc2VydmVyL3BrZy9wYi9hcGkvdjE7YXBpdjGiAgNBWFiqAgZBcGkuVjHKAgZBcGlcVjHiAhJBcGlcVjFcR1BCTWV0YWRhdGHqAgdBcGk6OlYxYgZwcm90bzM", [file_api_v1_options, file_api_v1_shared, file_google_protobuf_field_mask, file_google_protobuf_timestamp, file_buf_validate_validate]); /** * @generated from message api.v1.CreateWorkoutRequest @@ -71,6 +71,11 @@ export const CreateWorkoutResponseSchema: GenMessage = /* * @generated from message api.v1.ListWorkoutsRequest */ export type ListWorkoutsRequest = Message<"api.v1.ListWorkoutsRequest"> & { + /** + * @generated from field: repeated string user_ids = 1; + */ + userIds: string[]; + /** * @generated from field: int32 page_size = 2; */ diff --git a/web/src/router/router.ts b/web/src/router/router.ts index 0f869c70..e1b95cc9 100644 --- a/web/src/router/router.ts +++ b/web/src/router/router.ts @@ -3,6 +3,7 @@ import NotFound from '@/ui/NotFound.vue' import { create } from '@bufbuild/protobuf' import { useAuthStore } from '@/stores/auth' import { AuthClient } from '@/clients/clients' +import UserView from '@/ui/users/UserView.vue' import UserLogin from '@/ui/auth/UserLogin.vue' import UserSignup from '@/ui/auth/UserSignup.vue' import { usePageTitleStore } from '@/stores/pageTitle' @@ -36,6 +37,13 @@ const router: Router = createRouter({ name: 'profile', path: '/profile', }, + { + beforeEnter: [auth], + component: UserView, + meta: { title: '' }, + name: 'user-view', + path: '/users/:id', + }, { beforeEnter: [auth], component: ListWorkouts, diff --git a/web/src/stores/auth.ts b/web/src/stores/auth.ts index fb5e8eae..9b45f310 100644 --- a/web/src/stores/auth.ts +++ b/web/src/stores/auth.ts @@ -1,27 +1,36 @@ +import type { AccessToken } from '@/types/auth.ts' + import { ref } from 'vue' import { defineStore } from 'pinia' +import { jwtDecode } from 'jwt-decode' export const useAuthStore = defineStore( 'auth', () => { + const userID = ref('') const accessToken = ref('') const accessTokenRefreshInterval = ref(0) - function setAccessToken(token: string): void { + const setAccessToken = (token: string) => { console.log('setting access token', token) + if (userID.value === '') { + const claims = jwtDecode(token) as AccessToken + userID.value = claims.userId + } accessToken.value = token } - function logout() { + const logout = () => { + userID.value = '' accessToken.value = '' clearInterval(accessTokenRefreshInterval.value) } - function setAccessTokenRefreshInterval(interval: number) { + const setAccessTokenRefreshInterval = (interval: number) => { accessTokenRefreshInterval.value = interval } - return { accessToken, logout, setAccessToken, setAccessTokenRefreshInterval } + return { accessToken, logout, setAccessToken, setAccessTokenRefreshInterval, userID } }, { persist: true, diff --git a/web/src/types/auth.ts b/web/src/types/auth.ts new file mode 100644 index 00000000..a443c1a8 --- /dev/null +++ b/web/src/types/auth.ts @@ -0,0 +1,5 @@ +import type { JwtPayload } from 'jwt-decode' + +export interface AccessToken extends JwtPayload{ + userId: string +} diff --git a/web/src/ui/components/CardWorkout.vue b/web/src/ui/components/CardWorkout.vue index ae2cb43b..98e81b04 100644 --- a/web/src/ui/components/CardWorkout.vue +++ b/web/src/ui/components/CardWorkout.vue @@ -72,13 +72,18 @@ const postComment = async () => { />
- +
+ +