diff --git a/html/src/Components/ShareEditor.tsx b/html/src/Components/ShareEditor.tsx index 9170b33..49794f4 100644 --- a/html/src/Components/ShareEditor.tsx +++ b/html/src/Components/ShareEditor.tsx @@ -60,12 +60,12 @@ export function ShareEditor(props: ShareEditorProps&BoxComponentProps) { } {/* Share exposure */} - + { notifyChange({...options, exposure:v}); }} transitionDuration={0} diff --git a/html/src/i18n/config.ts b/html/src/i18n/config.ts index f400baf..5a2d832 100644 --- a/html/src/i18n/config.ts +++ b/html/src/i18n/config.ts @@ -59,9 +59,9 @@ i18n created: "Created", exposure: "Exposure", - guest_users_can: "Guest users can :", - upload: "Upload", - download: "Download", + you_want_to: "You want to :", + send: "Send", + receive: "Receive", both: "Both", validity: "Validity", @@ -104,9 +104,9 @@ i18n created: "Créé le", exposure: "Type de partage", - guest_users_can: "Les invités peuvent :", - upload: "Envoyer", - download: "Reçevoir", + you_want_to: "Vous souhaitez :", + send: "Envoyer", + receive: "Reçevoir", both: "Les deux", validity: "Expiration", diff --git a/hupload/pkg/apiws/apiws.go b/hupload/pkg/apiws/apiws.go index 0436b71..251199b 100644 --- a/hupload/pkg/apiws/apiws.go +++ b/hupload/pkg/apiws/apiws.go @@ -148,7 +148,15 @@ func (a *APIWS) Start() { if _, ok := a.Authentication.CallbackFunc(nil); ok { // If there is, define action to redirect to "/shares" handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/shares", http.StatusFound) + s, ok := r.Context().Value(authentication.AuthStatusKey).(authentication.AuthStatus) + if ok && s.Authenticated { + http.Redirect(w, r, "/shares", http.StatusFound) + return + } + if r.URL.Query().Get("error") != "" { + http.Error(w, r.URL.Query().Get("error"), http.StatusUnauthorized) + return + } }) m := auth.NewJWTAuthMiddleware(os.Getenv("JWT_SECRET")) f, _ := a.Authentication.CallbackFunc(m.Middleware(handler)) diff --git a/hupload/pkg/apiws/authentication/oidc.go b/hupload/pkg/apiws/authentication/oidc.go index 27e4660..48f3d22 100644 --- a/hupload/pkg/apiws/authentication/oidc.go +++ b/hupload/pkg/apiws/authentication/oidc.go @@ -5,8 +5,8 @@ import ( "crypto/rand" "encoding/base64" "encoding/json" + "errors" "io" - "log/slog" "net/http" "time" @@ -68,7 +68,7 @@ func NewAuthenticationOIDC(o AuthenticationOIDCConfig) (*AuthenticationOIDC, err Endpoint: result.Provider.Endpoint(), // "openid" is a required scope for OpenID Connect flows. - Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, + Scopes: []string{oidc.ScopeOpenID, "email", "profile"}, } return result, nil @@ -107,8 +107,7 @@ func (o *AuthenticationOIDC) CallbackFunc(h http.Handler) (func(w http.ResponseW oauth2Token, err := o.Config.Exchange(r.Context(), r.URL.Query().Get("code")) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - _ = json.NewEncoder(w).Encode(err) + ServeNextError(h, errors.New("code verification failed"), w, r) return } @@ -123,21 +122,18 @@ func (o *AuthenticationOIDC) CallbackFunc(h http.Handler) (func(w http.ResponseW // Parse and verify ID Token payload. idToken, err := verifier.Verify(r.Context(), rawIDToken) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - _ = json.NewEncoder(w).Encode(err) + ServeNextError(h, errors.New("token verification failed"), w, r) return } nonce, err := r.Cookie("nonce") if err != nil { - w.WriteHeader(http.StatusBadRequest) - _ = json.NewEncoder(w).Encode(err) + ServeNextError(h, errors.New("missing nonce"), w, r) //http.Error(w, "nonce not found", http.StatusBadRequest) return } if idToken.Nonce != nonce.Value { - w.WriteHeader(http.StatusBadRequest) - _ = json.NewEncoder(w).Encode(err) + ServeNextError(h, errors.New("nonce doesn't match"), w, r) //http.Error(w, "nonce did not match", http.StatusBadRequest) return } @@ -148,18 +144,21 @@ func (o *AuthenticationOIDC) CallbackFunc(h http.Handler) (func(w http.ResponseW Username string `json:"preferred_username"` } if err := idToken.Claims(&claims); err != nil { - w.WriteHeader(http.StatusInternalServerError) - _ = json.NewEncoder(w).Encode(err) + ServeNextError(h, err, w, r) return } - var rmessage json.RawMessage - if err := idToken.Claims(&rmessage); err == nil { - b, _ := json.MarshalIndent(rmessage, "", " ") - slog.Info("ID Token Claims: %s", slog.String("claims", string(b))) - } + // var rmessage json.RawMessage + // if err := idToken.Claims(&rmessage); err == nil { + // b, _ := json.MarshalIndent(rmessage, "", " ") + // slog.Info("ID Token Claims: %s", slog.String("claims", string(b))) + // } - ServeNextAuthenticated(claims.Username, h, w, r) + if claims.Username != "" { + ServeNextAuthenticated(claims.Username, h, w, r) + return + } + h.ServeHTTP(w, r) }, true } @@ -167,7 +166,10 @@ func ServeNextAuthenticated(user string, next http.Handler, w http.ResponseWrite ctx := context.WithValue(r.Context(), AuthStatusKey, AuthStatus{Authenticated: true, User: user}) next.ServeHTTP(w, r.WithContext(ctx)) } - +func ServeNextError(next http.Handler, err error, w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), AuthStatusKey, AuthStatus{Authenticated: false, User: "", Error: err}) + next.ServeHTTP(w, r.WithContext(ctx)) +} func (o *AuthenticationOIDC) ShowLoginForm() bool { return false } diff --git a/readme_images/properties-dark.png b/readme_images/properties-dark.png index cad3ef9..2062b9a 100644 Binary files a/readme_images/properties-dark.png and b/readme_images/properties-dark.png differ diff --git a/readme_images/properties-light.png b/readme_images/properties-light.png index 81d3a3a..3ef5793 100644 Binary files a/readme_images/properties-light.png and b/readme_images/properties-light.png differ diff --git a/readme_images/properties-preview-dark.png b/readme_images/properties-preview-dark.png index 5393326..e1ec87d 100644 Binary files a/readme_images/properties-preview-dark.png and b/readme_images/properties-preview-dark.png differ diff --git a/readme_images/properties-preview-light.png b/readme_images/properties-preview-light.png index dd80bc7..a596b4f 100644 Binary files a/readme_images/properties-preview-light.png and b/readme_images/properties-preview-light.png differ diff --git a/readme_images/shares-dark.png b/readme_images/shares-dark.png index 049d25f..d0479de 100644 Binary files a/readme_images/shares-dark.png and b/readme_images/shares-dark.png differ diff --git a/readme_images/shares-light.png b/readme_images/shares-light.png index 621cf97..189d93e 100644 Binary files a/readme_images/shares-light.png and b/readme_images/shares-light.png differ diff --git a/robot/Screenshots.robot b/robot/Screenshots.robot index 15467e0..0e33ce8 100644 --- a/robot/Screenshots.robot +++ b/robot/Screenshots.robot @@ -27,9 +27,9 @@ Screenshot Home Page Sleep 0.5 second Click css=\#showEditor Sleep 0.5 second - Take Screenshot ${CURDIR}/../readme_images/properties-${theme}.png crop={'x': 0, 'y': 216, 'width': 800, 'height': 345} + Take Screenshot ${CURDIR}/../readme_images/properties-${theme}.png crop={'x': 0, 'y': 222, 'width': 800, 'height': 346} Click css=\#preview - Take Screenshot ${CURDIR}/../readme_images/properties-preview-${theme}.png crop={'x': 0, 'y': 216, 'width': 800, 'height': 345} + Take Screenshot ${CURDIR}/../readme_images/properties-preview-${theme}.png crop={'x': 0, 'y': 222, 'width': 800, 'height': 346} Click css=\#kuva-yibi-bata \#edit