Commit 5f0a7f43 by Alexander Zobnin Committed by GitHub

Users: show badges for each auth provider (#17869)

* Users: show badges for each auth provider

* Chore: don't use functions in angular bindings

* Users: minor style changes to labels

* Chore: convert auth labels on the backed side, deduplicate frontend code

* Users: use authLabels everywhere instead of authModule

* User: fix edit user page style

* Users: minor fixes after review
parent ebff8830
...@@ -30,23 +30,6 @@ func GetTeamMembers(c *m.ReqContext) Response { ...@@ -30,23 +30,6 @@ func GetTeamMembers(c *m.ReqContext) Response {
return JSON(200, query.Result) return JSON(200, query.Result)
} }
func GetAuthProviderLabel(authModule string) string {
switch authModule {
case "oauth_github":
return "GitHub"
case "oauth_google":
return "Google"
case "oauth_gitlab":
return "GitLab"
case "oauth_grafana_com", "oauth_grafananet":
return "grafana.com"
case "ldap", "":
return "LDAP"
default:
return "OAuth"
}
}
// POST /api/teams/:teamId/members // POST /api/teams/:teamId/members
func (hs *HTTPServer) AddTeamMember(c *m.ReqContext, cmd m.AddTeamMemberCommand) Response { func (hs *HTTPServer) AddTeamMember(c *m.ReqContext, cmd m.AddTeamMemberCommand) Response {
cmd.OrgId = c.OrgId cmd.OrgId = c.OrgId
......
...@@ -29,8 +29,11 @@ func getUserUserProfile(userID int64) Response { ...@@ -29,8 +29,11 @@ func getUserUserProfile(userID int64) Response {
} }
getAuthQuery := m.GetAuthInfoQuery{UserId: userID} getAuthQuery := m.GetAuthInfoQuery{UserId: userID}
query.Result.AuthLabels = []string{}
if err := bus.Dispatch(&getAuthQuery); err == nil { if err := bus.Dispatch(&getAuthQuery); err == nil {
query.Result.AuthModule = []string{getAuthQuery.Result.AuthModule} authLabel := GetAuthProviderLabel(getAuthQuery.Result.AuthModule)
query.Result.AuthLabels = append(query.Result.AuthLabels, authLabel)
query.Result.IsExternal = true
} }
return JSON(200, query.Result) return JSON(200, query.Result)
...@@ -277,6 +280,12 @@ func searchUser(c *m.ReqContext) (*m.SearchUsersQuery, error) { ...@@ -277,6 +280,12 @@ func searchUser(c *m.ReqContext) (*m.SearchUsersQuery, error) {
for _, user := range query.Result.Users { for _, user := range query.Result.Users {
user.AvatarUrl = dtos.GetGravatarUrl(user.Email) user.AvatarUrl = dtos.GetGravatarUrl(user.Email)
user.AuthLabels = make([]string, 0)
if user.AuthModule != nil && len(user.AuthModule) > 0 {
for _, authModule := range user.AuthModule {
user.AuthLabels = append(user.AuthLabels, GetAuthProviderLabel(authModule))
}
}
} }
query.Result.Page = page query.Result.Page = page
...@@ -315,3 +324,20 @@ func ClearHelpFlags(c *m.ReqContext) Response { ...@@ -315,3 +324,20 @@ func ClearHelpFlags(c *m.ReqContext) Response {
return JSON(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1}) return JSON(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
} }
func GetAuthProviderLabel(authModule string) string {
switch authModule {
case "oauth_github":
return "GitHub"
case "oauth_google":
return "Google"
case "oauth_gitlab":
return "GitLab"
case "oauth_grafana_com", "oauth_grafananet":
return "grafana.com"
case "ldap", "":
return "LDAP"
default:
return "OAuth"
}
}
...@@ -216,7 +216,8 @@ type UserProfileDTO struct { ...@@ -216,7 +216,8 @@ type UserProfileDTO struct {
OrgId int64 `json:"orgId"` OrgId int64 `json:"orgId"`
IsGrafanaAdmin bool `json:"isGrafanaAdmin"` IsGrafanaAdmin bool `json:"isGrafanaAdmin"`
IsDisabled bool `json:"isDisabled"` IsDisabled bool `json:"isDisabled"`
AuthModule []string `json:"authModule"` IsExternal bool `json:"isExternal"`
AuthLabels []string `json:"authLabels"`
} }
type UserSearchHitDTO struct { type UserSearchHitDTO struct {
...@@ -229,7 +230,8 @@ type UserSearchHitDTO struct { ...@@ -229,7 +230,8 @@ type UserSearchHitDTO struct {
IsDisabled bool `json:"isDisabled"` IsDisabled bool `json:"isDisabled"`
LastSeenAt time.Time `json:"lastSeenAt"` LastSeenAt time.Time `json:"lastSeenAt"`
LastSeenAtAge string `json:"lastSeenAtAge"` LastSeenAtAge string `json:"lastSeenAtAge"`
AuthModule AuthModuleConversion `json:"authModule"` AuthLabels []string `json:"authLabels"`
AuthModule AuthModuleConversion `json:"-"`
} }
type UserIdDTO struct { type UserIdDTO struct {
......
...@@ -179,7 +179,7 @@ export default class AdminEditUserCtrl { ...@@ -179,7 +179,7 @@ export default class AdminEditUserCtrl {
const user = $scope.user; const user = $scope.user;
// External user can not be disabled // External user can not be disabled
if (user.authModule) { if (user.isExternal) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
return; return;
......
import { BackendSrv } from 'app/core/services/backend_srv'; import { BackendSrv } from 'app/core/services/backend_srv';
import { NavModelSrv } from 'app/core/core'; import { NavModelSrv } from 'app/core/core';
import tags from 'app/core/utils/tags';
export default class AdminListUsersCtrl { export default class AdminListUsersCtrl {
users: any; users: any;
...@@ -32,6 +33,8 @@ export default class AdminListUsersCtrl { ...@@ -32,6 +33,8 @@ export default class AdminListUsersCtrl {
for (let i = 1; i < this.totalPages + 1; i++) { for (let i = 1; i < this.totalPages + 1; i++) {
this.pages.push({ page: i, current: i === this.page }); this.pages.push({ page: i, current: i === this.page });
} }
this.addUsersAuthLabels();
}); });
} }
...@@ -40,10 +43,29 @@ export default class AdminListUsersCtrl { ...@@ -40,10 +43,29 @@ export default class AdminListUsersCtrl {
this.getUsers(); this.getUsers();
} }
getAuthModule(user: any) { addUsersAuthLabels() {
if (user.authModule && user.authModule.length) { for (const user of this.users) {
return user.authModule[0]; user.authLabel = getAuthLabel(user);
user.authLabelStyle = getAuthLabelStyle(user.authLabel);
} }
return undefined;
} }
} }
function getAuthLabel(user: any) {
if (user.authLabels && user.authLabels.length) {
return user.authLabels[0];
}
return '';
}
function getAuthLabelStyle(label: string) {
if (label === 'LDAP' || !label) {
return {};
}
const { color, borderColor } = tags.getTagColorsFromName(label);
return {
'background-color': color,
'border-color': borderColor,
};
}
...@@ -118,48 +118,52 @@ ...@@ -118,48 +118,52 @@
<h3 class="page-heading">Sessions</h3> <h3 class="page-heading">Sessions</h3>
<div class="gf-form-group"> <div class="gf-form-group">
<table class="filter-table form-inline"> <div class="gf-form">
<thead> <table class="filter-table form-inline">
<tr> <thead>
<th>Last seen</th> <tr>
<th>Logged on</th> <th>Last seen</th>
<th>IP address</th> <th>Logged on</th>
<th>Browser &amp; OS</th> <th>IP address</th>
<th></th> <th>Browser &amp; OS</th>
</tr> <th></th>
</thead> </tr>
<tbody> </thead>
<tr ng-repeat="session in sessions"> <tbody>
<td ng-if="session.isActive">Now</td> <tr ng-repeat="session in sessions">
<td ng-if="!session.isActive">{{session.seenAt}}</td> <td ng-if="session.isActive">Now</td>
<td>{{session.createdAt}}</td> <td ng-if="!session.isActive">{{session.seenAt}}</td>
<td>{{session.clientIp}}</td> <td>{{session.createdAt}}</td>
<td>{{session.browser}} on {{session.os}} {{session.osVersion}}</td> <td>{{session.clientIp}}</td>
<td> <td>{{session.browser}} on {{session.os}} {{session.osVersion}}</td>
<button class="btn btn-danger btn-small" ng-click="revokeUserSession(session.id)"> <td>
<i class="fa fa-power-off"></i> <button class="btn btn-danger btn-small" ng-click="revokeUserSession(session.id)">
</button> <i class="fa fa-power-off"></i>
</td> </button>
</tr> </td>
</tbody> </tr>
</table> </tbody>
</table>
</div>
<div class="gf-form-button-row">
<button ng-if="sessions.length" class="btn btn-danger" ng-click="revokeAllUserSessions()">
Logout user from all devices
</button>
</div>
</div> </div>
<button ng-if="sessions.length" class="btn btn-danger" ng-click="revokeAllUserSessions()">
Logout user from all devices
</button>
<div class="gf-form-group"> <h3 class="page-heading">User status</h3>
<h3 class="page-heading">User status</h3>
<div class="gf-form-group">
<div class="gf-form-button-row"> <div class="gf-form-button-row">
<button <button
type="submit" type="submit"
class="btn btn-danger" class="btn btn-danger"
ng-if="!user.isDisabled" ng-if="!user.isDisabled"
ng-click="disableUser($event)" ng-click="disableUser($event)"
bs-tooltip="user.authModule ? 'External user cannot be activated or deactivated' : ''" bs-tooltip="user.isExternal ? 'External user cannot be enabled or disabled' : ''"
ng-class="{'disabled': user.authModule}" ng-class="{'disabled': user.isExternal}"
> >
Disable Disable
</button> </button>
...@@ -168,8 +172,8 @@ ...@@ -168,8 +172,8 @@
class="btn btn-primary" class="btn btn-primary"
ng-if="user.isDisabled" ng-if="user.isDisabled"
ng-click="disableUser($event)" ng-click="disableUser($event)"
bs-tooltip="user.authModule ? 'External user cannot be activated or deactivated' : ''" bs-tooltip="user.isExternal ? 'External user cannot be enabled or disabled' : ''"
ng-class="{'disabled': user.authModule}" ng-class="{'disabled': user.isExternal}"
> >
Enable Enable
</button> </button>
......
...@@ -55,7 +55,9 @@ ...@@ -55,7 +55,9 @@
</a> </a>
</td> </td>
<td class="text-right"> <td class="text-right">
<span class="label label-tag" ng-class="{'muted': user.isDisabled}" ng-if="ctrl.getAuthModule(user) === 'ldap'">LDAP</span> <span class="label label-tag" ng-style="user.authLabelStyle" ng-if="user.authLabel">
{{user.authLabel}}
</span>
</td> </td>
<td class="text-right"> <td class="text-right">
<span class="label label-tag label-tag--gray" ng-if="user.isDisabled">Disabled</span> <span class="label label-tag label-tag--gray" ng-if="user.isDisabled">Disabled</span>
......
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