diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 42589f100..37eec3d3a 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -98,7 +98,7 @@ const insertDevCSPPlugin: Plugin = {
"",
`
- `
+ `
);
},
},
diff --git a/http/alby_http_service.go b/http/alby_http_service.go
index 1c88adebc..8dd24f17a 100644
--- a/http/alby_http_service.go
+++ b/http/alby_http_service.go
@@ -32,6 +32,7 @@ func (albyHttpSvc *AlbyHttpService) RegisterSharedRoutes(readOnlyApiGroup *echo.
e.GET("/api/alby/callback", albyHttpSvc.albyCallbackHandler)
e.GET("/api/alby/info", albyHttpSvc.albyInfoHandler)
e.GET("/api/alby/rates", albyHttpSvc.albyBitcoinRateHandler)
+ e.GET("/api/alby/blog/latest", albyHttpSvc.albyBlogLatestHandler)
readOnlyApiGroup.GET("/alby/me", albyHttpSvc.albyMeHandler)
fullAccessApiGroup.POST("/alby/link-account", albyHttpSvc.albyLinkAccountHandler)
fullAccessApiGroup.POST("/alby/auto-channel", albyHttpSvc.autoChannelHandler)
@@ -96,6 +97,17 @@ func (albyHttpSvc *AlbyHttpService) albyBitcoinRateHandler(c echo.Context) error
return c.JSON(http.StatusOK, rate)
}
+func (albyHttpSvc *AlbyHttpService) albyBlogLatestHandler(c echo.Context) error {
+ post, err := albyHttpSvc.albySvc.GetLatestBlogPost(c.Request().Context())
+ if err != nil {
+ logger.Logger.WithError(err).Error("Failed to get latest blog post")
+ return c.JSON(http.StatusInternalServerError, ErrorResponse{
+ Message: fmt.Sprintf("Failed to get latest blog post: %s", err.Error()),
+ })
+ }
+ return c.JSON(http.StatusOK, post)
+}
+
func (albyHttpSvc *AlbyHttpService) albyCallbackHandler(c echo.Context) error {
code := c.QueryParam("code")
diff --git a/http/http_service.go b/http/http_service.go
index 7d798bd5d..3d292b194 100644
--- a/http/http_service.go
+++ b/http/http_service.go
@@ -66,7 +66,7 @@ func (httpSvc *HttpService) RegisterSharedRoutes(e *echo.Echo) {
e.Use(middleware.SecureWithConfig(middleware.SecureConfig{
ContentTypeNosniff: "nosniff",
XFrameOptions: "DENY",
- ContentSecurityPolicy: "default-src 'self'; img-src 'self' https://uploads.getalby-assets.com https://getalby.com; connect-src 'self' https://api.getalby.com https://getalby.com https://zapplanner.albylabs.com wss://relay.getalby.com wss://relay2.getalby.com; frame-src https://embed.bitrefill.com",
+ ContentSecurityPolicy: "default-src 'self'; img-src 'self' https://uploads.getalby-assets.com https://getalby.com https://framerusercontent.com; connect-src 'self' https://api.getalby.com https://getalby.com https://zapplanner.albylabs.com wss://relay.getalby.com wss://relay2.getalby.com; frame-src https://embed.bitrefill.com",
ReferrerPolicy: "no-referrer",
}))
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
diff --git a/tests/mocks/AlbyService.go b/tests/mocks/AlbyService.go
index d4a127949..94bbca8a9 100644
--- a/tests/mocks/AlbyService.go
+++ b/tests/mocks/AlbyService.go
@@ -162,6 +162,67 @@ func (_c *MockAlbyService_GetChannelPeerSuggestions_Call) RunAndReturn(run func(
return _c
}
+func (_mock *MockAlbyService) GetLatestBlogPost(ctx context.Context) (*alby.BlogPost, error) {
+ ret := _mock.Called(ctx)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetLatestBlogPost")
+ }
+
+ var r0 *alby.BlogPost
+ var r1 error
+ if returnFunc, ok := ret.Get(0).(func(context.Context) (*alby.BlogPost, error)); ok {
+ return returnFunc(ctx)
+ }
+ if returnFunc, ok := ret.Get(0).(func(context.Context) *alby.BlogPost); ok {
+ r0 = returnFunc(ctx)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*alby.BlogPost)
+ }
+ }
+ if returnFunc, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = returnFunc(ctx)
+ } else {
+ r1 = ret.Error(1)
+ }
+ return r0, r1
+}
+
+// MockAlbyService_GetLatestBlogPost_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestBlogPost'
+type MockAlbyService_GetLatestBlogPost_Call struct {
+ *mock.Call
+}
+
+// GetLatestBlogPost is a helper method to define mock.On call
+// - ctx context.Context
+func (_e *MockAlbyService_Expecter) GetLatestBlogPost(ctx interface{}) *MockAlbyService_GetLatestBlogPost_Call {
+ return &MockAlbyService_GetLatestBlogPost_Call{Call: _e.mock.On("GetLatestBlogPost", ctx)}
+}
+
+func (_c *MockAlbyService_GetLatestBlogPost_Call) Run(run func(ctx context.Context)) *MockAlbyService_GetLatestBlogPost_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ var arg0 context.Context
+ if args[0] != nil {
+ arg0 = args[0].(context.Context)
+ }
+ run(
+ arg0,
+ )
+ })
+ return _c
+}
+
+func (_c *MockAlbyService_GetLatestBlogPost_Call) Return(blogPost *alby.BlogPost, err error) *MockAlbyService_GetLatestBlogPost_Call {
+ _c.Call.Return(blogPost, err)
+ return _c
+}
+
+func (_c *MockAlbyService_GetLatestBlogPost_Call) RunAndReturn(run func(ctx context.Context) (*alby.BlogPost, error)) *MockAlbyService_GetLatestBlogPost_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
// GetInfo provides a mock function for the type MockAlbyService
func (_mock *MockAlbyService) GetInfo(ctx context.Context) (*alby.AlbyInfo, error) {
ret := _mock.Called(ctx)
diff --git a/wails/wails_handlers.go b/wails/wails_handlers.go
index f96697de6..8005a5062 100644
--- a/wails/wails_handlers.go
+++ b/wails/wails_handlers.go
@@ -409,6 +409,17 @@ func (app *WailsApp) WailsRequestRouter(route string, method string, body string
return WailsRequestRouterResponse{Body: nil, Error: err.Error()}
}
return WailsRequestRouterResponse{Body: rate, Error: ""}
+ case "/api/alby/blog/latest":
+ post, err := app.svc.GetAlbySvc().GetLatestBlogPost(ctx)
+ if err != nil {
+ logger.Logger.WithFields(logrus.Fields{
+ "route": route,
+ "method": method,
+ "body": body,
+ }).WithError(err).Error("Failed to get latest blog post")
+ return WailsRequestRouterResponse{Body: nil, Error: err.Error()}
+ }
+ return WailsRequestRouterResponse{Body: post, Error: ""}
case "/api/apps":
switch method {
case "POST":