Skip to content

Commit ccaf6a1

Browse files
authored
Merge pull request #10 from rtmelsov/fix/file-stream
Fix/file stream
2 parents f07447c + 00f10c6 commit ccaf6a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2866
-760
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ db/migrations/*.sql-journal
2121
/.vscode/
2222
.DS_Store
2323
/var/
24+
opt/

Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
APP := tui
33
PKG := ./cmd/tui
44
DIST := dist
5+
SERVER_PKG ?= ./cmd/server
6+
GRPC_ADDR ?= 127.0.0.1:8080
7+
DB_DSN ?= mem://
8+
9+
510

611
.PHONY: build run clean linux mac windows
712

@@ -29,3 +34,15 @@ windows:
2934
mkdir -p $(DIST)
3035
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o $(DIST)/$(APP)_windows_amd64.exe $(PKG)
3136

37+
help:
38+
@echo "make run - run server via 'go run'"
39+
@echo "make build -build server binary into ./bin/server"
40+
@echo "env overrides: GRPC_ADDR (default: $(GRPC_ADDR)), DB_DSN (default: $(DB_DSN))"
41+
@echo "example: make run GRPC_ADDR=:9090 DB_DSN='postgres://...@localhost:5432/vault?sslmode=disable"
42+
buildServer:
43+
@mkdir -p bin
44+
@echo "===> go build ./cmd/server -> ./bin/server"
45+
@go build -o bin/server $(SERVER_PKG)
46+
47+
tidy:
48+
@go mod tidy

api/proto/common/v1/common.proto

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ package common.v1;
33
option go_package = "github.com/rtmelsov/adv-keeper/gen/go/common/v1;commonv1";
44

55
import "google/protobuf/timestamp.proto";
6+
import "google/protobuf/empty.proto";
67

78
service AuthService {
8-
rpc Logout(TokenPair) returns (TokenPair);
9+
rpc Logout(google.protobuf.Empty) returns (TokenPair);
10+
rpc GetProfile(google.protobuf.Empty) returns (GetProfileResponse);
911
rpc Register(RegisterRequest) returns (RegisterResponse);
1012
rpc Login(LoginRequest) returns (LoginResponse);
1113
}
1214

1315
message TokenPair {
1416
string access_token = 1; // JWT (HS256)
15-
//google.protobuf.Timestamp
1617
google.protobuf.Timestamp expires_at = 3; // RFC3339 серверное время истечения refresh
1718
}
1819

@@ -21,9 +22,13 @@ message LoginRequest {
2122
string password = 2;
2223
}
2324

25+
message GetProfileResponse {
26+
string user_id = 1;
27+
string email = 3;
28+
}
29+
2430
message LoginResponse {
2531
string user_id = 1;
26-
string device_id = 2;
2732
string email = 3;
2833
TokenPair tokens = 4; // ← добавили
2934
}
@@ -35,7 +40,6 @@ message RegisterRequest {
3540

3641
message RegisterResponse {
3742
string user_id = 1;
38-
string device_id = 2; // вернём то, что прислал клиент
3943
string email = 3;
4044
TokenPair tokens = 4; // ← добавили
4145
}

api/proto/file/v1/file.proto

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,35 @@
1+
12
syntax = "proto3";
23

34
package file.v1;
45
option go_package = "github.com/rtmelsov/adv-keeper/gen/go/file/v1;filev1";
56

7+
import "google/protobuf/timestamp.proto";
8+
import "google/protobuf/empty.proto";
9+
610
service FileService {
711
// Клиент шлёт поток кусков, сервер в конце отвечает сводкой
812
rpc Upload(stream UploadRequest) returns (UploadResponse);
13+
rpc DownloadFile(DownloadFileRequest) returns (stream DownloadFileResponse);
14+
rpc DeleteFile(DeleteFileRequest) returns (google.protobuf.Empty);
15+
// Список файлов текущего пользователя (берём user_id из контекста)
16+
rpc GetFiles(GetFilesRequest) returns (GetFilesResponse);
17+
}
18+
19+
message GetFilesRequest {
20+
int32 limit = 1; // по умолчанию 50
21+
int32 offset = 2; // по умолчанию 0
22+
}
23+
24+
message FileItem {
25+
string fileid = 1;
26+
string filename = 2;
27+
int64 size = 3;
28+
google.protobuf.Timestamp created_at = 4;
29+
}
30+
31+
message GetFilesResponse {
32+
repeated FileItem files = 1;
933
}
1034

1135
message UploadRequest {
@@ -21,12 +45,32 @@ message FileInfo {
2145
}
2246

2347
message FileChunk {
24-
bytes content = 1; // данные куска (< 4 MiB — лимит gRPC на сообщение)
25-
int64 offset = 2; // сдвиг от начала файла (полезно для резюмации)
48+
bytes content = 1; // данные куска (< 4 MiB — лимит gRPC на сообщение)
49+
int64 offset = 2; // сдвиг от начала файла (полезно для резюмации)
2650
}
2751

2852
message UploadResponse {
2953
string stored_as = 1; // путь/имя сохранённого файла на сервере
3054
int64 bytes_received = 2; // сколько байт приняли
3155
string sha256 = 3; // контрольная сумма принятого
3256
}
57+
58+
59+
message DownloadFileResponse {
60+
oneof payload {
61+
FileInfo info = 1; // ПЕРВОЕ сообщение — мета-инфа
62+
FileChunk chunk = 2; // Далее — куски файла
63+
}
64+
}
65+
66+
message DownloadFileRequest {
67+
string fileid = 1;
68+
}
69+
70+
message DeleteFileRequest {
71+
string fileid = 1;
72+
}
73+
74+
message DeleteFileResponse {
75+
string fileid = 1;
76+
}

cmd/server/main.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@ package main
22

33
import (
44
"database/sql"
5-
"google.golang.org/grpc/reflection"
6-
"log"
5+
"fmt"
76
"net"
87
"time"
98

9+
"github.com/charmbracelet/log"
10+
"google.golang.org/grpc/reflection"
11+
1012
commonv1 "github.com/rtmelsov/adv-keeper/gen/go/proto/common/v1"
1113
filev1 "github.com/rtmelsov/adv-keeper/gen/go/proto/file/v1"
14+
"github.com/rtmelsov/adv-keeper/internal/authserver"
1215
db "github.com/rtmelsov/adv-keeper/internal/db"
13-
"github.com/rtmelsov/adv-keeper/internal/file"
16+
"github.com/rtmelsov/adv-keeper/internal/fileserver"
1417
"github.com/rtmelsov/adv-keeper/internal/helpers"
1518
"github.com/rtmelsov/adv-keeper/internal/middleware"
16-
"github.com/rtmelsov/adv-keeper/internal/server"
1719
"google.golang.org/grpc/keepalive"
1820

1921
_ "github.com/jackc/pgx/v5/stdlib"
@@ -30,7 +32,9 @@ func main() {
3032
if err != nil {
3133
log.Fatal(err)
3234
}
33-
35+
path := fmt.Sprintf("file:/%s", envs.MigrationsFilesDir)
36+
log.Info("path", "path", path)
37+
helpers.RunMigrations(envs.DBDSN, path)
3438
// Подключение к Postgres
3539
dbx, err := sql.Open("pgx", envs.DBDSN)
3640
if err != nil {
@@ -41,6 +45,7 @@ func main() {
4145
q := db.New(dbx)
4246
s := grpc.NewServer(
4347
grpc.UnaryInterceptor(middleware.ServerInterceptor),
48+
grpc.StreamInterceptor(middleware.StreamInterceptor), // вот тут
4449
grpc.KeepaliveParams(keepalive.ServerParameters{
4550
MaxConnectionIdle: 0,
4651
MaxConnectionAge: 0,
@@ -49,12 +54,12 @@ func main() {
4954
Timeout: 20 * time.Second,
5055
}),
5156
)
52-
commonv1.RegisterAuthServiceServer(s, server.New(q))
53-
filev1.RegisterFileServiceServer(s, file.New(q))
57+
commonv1.RegisterAuthServiceServer(s, authserver.New(q))
58+
filev1.RegisterFileServiceServer(s, fileserver.New(q))
5459

5560
reflection.Register(s)
5661

57-
log.Println("gRPC listening on", lis.Addr())
62+
log.Info("gRPC listening on", "add", lis.Addr())
5863
if err := s.Serve(lis); err != nil {
5964
log.Fatal(err)
6065
}

cmd/tui/main.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,15 @@ func main() {
3232

3333
// После выхода выведем список выбранных покупок
3434
m := final.(tui.TuiModel)
35-
if len(m.Selected) == 0 {
35+
if len(m.SelectedPage) == 0 {
3636
fmt.Println("Ничего не выбрано.")
3737
return
3838
}
3939

4040
// Соберём в стабильном порядке
41-
idxs := make([]int, 0, len(m.Selected))
42-
for i := range m.Selected {
41+
idxs := make([]int, 0, len(m.SelectedPage))
42+
for i := range m.SelectedPage {
4343
idxs = append(idxs, i)
4444
}
4545
sort.Ints(idxs)
46-
47-
fmt.Println("Вы выбрали:")
48-
for _, i := range idxs {
49-
fmt.Printf(" • %s\n", m.Choices[i])
50-
}
5146
}

db/queries/auth.sql

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-- name: RegisterWithDevice :one
1+
-- name: Register :one
22
INSERT INTO users (email, pwd_phc, e2ee_pub)
33
VALUES ($1, $2, $3)
44
RETURNING id;
@@ -9,16 +9,27 @@ FROM users
99
WHERE email = $1;
1010

1111
-- name: AddFile :one
12-
INSERT INTO files (user_id, name, path)
13-
VALUES ($1, $2, $3)
14-
RETURNING id, user_id, name, path, created_at;
12+
INSERT INTO files (user_id, filename, path, size_bytes)
13+
VALUES ($1, $2, $3, $4)
14+
RETURNING id, user_id, filename, path, size_bytes, created_at;
1515

1616
-- name: ListFilesByUser :many
17-
SELECT id, name, path, created_at
17+
SELECT id, filename, path, size_bytes, created_at
1818
FROM files
1919
WHERE user_id = $1
2020
ORDER BY created_at DESC;
2121

22-
-- name: DeleteFile :exec
22+
-- name: DeleteFile :one
2323
DELETE FROM files
24+
WHERE id = $1 AND user_id = $2
25+
RETURNING id;-- name: GetUserByID :one
26+
27+
-- name: GetUserByID :one
28+
SELECT id, email, created_at
29+
FROM users
30+
WHERE id = $1;
31+
32+
-- name: GetFileForUser :one
33+
SELECT id, user_id, filename, path, size_bytes, created_at
34+
FROM files
2435
WHERE id = $1 AND user_id = $2;

0 commit comments

Comments
 (0)