Skip to content
This repository was archived by the owner on Sep 2, 2024. It is now read-only.

Commit 4fe5f2a

Browse files
committed
refactored the storage API to use the backend package as a PoC
1 parent 6c3994b commit 4fe5f2a

File tree

11 files changed

+177
-119
lines changed

11 files changed

+177
-119
lines changed

account.go

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

33
import (
44
"fmt"
5-
"math/rand"
65
"net/http"
76
"strings"
87
"time"
98

109
"github.com/staticbackendhq/core/config"
1110
emailFuncs "github.com/staticbackendhq/core/email"
11+
"github.com/staticbackendhq/core/internal"
1212
"github.com/staticbackendhq/core/logger"
1313
"github.com/staticbackendhq/core/middleware"
1414
"github.com/staticbackendhq/core/model"
@@ -19,10 +19,6 @@ import (
1919
"github.com/stripe/stripe-go/v72/sub"
2020
)
2121

22-
var (
23-
letterRunes = []rune("abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ2345679")
24-
)
25-
2622
type accounts struct {
2723
membership *membership
2824
log *logger.Logger
@@ -123,7 +119,7 @@ func (a *accounts) create(w http.ResponseWriter, r *http.Request) {
123119

124120
// make sure the DB name is unique
125121
retry := 10
126-
dbName := randStringRunes(12)
122+
dbName := internal.RandStringRunes(12)
127123
if memoryMode {
128124
dbName = "dev-memory-pk"
129125
}
@@ -134,7 +130,7 @@ func (a *accounts) create(w http.ResponseWriter, r *http.Request) {
134130
return
135131
} else if exists {
136132
retry--
137-
dbName = randStringRunes(12)
133+
dbName = internal.RandStringRunes(12)
138134
continue
139135
}
140136
break
@@ -156,7 +152,7 @@ func (a *accounts) create(w http.ResponseWriter, r *http.Request) {
156152

157153
// we create an admin user
158154
// we make sure to switch DB
159-
pw := randStringRunes(6)
155+
pw := internal.RandStringRunes(6)
160156
if memoryMode {
161157
pw = "devpw1234"
162158
}
@@ -312,15 +308,3 @@ func getStripePortalURL(customerID string) (string, error) {
312308

313309
return s.URL, nil
314310
}
315-
316-
func randStringRunes(n int) string {
317-
b := make([]rune, n)
318-
for i := range b {
319-
b[i] = letterRunes[rand.Intn(len(letterRunes))]
320-
}
321-
322-
// due to PostgreSQL schema requiring letter start.
323-
b[0] = letterRunes[0]
324-
325-
return string(b)
326-
}

backend/backend.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
type Backend struct {
3030
DB database.Persister
3131
User func(baseID string) User
32+
File func(model.Auth, model.BaseConfig) FileStore
3233
}
3334

3435
var (
@@ -132,6 +133,7 @@ func New(cfg config.AppConfig) Backend {
132133
return Backend{
133134
DB: datastore,
134135
User: newUser,
136+
File: newFile,
135137
}
136138
}
137139

backend/file.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package backend
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"path/filepath"
7+
"time"
8+
9+
"github.com/staticbackendhq/core/internal"
10+
"github.com/staticbackendhq/core/model"
11+
)
12+
13+
type FileStore struct {
14+
auth model.Auth
15+
conf model.BaseConfig
16+
}
17+
18+
func newFile(auth model.Auth, conf model.BaseConfig) FileStore {
19+
return FileStore{
20+
auth: auth,
21+
conf: conf,
22+
}
23+
}
24+
25+
type SavedFile struct {
26+
ID string `json:"id"`
27+
URL string `json:"url"`
28+
}
29+
30+
func (f FileStore) Save(filename, name string, file io.ReadSeeker, size int64) (sf SavedFile, err error) {
31+
ext := filepath.Ext(name)
32+
33+
if len(name) == 0 {
34+
// if no forced name is used, let's use the original name
35+
name = internal.CleanUpFileName(filename)
36+
}
37+
38+
fileKey := fmt.Sprintf("%s/%s/%s%s",
39+
f.conf.Name,
40+
f.auth.AccountID,
41+
name,
42+
ext,
43+
)
44+
45+
upData := model.UploadFileData{FileKey: fileKey, File: file}
46+
url, err := Filestore.Save(upData)
47+
if err != nil {
48+
return
49+
}
50+
51+
sbFile := model.File{
52+
AccountID: f.auth.AccountID,
53+
Key: fileKey,
54+
URL: url,
55+
Size: size,
56+
Uploaded: time.Now(),
57+
}
58+
59+
newID, err := datastore.AddFile(f.conf.Name, sbFile)
60+
if err != nil {
61+
return
62+
}
63+
64+
sf.ID = newID
65+
sf.URL = url
66+
67+
return
68+
}
69+
70+
func (f FileStore) Delete(fileID string) error {
71+
file, err := datastore.GetFileByID(f.conf.Name, fileID)
72+
if err != nil {
73+
return err
74+
}
75+
76+
fileKey := file.Key
77+
78+
if err := Filestore.Delete(fileKey); err != nil {
79+
return err
80+
}
81+
82+
if err := datastore.DeleteFile(f.conf.Name, file.ID); err != nil {
83+
return err
84+
}
85+
return nil
86+
}

backend/user.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import (
66
"strings"
77
"time"
88

9-
sb "github.com/staticbackendhq/core"
9+
"github.com/gbrlsnchs/jwt/v3"
10+
"github.com/staticbackendhq/core/internal"
1011
"github.com/staticbackendhq/core/model"
1112
"golang.org/x/crypto/bcrypt"
1213
)
@@ -63,7 +64,7 @@ func (u User) Authenticate(email, password string) (string, error) {
6364

6465
token := fmt.Sprintf("%s|%s", tok.ID, tok.Token)
6566

66-
jwt, err := sb.GetJWT(token)
67+
jwt, err := GetJWT(token)
6768
if err != nil {
6869
return "", err
6970
}
@@ -117,3 +118,20 @@ func (u User) UserSetPassword(tokenID, password string) error {
117118

118119
return datastore.UserSetPassword(u.conf.Name, tokenID, string(b))
119120
}
121+
122+
func GetJWT(token string) ([]byte, error) {
123+
now := time.Now()
124+
pl := model.JWTPayload{
125+
Payload: jwt.Payload{
126+
Issuer: "StaticBackend",
127+
ExpirationTime: jwt.NumericDate(now.Add(12 * time.Hour)),
128+
NotBefore: jwt.NumericDate(now.Add(30 * time.Minute)),
129+
IssuedAt: jwt.NumericDate(now),
130+
JWTID: internal.RandStringRunes(32),
131+
},
132+
Token: token,
133+
}
134+
135+
return jwt.Sign(pl, model.HashSecret)
136+
137+
}

extras.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/chromedp/cdproto/page"
1313
"github.com/chromedp/chromedp"
1414
"github.com/staticbackendhq/core/extra"
15+
"github.com/staticbackendhq/core/internal"
1516
"github.com/staticbackendhq/core/logger"
1617
"github.com/staticbackendhq/core/middleware"
1718
"github.com/staticbackendhq/core/model"
@@ -54,7 +55,7 @@ func (ex *extras) resizeImage(w http.ResponseWriter, r *http.Request) {
5455

5556
name := r.Form.Get("name")
5657
if len(name) == 0 {
57-
name = randStringRunes(32)
58+
name = internal.RandStringRunes(32)
5859
}
5960

6061
newWidth, err := strconv.ParseFloat(r.Form.Get("width"), 64)

internal/helpers.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package internal
2+
3+
import (
4+
"math/rand"
5+
"path/filepath"
6+
"regexp"
7+
"strings"
8+
)
9+
10+
var (
11+
letterRunes = []rune("abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ2345679")
12+
)
13+
14+
// RandStringRunes returns a random string with n characters
15+
func RandStringRunes(n int) string {
16+
b := make([]rune, n)
17+
for i := range b {
18+
b[i] = letterRunes[rand.Intn(len(letterRunes))]
19+
}
20+
21+
// due to PostgreSQL schema requiring letter start.
22+
b[0] = letterRunes[0]
23+
24+
return string(b)
25+
}
26+
27+
// CleanUpFileName removes file extention and anything but a-zA-Z-_
28+
func CleanUpFileName(s string) string {
29+
s = strings.TrimSuffix(s, filepath.Ext(s))
30+
31+
exp := regexp.MustCompile(`[^a-zA-Z\-_]`)
32+
33+
return exp.ReplaceAllString(s, "")
34+
35+
}

membership.go

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@ import (
88
"math/rand"
99
"net/http"
1010
"strings"
11-
"time"
1211

12+
"github.com/staticbackendhq/core/backend"
1313
"github.com/staticbackendhq/core/config"
1414
"github.com/staticbackendhq/core/email"
15+
"github.com/staticbackendhq/core/internal"
1516
"github.com/staticbackendhq/core/logger"
1617
"github.com/staticbackendhq/core/middleware"
1718
"github.com/staticbackendhq/core/model"
1819

1920
"golang.org/x/crypto/bcrypt"
20-
21-
"github.com/gbrlsnchs/jwt/v3"
2221
)
2322

2423
type membership struct {
@@ -150,7 +149,7 @@ func (m *membership) getAuthToken(tok model.Token, conf model.BaseConfig) (jwtBy
150149
token := fmt.Sprintf("%s|%s", tok.ID, tok.Token)
151150

152151
// get their JWT
153-
jwtBytes, err = GetJWT(token)
152+
jwtBytes, err = backend.GetJWT(token)
154153
if err != nil {
155154
return
156155
}
@@ -212,7 +211,7 @@ func (m *membership) createUser(dbName, accountID, email, password string, role
212211
token := fmt.Sprintf("%s|%s", tokID, tok.Token)
213212

214213
// Get their JWT
215-
jwtBytes, err := GetJWT(token)
214+
jwtBytes, err := backend.GetJWT(token)
216215
if err != nil {
217216
return nil, tok, err
218217
}
@@ -238,7 +237,7 @@ func (m *membership) setResetCode(w http.ResponseWriter, r *http.Request) {
238237
return
239238
}
240239

241-
code := randStringRunes(10)
240+
code := internal.RandStringRunes(10)
242241

243242
conf, _, err := middleware.Extract(r, false)
244243
if err != nil {
@@ -356,23 +355,6 @@ func (m *membership) setPassword(w http.ResponseWriter, r *http.Request) {
356355
respond(w, http.StatusOK, true)
357356
}
358357

359-
func GetJWT(token string) ([]byte, error) {
360-
now := time.Now()
361-
pl := model.JWTPayload{
362-
Payload: jwt.Payload{
363-
Issuer: "StaticBackend",
364-
ExpirationTime: jwt.NumericDate(now.Add(12 * time.Hour)),
365-
NotBefore: jwt.NumericDate(now.Add(30 * time.Minute)),
366-
IssuedAt: jwt.NumericDate(now),
367-
JWTID: randStringRunes(32), // changed from primitive.NewObjectID
368-
},
369-
Token: token,
370-
}
371-
372-
return jwt.Sign(pl, model.HashSecret)
373-
374-
}
375-
376358
func (m *membership) sudoGetTokenFromAccountID(w http.ResponseWriter, r *http.Request) {
377359
conf, _, err := middleware.Extract(r, false)
378360
if err != nil {
@@ -393,7 +375,7 @@ func (m *membership) sudoGetTokenFromAccountID(w http.ResponseWriter, r *http.Re
393375

394376
token := fmt.Sprintf("%s|%s", tok.ID, tok.Token)
395377

396-
jwtBytes, err := GetJWT(token)
378+
jwtBytes, err := backend.GetJWT(token)
397379
if err != nil {
398380
http.Error(w, err.Error(), http.StatusInternalServerError)
399381
return

oauth.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/http"
77
"strings"
88

9+
"github.com/staticbackendhq/core/backend"
910
"github.com/staticbackendhq/core/config"
1011
"github.com/staticbackendhq/core/logger"
1112
"github.com/staticbackendhq/core/middleware"
@@ -229,7 +230,7 @@ func (el *ExternalLogins) signIn(dbName, email string) (sessionToken string, err
229230

230231
token := fmt.Sprintf("%s|%s", tok.ID, tok.Token)
231232

232-
b, err := GetJWT(token)
233+
b, err := backend.GetJWT(token)
233234
if err != nil {
234235
return
235236
}

0 commit comments

Comments
 (0)