diff --git a/api/routes.go b/api/routes.go
index 8213b220..a946d0e2 100644
--- a/api/routes.go
+++ b/api/routes.go
@@ -27,6 +27,8 @@ func AddRoutes(r *mux.Router) {
r.Handle("/image/{uuid}", auth.NewEnsureAuth(apiImagePost)).Methods("POST")
r.Handle("/image/{uuid}/content", auth.NewEnsureAuth(apiImageContentGet)).Methods("GET")
r.Handle("/image/{uuid}/content", auth.NewEnsureAuth(apiImageContentPost)).Methods("POST")
+ impersonation := resource.Impersonation(router)
+ r.Handle("/impersonation", authenticatedHandlerJSONPost(impersonation.Create)).Methods("POST")
lead := resource.Lead(r)
r.Handle("/leads", authenticatedHandlerJSON(lead.List)).Methods("GET")
r.Handle("/leads", authenticatedHandlerJSONPost(lead.Create)).Methods("POST")
diff --git a/api/signup.go b/api/signup.go
index e8e7bad6..2208dea4 100644
--- a/api/signup.go
+++ b/api/signup.go
@@ -31,7 +31,7 @@ func postSignup(ctx context.Context, r *http.Request, signup reqSignup) (string,
return "", nhttp.NewError("Failed to signup user", err)
}
- auth.AddUserSession(r, user)
+ auth.AddUserSession(ctx, user)
return "/", nil
}
diff --git a/auth/auth.go b/auth/auth.go
index 9d0a37c3..fa34d815 100644
--- a/auth/auth.go
+++ b/auth/auth.go
@@ -30,16 +30,37 @@ type EnsureAuth struct {
handler AuthenticatedHandler
}
-func AddUserSession(r *http.Request, user *platform.User) {
- id := strconv.Itoa(int(user.ID))
- sessionManager.Put(r.Context(), "user_id", id)
- sessionManager.Put(r.Context(), "username", user.Username)
- log.Debug().Str("id", id).Str("username", user.Username).Msg("added user session")
+func AddUserSession(ctx context.Context, user *platform.User) {
+ id_str := strconv.Itoa(int(user.ID))
+ sessionManager.Put(ctx, "user_id", id_str)
+ sessionManager.Put(ctx, "username", user.Username)
+ log.Debug().Str("id", id_str).Str("username", user.Username).Msg("added user session")
+}
+func ImpersonateUser(ctx context.Context, target_user_id int) {
+ target_user_id_str := strconv.Itoa(int(target_user_id))
+ sessionManager.Put(ctx, "impersonated_user_id", target_user_id_str)
+}
+func ImpersonatedUser(ctx context.Context) *int32 {
+ i_str := sessionManager.GetString(ctx, "impersonated_user_id")
+ if i_str == "" {
+ return nil
+ }
+ i, err := strconv.Atoi(i_str)
+ if err != nil {
+ log.Error().Err(err).Str("impersonated_user_id", i_str).Msg("failed to parse impersonated_user_id")
+ return nil
+ }
+ result := int32(i)
+ return &result
}
func GetAuthenticatedUser(r *http.Request) (*platform.User, error) {
ctx := r.Context()
user_id_str := sessionManager.GetString(ctx, "user_id")
+ impersonated_user_id_str := sessionManager.GetString(ctx, "impersonated_user_id")
+ if impersonated_user_id_str != "" {
+ user_id_str = impersonated_user_id_str
+ }
if user_id_str != "" {
user_id, err := strconv.Atoi(user_id_str)
if err != nil {
@@ -59,7 +80,7 @@ func GetAuthenticatedUser(r *http.Request) (*platform.User, error) {
if err != nil {
return nil, err
}
- AddUserSession(r, user)
+ AddUserSession(ctx, user)
return user, nil
}
@@ -108,7 +129,7 @@ func SigninUser(r *http.Request, username string, password string) (*platform.Us
if user == nil {
return nil, errors.New("No matching user")
}
- AddUserSession(r, user)
+ AddUserSession(r.Context(), user)
return user, nil
}
diff --git a/resource/session.go b/resource/session.go
index 1fb21297..ee978a92 100644
--- a/resource/session.go
+++ b/resource/session.go
@@ -4,6 +4,7 @@ import (
"context"
"net/http"
+ "github.com/Gleipnir-Technology/nidus-sync/auth"
"github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/html"
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
@@ -47,6 +48,7 @@ type sessionURL struct {
type sessionURLAPI struct {
Avatar string `json:"avatar"`
Communication string `json:"communication"`
+ Impersonation string `json:"impersonation"`
PublicreportMessage string `json:"publicreport_message"`
ReviewTask string `json:"review_task"`
Signal string `json:"signal"`
@@ -65,8 +67,17 @@ func (res *sessionR) Get(ctx context.Context, r *http.Request, user platform.Use
if err != nil {
return nil, nhttp.NewError("create user: %w", err)
}
+ var impersonating *string
+ impersonating_id := auth.ImpersonatedUser(ctx)
+ if impersonating_id != nil {
+ i, err := res.router.IDToURI("user.ByIDGet", int(*impersonating_id))
+ if err != nil {
+ return nil, nhttp.NewError("create impersonating uri: %w", err)
+ }
+ impersonating = &i
+ }
return &session{
- Impersonating: nil,
+ Impersonating: impersonating,
NotificationCounts: sessionNotificationCounts{
Communications: counts.Communications,
Home: counts.Home,
@@ -81,6 +92,7 @@ func (res *sessionR) Get(ctx context.Context, r *http.Request, user platform.Use
API: sessionURLAPI{
Avatar: config.MakeURLNidus("/api/avatar"),
Communication: urls.API.Communication,
+ Impersonation: config.MakeURLNidus("/api/impersonation"),
PublicreportMessage: urls.API.Publicreport.Message,
ReviewTask: config.MakeURLNidus("/api/review-task"),
Signal: config.MakeURLNidus("/api/signal"),
diff --git a/resource/user.go b/resource/user.go
index 714e23f3..3e64a9d7 100644
--- a/resource/user.go
+++ b/resource/user.go
@@ -14,7 +14,7 @@ import (
"github.com/aarondl/opt/omitnull"
"github.com/google/uuid"
"github.com/gorilla/mux"
- "github.com/rs/zerolog/log"
+ //"github.com/rs/zerolog/log"
)
type user struct {
@@ -159,9 +159,9 @@ func (res *userR) List(ctx context.Context, r *http.Request, u platform.User, qu
return nil, nhttp.NewError("list users: %w", err)
}
results := make([]*user, len(users))
- log.Debug().Int("len", len(users)).Msg("building response")
+ //log.Debug().Int("len", len(users)).Msg("building response")
for i, v := range users {
- log.Debug().Int("i", i).Msg("making results")
+ //log.Debug().Int("i", i).Msg("making results")
resp, err := res.response(v)
if err != nil {
return nil, nhttp.NewError("create response: %w", err)
diff --git a/scss/sidebar.scss b/scss/sidebar.scss
index 24c9fc48..e69de29b 100644
--- a/scss/sidebar.scss
+++ b/scss/sidebar.scss
@@ -1,140 +0,0 @@
-.logo-container {
- display: flex;
- justify-content: center;
- align-items: center;
- transition: all 0.3s ease;
-}
-
-.logo {
- max-width: 100%;
- height: auto;
- transition: all 0.3s ease;
-}
-
-#sidebar {
- background-color: $off-white;
- min-height: 100vh;
- transition: all 0.3s;
- width: 250px;
- position: fixed;
- z-index: 1000;
- padding: 20px;
-}
-
-#sidebar.collapsed {
- width: 70px;
- padding: 20px 10px;
-}
-/* Logo style when sidebar is collapsed */
-#sidebar.collapsed .logo-container {
- width: 100%;
-}
-
-#sidebar.collapsed .logo-img {
- max-width: 40px; /* smaller size for collapsed state */
-}
-#content {
- transition: all 0.3s;
- margin-left: 250px;
- padding: 10px;
- width: calc(100% - 250px);
-}
-
-#content.expanded {
- margin-left: 70px;
- width: calc(100% - 70px);
-}
-
-.sidebar-header {
- padding-bottom: 20px;
- border-bottom: 1px solid $off-black;
- margin-bottom: 20px;
- overflow: hidden;
- white-space: nowrap;
- display: flex;
- justify-content: center; /* Center for the logo */
-}
-
-.sidebar-menu {
- list-style: none;
- padding: 0;
-}
-
-.sidebar-menu li {
- padding: 10px 0;
-}
-
-.sidebar-menu li a {
- text-decoration: none;
- color: $off-black;
- display: flex;
- align-items: center;
- overflow: hidden;
- white-space: nowrap;
-}
-
-.sidebar-menu li a:hover {
- color: $primary;
-}
-
-.sidebar-menu .menu-icon {
- font-size: 1.2rem;
- min-width: 30px;
- display: flex;
- justify-content: center;
-}
-.sidebar-menu .menu-icon svg {
- width: 1.5em;
- height: 1.5em;
-}
-.sidebar-menu .menu-text {
- transition: opacity 0.3s;
-}
-
-#sidebar.collapsed .menu-text {
- opacity: 0;
- visibility: hidden;
- width: 0;
-}
-
-#sidebar.collapsed .sidebar-header h4 {
- opacity: 0;
- visibility: hidden;
-}
-
-#sidebar.collapsed .sidebar-menu .menu-icon {
- min-width: 100%;
- font-size: 1.5rem;
-}
-
-#sidebarToggle {
- position: absolute;
- left: calc(250px - 15px);
- top: 50%;
- transform: translateY(-50%);
- z-index: 1050;
- width: 30px;
- height: 30px;
- border-radius: 50%;
- border: 1px solid #dee2e6;
- display: flex;
- align-items: center;
- transition: left 0.3s;
- padding: 0;
-}
-#sidebarToggle i {
- transition: transform 0.3s;
-}
-
-#sidebar.collapsed > #sidebarToggle {
- left: calc(70px - 15px);
-}
-
-#sidebar > #sidebarToggle i {
- position: relative;
- left: 5px;
-}
-
-#sidebar.collapsed > #sidebarToggle i {
- transform: rotate(180deg);
-}
diff --git a/ts/App.vue b/ts/App.vue
index cdfb8186..fa877d66 100644
--- a/ts/App.vue
+++ b/ts/App.vue
@@ -12,6 +12,7 @@
diff --git a/ts/components/UserSelector.vue b/ts/components/UserSelector.vue
index 07aa826f..adc8330b 100644
--- a/ts/components/UserSelector.vue
+++ b/ts/components/UserSelector.vue
@@ -49,24 +49,25 @@
diff --git a/ts/types.ts b/ts/types.ts
index a6ef61bb..17bc4406 100644
--- a/ts/types.ts
+++ b/ts/types.ts
@@ -229,6 +229,7 @@ export interface URLs {
interface URLsAPI {
avatar: string;
communication: string;
+ impersonation: string;
publicreport_message: string;
review_task: string;
signal: string;