Commit 992b4b8a by Leonard Gram Committed by GitHub

Licensing service (#19903)

* Licensing: supplies a service to handle licensing information

* Licensing: uses the license service further

Uses the license service instead of settings.isEnterprise:
- external team members
- saml
- usage stats

* Licensing: fixes broken tests due to new Licensing service dependency

* Licensing: fixes linting errors

* Licensing: exposes license expiry information to the frontend
parent 0ecc9a57
...@@ -154,7 +154,7 @@ func (hs *HTTPServer) registerRoutes() { ...@@ -154,7 +154,7 @@ func (hs *HTTPServer) registerRoutes() {
teamsRoute.Post("/", bind(models.CreateTeamCommand{}), Wrap(hs.CreateTeam)) teamsRoute.Post("/", bind(models.CreateTeamCommand{}), Wrap(hs.CreateTeam))
teamsRoute.Put("/:teamId", bind(models.UpdateTeamCommand{}), Wrap(hs.UpdateTeam)) teamsRoute.Put("/:teamId", bind(models.UpdateTeamCommand{}), Wrap(hs.UpdateTeam))
teamsRoute.Delete("/:teamId", Wrap(hs.DeleteTeamByID)) teamsRoute.Delete("/:teamId", Wrap(hs.DeleteTeamByID))
teamsRoute.Get("/:teamId/members", Wrap(GetTeamMembers)) teamsRoute.Get("/:teamId/members", Wrap(hs.GetTeamMembers))
teamsRoute.Post("/:teamId/members", bind(models.AddTeamMemberCommand{}), Wrap(hs.AddTeamMember)) teamsRoute.Post("/:teamId/members", bind(models.AddTeamMemberCommand{}), Wrap(hs.AddTeamMember))
teamsRoute.Put("/:teamId/members/:userId", bind(models.UpdateTeamMemberCommand{}), Wrap(hs.UpdateTeamMember)) teamsRoute.Put("/:teamId/members/:userId", bind(models.UpdateTeamMemberCommand{}), Wrap(hs.UpdateTeamMember))
teamsRoute.Delete("/:teamId/members/:userId", Wrap(hs.RemoveTeamMember)) teamsRoute.Delete("/:teamId/members/:userId", Wrap(hs.RemoveTeamMember))
......
...@@ -196,7 +196,11 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf ...@@ -196,7 +196,11 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf
"latestVersion": plugins.GrafanaLatestVersion, "latestVersion": plugins.GrafanaLatestVersion,
"hasUpdate": plugins.GrafanaHasUpdate, "hasUpdate": plugins.GrafanaHasUpdate,
"env": setting.Env, "env": setting.Env,
"isEnterprise": setting.IsEnterprise, "isEnterprise": hs.License.HasValidLicense(),
},
"licenseInfo": map[string]interface{}{
"hasLicense": hs.License.HasLicense(),
"expiry": hs.License.Expiry(),
}, },
"featureToggles": hs.Cfg.FeatureToggles, "featureToggles": hs.Cfg.FeatureToggles,
} }
......
...@@ -69,6 +69,7 @@ type HTTPServer struct { ...@@ -69,6 +69,7 @@ type HTTPServer struct {
RemoteCacheService *remotecache.RemoteCache `inject:""` RemoteCacheService *remotecache.RemoteCache `inject:""`
ProvisioningService ProvisioningService `inject:""` ProvisioningService ProvisioningService `inject:""`
Login *login.LoginService `inject:""` Login *login.LoginService `inject:""`
License models.Licensing `inject:""`
} }
func (hs *HTTPServer) Init() error { func (hs *HTTPServer) Init() error {
......
...@@ -83,7 +83,7 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er ...@@ -83,7 +83,7 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er
NewGrafanaVersion: plugins.GrafanaLatestVersion, NewGrafanaVersion: plugins.GrafanaLatestVersion,
NewGrafanaVersionExists: plugins.GrafanaHasUpdate, NewGrafanaVersionExists: plugins.GrafanaHasUpdate,
AppName: setting.ApplicationName, AppName: setting.ApplicationName,
AppNameBodyClass: getAppNameBodyClass(setting.ApplicationName), AppNameBodyClass: getAppNameBodyClass(hs.License.HasValidLicense()),
} }
if setting.DisableGravatar { if setting.DisableGravatar {
...@@ -372,13 +372,10 @@ func (hs *HTTPServer) NotFoundHandler(c *m.ReqContext) { ...@@ -372,13 +372,10 @@ func (hs *HTTPServer) NotFoundHandler(c *m.ReqContext) {
c.HTML(404, "index", data) c.HTML(404, "index", data)
} }
func getAppNameBodyClass(name string) string { func getAppNameBodyClass(validLicense bool) string {
switch name { if validLicense {
case setting.APP_NAME:
return "app-grafana"
case setting.APP_NAME_ENTERPRISE:
return "app-enterprise" return "app-enterprise"
default:
return ""
} }
return "app-grafana"
} }
...@@ -40,7 +40,7 @@ func (hs *HTTPServer) LoginView(c *models.ReqContext) { ...@@ -40,7 +40,7 @@ func (hs *HTTPServer) LoginView(c *models.ReqContext) {
} }
viewData.Settings["oauth"] = enabledOAuths viewData.Settings["oauth"] = enabledOAuths
viewData.Settings["samlEnabled"] = setting.IsEnterprise && hs.Cfg.SAMLEnabled viewData.Settings["samlEnabled"] = hs.License.HasValidLicense() && hs.Cfg.SAMLEnabled
if loginError, ok := tryGetEncryptedCookie(c, LoginErrorCookieName); ok { if loginError, ok := tryGetEncryptedCookie(c, LoginErrorCookieName); ok {
//this cookie is only set whenever an OAuth login fails //this cookie is only set whenever an OAuth login fails
......
...@@ -61,6 +61,7 @@ func TestLoginErrorCookieApiEndpoint(t *testing.T) { ...@@ -61,6 +61,7 @@ func TestLoginErrorCookieApiEndpoint(t *testing.T) {
sc := setupScenarioContext("/login") sc := setupScenarioContext("/login")
hs := &HTTPServer{ hs := &HTTPServer{
Cfg: setting.NewCfg(), Cfg: setting.NewCfg(),
License: models.OSSLicensingService{},
} }
sc.defaultHandler = Wrap(func(w http.ResponseWriter, c *models.ReqContext) { sc.defaultHandler = Wrap(func(w http.ResponseWriter, c *models.ReqContext) {
...@@ -110,6 +111,7 @@ func TestLoginOAuthRedirect(t *testing.T) { ...@@ -110,6 +111,7 @@ func TestLoginOAuthRedirect(t *testing.T) {
sc := setupScenarioContext("/login") sc := setupScenarioContext("/login")
hs := &HTTPServer{ hs := &HTTPServer{
Cfg: setting.NewCfg(), Cfg: setting.NewCfg(),
License: models.OSSLicensingService{},
} }
sc.defaultHandler = Wrap(func(c *models.ReqContext) { sc.defaultHandler = Wrap(func(c *models.ReqContext) {
......
...@@ -5,12 +5,11 @@ import ( ...@@ -5,12 +5,11 @@ import (
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models" m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/teamguardian" "github.com/grafana/grafana/pkg/services/teamguardian"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
) )
// GET /api/teams/:teamId/members // GET /api/teams/:teamId/members
func GetTeamMembers(c *m.ReqContext) Response { func (hs *HTTPServer) GetTeamMembers(c *m.ReqContext) Response {
query := m.GetTeamMembersQuery{OrgId: c.OrgId, TeamId: c.ParamsInt64(":teamId")} query := m.GetTeamMembersQuery{OrgId: c.OrgId, TeamId: c.ParamsInt64(":teamId")}
if err := bus.Dispatch(&query); err != nil { if err := bus.Dispatch(&query); err != nil {
...@@ -21,7 +20,7 @@ func GetTeamMembers(c *m.ReqContext) Response { ...@@ -21,7 +20,7 @@ func GetTeamMembers(c *m.ReqContext) Response {
member.AvatarUrl = dtos.GetGravatarUrl(member.Email) member.AvatarUrl = dtos.GetGravatarUrl(member.Email)
member.Labels = []string{} member.Labels = []string{}
if setting.IsEnterprise && member.External { if hs.License.HasValidLicense() && member.External {
authProvider := GetAuthProviderLabel(member.AuthModule) authProvider := GetAuthProviderLabel(member.AuthModule)
member.Labels = append(member.Labels, authProvider) member.Labels = append(member.Labels, authProvider)
} }
......
...@@ -6,6 +6,8 @@ import ( ...@@ -6,6 +6,8 @@ import (
_ "github.com/crewjam/saml" _ "github.com/crewjam/saml"
_ "github.com/gobwas/glob" _ "github.com/gobwas/glob"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/registry"
_ "github.com/jung-kurt/gofpdf" _ "github.com/jung-kurt/gofpdf"
_ "github.com/robfig/cron" _ "github.com/robfig/cron"
_ "github.com/robfig/cron/v3" _ "github.com/robfig/cron/v3"
...@@ -13,4 +15,8 @@ import ( ...@@ -13,4 +15,8 @@ import (
_ "gopkg.in/square/go-jose.v2" _ "gopkg.in/square/go-jose.v2"
) )
func init() {
registry.RegisterService(&models.OSSLicensingService{})
}
var IsEnterprise bool = false var IsEnterprise bool = false
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/login/social" "github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
...@@ -23,6 +24,7 @@ type UsageStatsService struct { ...@@ -23,6 +24,7 @@ type UsageStatsService struct {
Cfg *setting.Cfg `inject:""` Cfg *setting.Cfg `inject:""`
Bus bus.Bus `inject:""` Bus bus.Bus `inject:""`
SQLStore *sqlstore.SqlStore `inject:""` SQLStore *sqlstore.SqlStore `inject:""`
License models.Licensing `inject:""`
oauthProviders map[string]bool oauthProviders map[string]bool
} }
......
...@@ -32,7 +32,7 @@ func (uss *UsageStatsService) sendUsageStats(oauthProviders map[string]bool) { ...@@ -32,7 +32,7 @@ func (uss *UsageStatsService) sendUsageStats(oauthProviders map[string]bool) {
"metrics": metrics, "metrics": metrics,
"os": runtime.GOOS, "os": runtime.GOOS,
"arch": runtime.GOARCH, "arch": runtime.GOARCH,
"edition": getEdition(), "edition": getEdition(uss.License.HasValidLicense()),
"packaging": setting.Packaging, "packaging": setting.Packaging,
} }
...@@ -182,8 +182,8 @@ func (uss *UsageStatsService) updateTotalStats() { ...@@ -182,8 +182,8 @@ func (uss *UsageStatsService) updateTotalStats() {
metrics.StatsTotalActiveAdmins.Set(float64(statsQuery.Result.ActiveAdmins)) metrics.StatsTotalActiveAdmins.Set(float64(statsQuery.Result.ActiveAdmins))
} }
func getEdition() string { func getEdition(validLicense bool) string {
if setting.IsEnterprise { if validLicense {
return "enterprise" return "enterprise"
} }
return "oss" return "oss"
......
...@@ -25,6 +25,7 @@ func TestMetrics(t *testing.T) { ...@@ -25,6 +25,7 @@ func TestMetrics(t *testing.T) {
uss := &UsageStatsService{ uss := &UsageStatsService{
Bus: bus.New(), Bus: bus.New(),
SQLStore: sqlstore.InitTestDB(t), SQLStore: sqlstore.InitTestDB(t),
License: models.OSSLicensingService{},
} }
var getSystemStatsQuery *models.GetSystemStatsQuery var getSystemStatsQuery *models.GetSystemStatsQuery
......
package models
type Licensing interface {
// HasValidLicense is true if a valid license exists
HasValidLicense() bool
// HasLicense is true if there is a license provided
HasLicense() bool
// Expiry returns the unix epoch timestamp when the license expires, or 0 if no valid license is provided
Expiry() int64
}
type OSSLicensingService struct{}
func (OSSLicensingService) HasLicense() bool {
return false
}
func (OSSLicensingService) Expiry() int64 {
return 0
}
func (OSSLicensingService) Init() error {
return nil
}
func (OSSLicensingService) HasValidLicense() bool {
return false
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment