diff --git a/Dockerfile b/Dockerfile index 03f6a35..fe2e6e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,9 +7,11 @@ COPY /view /src/view RUN npm install -g tailwindcss RUN npm install -g javascript-obfuscator -RUN npx tailwindcss -i ./public/input.css -o ./public/output.css +RUN npm install -g clean-css-cli +RUN npx tailwindcss -i ./public/input.css -o ./tmp/output.css RUN javascript-obfuscator ./public/upload.js --compact true --self-defending true --output ./public/upload_obfuscated.js RUN javascript-obfuscator ./public/validatePassword.js --compact true --self-defending true --output ./public/validatePassword_obfuscated.js +RUN cleancss -o ./public/output.css ./tmp/output.css FROM golang:1.22.2-alpine3.19 AS go_builder @@ -19,7 +21,7 @@ COPY --from=node_builder /src/public /src/public COPY --from=node_builder /src/public/upload_obfuscated.js /src/public/upload.js COPY --from=node_builder /src/public/validatePassword_obfuscated.js /src/public/validatePassword.js -RUN apk update && apk upgrade && apk add --no-cache ca-certificates +RUN apk update && apk upgrade && apk add --no-cache ca-certificates tzdata RUN update-ca-certificates RUN go install github.com/a-h/templ/cmd/templ@$(go list -m -f '{{ .Version }}' github.com/a-h/templ) RUN templ generate @@ -30,9 +32,12 @@ FROM scratch WORKDIR /src +COPY --from=go_builder /usr/share/zoneinfo /usr/share/zoneinfo COPY --from=go_builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=go_builder /src/schema.sql /src COPY --from=go_builder /src/public /src/public COPY --from=go_builder /src/tmp/main /src +ENV TZ Asia/Jakarta + ENTRYPOINT ["./main"] diff --git a/handler/index/index.go b/handler/index/index.go index f1838bd..4bcbdc2 100644 --- a/handler/index/index.go +++ b/handler/index/index.go @@ -1,6 +1,7 @@ package indexHandler import ( + "github.com/fossyy/filekeeper/session" "net/http" "github.com/fossyy/filekeeper/logger" @@ -14,7 +15,8 @@ func init() { } func GET(w http.ResponseWriter, r *http.Request) { - component := indexView.Main("main page") + _, userSession, _ := session.GetSession(r) + component := indexView.Main("main page", userSession) err := component.Render(r.Context(), w) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/handler/user/user.go b/handler/user/user.go index abe001d..755ae78 100644 --- a/handler/user/user.go +++ b/handler/user/user.go @@ -17,7 +17,7 @@ func init() { func GET(w http.ResponseWriter, r *http.Request) { userSession := r.Context().Value("user").(types.User) - component := userView.Main("User Page", userSession.Email, userSession.Username, session.UserSessionInfoList[userSession.Email]) + component := userView.Main("User Page", userSession.Email, userSession.Username, session.GetSessions(userSession.Email)) err := component.Render(r.Context(), w) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/middleware/middleware.go b/middleware/middleware.go index e58582b..90a2f4a 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -59,10 +59,13 @@ func Handler(next http.Handler) http.Handler { } func Auth(next http.HandlerFunc, w http.ResponseWriter, r *http.Request) { - status, user := session.GetSession(r) + status, user, sessionID := session.GetSession(r) switch status { case session.Authorized: + userSession := session.GetSessionInfo(user.Email, sessionID) + userSession.UpdateAccessTime() + ctx := context.WithValue(r.Context(), "user", user) req := r.WithContext(ctx) r.Context().Value("user") @@ -94,7 +97,7 @@ func Auth(next http.HandlerFunc, w http.ResponseWriter, r *http.Request) { } func Guest(next http.HandlerFunc, w http.ResponseWriter, r *http.Request) { - status, _ := session.GetSession(r) + status, _, _ := session.GetSession(r) switch status { case session.Authorized: diff --git a/public/brand.svg b/public/brand.svg new file mode 100644 index 0000000..0bdcb1c --- /dev/null +++ b/public/brand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/session/session.go b/session/session.go index abc1574..a4a07f4 100644 --- a/session/session.go +++ b/session/session.go @@ -40,10 +40,8 @@ const ( InvalidSession UserStatus = "invalid_session" ) -type SessionInfoList map[string][]*SessionInfo - var GlobalSessionStore = SessionStore{Sessions: make(map[string]*Session)} -var UserSessionInfoList = make(SessionInfoList) +var UserSessionInfoList = make(map[string]map[string]*SessionInfo) type SessionNotFoundError struct{} @@ -95,22 +93,22 @@ func (s *Session) Destroy(w http.ResponseWriter) { } func AddSessionInfo(email string, sessionInfo *SessionInfo) { - UserSessionInfoList[email] = append(UserSessionInfoList[email], sessionInfo) + if _, ok := UserSessionInfoList[email]; !ok { + UserSessionInfoList[email] = make(map[string]*SessionInfo) + } + + UserSessionInfoList[email][sessionInfo.SessionID] = sessionInfo } func RemoveSessionInfo(email string, id string) { - sessionInfos := UserSessionInfoList[email] - var updatedSessionInfos []*SessionInfo - for _, sessionInfo := range sessionInfos { - if sessionInfo.SessionID != id { - updatedSessionInfos = append(updatedSessionInfos, sessionInfo) + if userSessions, ok := UserSessionInfoList[email]; ok { + if _, ok := userSessions[id]; ok { + delete(userSessions, id) + if len(userSessions) == 0 { + delete(UserSessionInfoList, email) + } } } - if len(updatedSessionInfos) > 0 { - UserSessionInfoList[email] = updatedSessionInfos - return - } - delete(UserSessionInfoList, email) } func RemoveAllSessions(email string) { @@ -122,8 +120,8 @@ func RemoveAllSessions(email string) { } func GetSessionInfo(email string, id string) *SessionInfo { - for _, sessionInfo := range UserSessionInfoList[email] { - if sessionInfo.SessionID == id { + if userSession, ok := UserSessionInfoList[email]; ok { + if sessionInfo, ok := userSession[id]; ok { return sessionInfo } } @@ -136,26 +134,37 @@ func (sessionInfo *SessionInfo) UpdateAccessTime() { sessionInfo.AccessAt = formattedTime } -func GetSession(r *http.Request) (UserStatus, types.User) { +func GetSession(r *http.Request) (UserStatus, types.User, string) { cookie, err := r.Cookie("Session") if err != nil { - return Unauthorized, types.User{} + return Unauthorized, types.User{}, "" } storeSession, err := GlobalSessionStore.Get(cookie.Value) if err != nil { if errors.Is(err, &SessionNotFoundError{}) { - return InvalidSession, types.User{} + return InvalidSession, types.User{}, "" } - return Unauthorized, types.User{} + return Unauthorized, types.User{}, "" } val := storeSession.Values["user"] var userSession = types.User{} userSession, ok := val.(types.User) if !ok { - return Unauthorized, types.User{} + return Unauthorized, types.User{}, "" } - return Authorized, userSession + return Authorized, userSession, cookie.Value +} + +func GetSessions(email string) []*SessionInfo { + if sessions, ok := UserSessionInfoList[email]; ok { + result := make([]*SessionInfo, 0, len(sessions)) + for _, sessionInfo := range sessions { + result = append(result, sessionInfo) + } + return result + } + return nil } diff --git a/utils/utils.go b/utils/utils.go index 8b1f3da..9e795ca 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -26,10 +26,6 @@ type Env struct { var env *Env var log *logger.AggregatedLogger -const ( - csrfTokenLength = 32 // Length of the CSRF token in bytes -) - func init() { env = &Env{value: map[string]string{}} } diff --git a/view/auth/auth.templ b/view/auth/auth.templ index 0c203f9..e1626c7 100644 --- a/view/auth/auth.templ +++ b/view/auth/auth.templ @@ -11,8 +11,8 @@ templ form(err types.Message, title string) {
-

Sign Up

-

Enter your email below to login to your account

+

Set Up Your Account

+

Enter your information to create a new account

switch err.Code { case 0:
-
- + +
+
+
+
+
+ + + +
+

Unlimited Storage

+

+ Store as many files as you need with our generous storage limits. +

+
+
+
+ + + + +
+

Secure Encryption

+

+ Your files are encrypted with the latest security protocols to keep them safe. +

+
+
+
+ + + + + +
+

Easy Sharing

+

+ Quickly share files with friends, family, or colleagues with shareable links. +

+
+
+
+
+ + + + } } -templ Main(title string) { - @content(title) +templ Main(title string, user types.User) { + @content(title, user) } \ No newline at end of file diff --git a/view/signup/signup.templ b/view/signup/signup.templ index e3a8878..1a2f53c 100644 --- a/view/signup/signup.templ +++ b/view/signup/signup.templ @@ -12,7 +12,7 @@ templ form(err types.Message, title string) {

Sign Up

-

Enter your email below to login to your account

+

Enter your information to create an account

switch err.Code { case 0:
@@ -241,18 +237,20 @@ templ content(email string, username string, title string, ListSession []*sessio

Pro Plan

50GB of storage for $9.99/month

- +

Enterprise Plan

1TB of storage for $49.99/month

- +