Skip to content

Commit

Permalink
Implement env flag in front-end and consider empty creator as admin (#…
Browse files Browse the repository at this point in the history
…4753)

* Add env var enableUserEndpoints to store model

* Adjust components for enableUserEndpoints

* Small adjustments in the back-end to enableUserEndpoints

* Consider an empty string for the creator as an admin user

Signed-off-by: Thomas Quandt <[email protected]>
  • Loading branch information
thquad committed Jan 28, 2021
1 parent dce832d commit 98c769e
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
} from '../../../shared/components/list/list-types/endpoint/endpoints-list-config.service';
import { ListConfig } from '../../../shared/components/list/list.component.types';
import { SnackBarService } from '../../../shared/services/snackbar.service';
import { SessionService } from '../../../shared/services/session.service';

@Component({
selector: 'app-endpoints-page',
Expand All @@ -45,7 +46,7 @@ import { SnackBarService } from '../../../shared/services/snackbar.service';
}, EndpointListHelper]
})
export class EndpointsPageComponent implements AfterViewInit, OnDestroy, OnInit {
public canRegisterEndpoint = [StratosCurrentUserPermissions.EDIT_ADMIN_ENDPOINT, StratosCurrentUserPermissions.EDIT_ENDPOINT];
public canRegisterEndpoint = [StratosCurrentUserPermissions.EDIT_ADMIN_ENDPOINT];
private healthCheckTimeout: number;

public canBackupRestore$: Observable<boolean>;
Expand All @@ -68,6 +69,7 @@ export class EndpointsPageComponent implements AfterViewInit, OnDestroy, OnInit
private snackBarService: SnackBarService,
cs: CustomizationService,
currentUserPermissionsService: CurrentUserPermissionsService,
public sessionService: SessionService
) {
this.customizations = cs.get();

Expand All @@ -93,6 +95,10 @@ export class EndpointsPageComponent implements AfterViewInit, OnDestroy, OnInit
map(sessionData => sessionData?.plugins.backup),
switchMap(enabled => enabled ? currentUserPermissionsService.can(this.canRegisterEndpoint[0]) : of(false))
);

this.sessionService.userEndpointsEnabled().subscribe(enabled => {
if(enabled) this.canRegisterEndpoint.push(StratosCurrentUserPermissions.EDIT_ENDPOINT);
});
}

subs: Subscription[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</div>
</app-meta-card-value>
</app-meta-card-item>
<app-meta-card-item>
<app-meta-card-item *ngIf="enableUserEndpoints$ | async">
<app-meta-card-key>Created by</app-meta-card-key>
<app-meta-card-value>
<div>{{ row.creator.admin ? "Admin" : "User" }}</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { BaseEndpointsDataSource } from '../base-endpoints-data-source';
import { EndpointListDetailsComponent, EndpointListHelper } from '../endpoint-list.helpers';
import { RouterNav } from './../../../../../../../../store/src/actions/router.actions';
import { CopyToClipboardComponent } from './../../../../copy-to-clipboard/copy-to-clipboard.component';
import { SessionService } from '../../../../../services/session.service';

@Component({
selector: 'app-endpoint-card',
Expand All @@ -54,6 +55,7 @@ export class EndpointCardComponent extends CardCell<EndpointModel> implements On
public cardStatus$: Observable<StratosStatus>;
private subs: Subscription[] = [];
public connectionStatus: string;
public enableUserEndpoints$: Observable<boolean>;

private componentRef: ComponentRef<EndpointListDetailsComponent>;

Expand Down Expand Up @@ -121,6 +123,7 @@ export class EndpointCardComponent extends CardCell<EndpointModel> implements On
private endpointListHelper: EndpointListHelper,
private componentFactoryResolver: ComponentFactoryResolver,
private userFavoriteManager: UserFavoriteManager,
private sessionService: SessionService,
) {
super();
this.endpointIds$ = this.endpointIds.asObservable();
Expand All @@ -130,6 +133,7 @@ export class EndpointCardComponent extends CardCell<EndpointModel> implements On
this.favorite = this.userFavoriteManager.getFavoriteEndpointFromEntity(this.row);
const e = this.endpointCatalogEntity.definition;
this.hasDetails = !!e && !!e.listDetailsComponent;
this.enableUserEndpoints$ = this.sessionService.userEndpointsEnabled();
}

ngOnDestroy(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ConfirmationDialogService } from '../../../confirmation-dialog.service'
import { createMetaCardMenuItemSeparator } from '../../list-cards/meta-card/meta-card-base/meta-card.component';
import { IListAction } from '../../list.component.types';
import { TableCellCustom } from '../../list.types';
import { SessionService } from '../../../../../shared/services/session.service';

interface EndpointDetailsContainerRefs {
componentRef: ComponentRef<EndpointListDetailsComponent>;
Expand Down Expand Up @@ -67,6 +68,7 @@ export class EndpointListHelper {
private currentUserPermissionsService: CurrentUserPermissionsService,
private confirmDialog: ConfirmationDialogService,
private snackBarService: SnackBarService,
private sessionService: SessionService,
) { }

endpointActions(includeSeparators = false): IListAction<EndpointModel>[] {
Expand Down Expand Up @@ -108,10 +110,10 @@ export class EndpointListHelper {
},
label: 'Disconnect',
description: ``, // Description depends on console user permission
createVisible: (row$: Observable<EndpointModel>) => combineLatest(
this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_ENDPOINT),
row$
).pipe(
createVisible: (row$: Observable<EndpointModel>) => combineLatest([
this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_ENDPOINT),
row$
]).pipe(
map(([isAdmin, row]) => {
const isConnected = row.connectionStatus === 'connected';
return isConnected && (!row.system_shared_token || row.system_shared_token && isAdmin);
Expand Down Expand Up @@ -157,21 +159,20 @@ export class EndpointListHelper {
label: 'Unregister',
description: 'Remove the endpoint',
createVisible: (row$: Observable<EndpointModel>) => {
// TODO lock this behind featureflag
return combineLatest([
this.sessionService.userEndpointsEnabled(),
this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_ADMIN_ENDPOINT),
this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_ENDPOINT),
row$
]).pipe(
map(([isAdmin, isEndpointAdmin, row])=>{
if(row.creator.admin){
map(([userEndpointsEnabled, isAdmin, isEndpointAdmin, row])=>{
if(!userEndpointsEnabled || row.creator.admin){
return isAdmin;
}else{
return isEndpointAdmin || isAdmin;
}
})
);
//return this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_ENDPOINT)
}
},
{
Expand All @@ -182,21 +183,20 @@ export class EndpointListHelper {
label: 'Edit endpoint',
description: 'Edit the endpoint',
createVisible: (row$: Observable<EndpointModel>) => {
// TODO lock this behind featureflag
return combineLatest([
this.sessionService.userEndpointsEnabled(),
this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_ADMIN_ENDPOINT),
this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_ENDPOINT),
row$
]).pipe(
map(([isAdmin, isEndpointAdmin, row])=>{
if(row.creator.admin){
map(([userEndpointsEnabled, isAdmin, isEndpointAdmin, row])=>{
if(!userEndpointsEnabled || row.creator.admin){
return isAdmin;
}else{
return isEndpointAdmin || isAdmin;
}
})
);
//return this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_ENDPOINT)
}
},
...customActions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@ export class SessionService {
map(sessionData => sessionData.config.enableTechPreview || false)
);
}

userEndpointsEnabled(): Observable<boolean> {
return this.store.select(selectSessionData()).pipe(
first(),
map(sessionData => sessionData.config.enableUserEndpoints || false)
);
}
}
1 change: 1 addition & 0 deletions src/frontend/packages/store/src/types/auth.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface SessionDataConfig {
APIKeysEnabled?: APIKeysEnabled;
// Default value for Home View - show only favorited endpoints?
homeViewShowFavoritesOnly?: boolean;
enableUserEndpoints?: boolean;
}
export interface SessionData {
endpoints?: SessionEndpoints;
Expand Down
8 changes: 6 additions & 2 deletions src/jetstream/cnsi.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ func (p *portalProxy) DoRegisterEndpoint(cnsiName string, apiEndpoint string, sk
newCNSI.ClientSecret = clientSecret
newCNSI.SSOAllowed = ssoAllowed
newCNSI.SubType = subType
newCNSI.CreatedBy = userId

if p.GetConfig().EnableUserEndpoints == true {
newCNSI.CreatedBy = userId
}

err = p.setCNSIRecord(guid, newCNSI)

Expand Down Expand Up @@ -255,12 +258,13 @@ func (p *portalProxy) ListAdminEndpoints(userID string) ([]*interfaces.CNSIRecor
if err != nil {
return cnsiList, err
}
stratosAdmin := strings.Contains(strings.Join(tokenInfo.Scope, ""), "stratos.admin")
stratosAdmin := strings.Contains(strings.Join(tokenInfo.Scope, ""), p.GetConfig().ConsoleConfig.ConsoleAdminScope)
if stratosAdmin == true {
adminList = append(adminList, tokenInfo.UserGUID)
}
}
adminList = append(adminList, userID)
adminList = append(adminList, "") //legacy endpoints dont have a creator

//get a cnsi list from every admin found and given userID
cnsiRepo, err := p.GetStoreFactory().EndpointStore()
Expand Down
15 changes: 10 additions & 5 deletions src/jetstream/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func (p *portalProxy) getInfo(c echo.Context) (*interfaces.Info, error) {
s.Configuration.ListAllowLoadMaxed = p.Config.UIListAllowLoadMaxed
s.Configuration.APIKeysEnabled = string(p.Config.APIKeysEnabled)
s.Configuration.HomeViewShowFavoritesOnly = p.Config.HomeViewShowFavoritesOnly
s.Configuration.EnableUserEndpoints = p.Config.EnableUserEndpoints

// Only add diagnostics information if the user is an admin
if uaaUser.Admin {
Expand Down Expand Up @@ -99,13 +100,17 @@ func (p *portalProxy) getInfo(c echo.Context) (*interfaces.Info, error) {
endpoint.SystemSharedToken = token.SystemShared
}

// set the creator preemptively as admin, if no id is found
endpoint.Creator = &interfaces.CreatorInfo{
Admin: true,
}

// try to get additional creator information for this cnsi
u, err := p.StratosAuthService.GetUser(cnsi.CreatedBy)
if err == nil {
creator := &interfaces.CreatorInfo{
Admin: u.Admin,
if len(cnsi.CreatedBy) != 0 {
u, err := p.StratosAuthService.GetUser(cnsi.CreatedBy)
if err == nil {
endpoint.Creator.Admin = u.Admin
}
endpoint.Creator = creator
}

cnsiType := cnsi.CNSIType
Expand Down
5 changes: 0 additions & 5 deletions src/jetstream/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,6 @@ func main() {

log.Info("Initialization complete.")

//TODO delete later
enableuserendpoints := portalProxy.GetConfig().EnableUserEndpoints
fmt.Println("User Endpoints enabled?")
fmt.Println(enableuserendpoints)

c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
Expand Down
14 changes: 10 additions & 4 deletions src/jetstream/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,16 +279,22 @@ func (p *portalProxy) endpointMiddleware(h echo.HandlerFunc) echo.HandlerFunc {
return c.NoContent(http.StatusUnauthorized)
}

creator, err := p.StratosAuthService.GetUser(cnsiRecord.CreatedBy)
if err != nil {
return c.NoContent(http.StatusUnauthorized)
// if CreatedBy is not set, then its a legacy admin-endpoint
creator := &interfaces.ConnectedUser{}
creator.Admin = true
if len(cnsiRecord.CreatedBy) != 0 {
creatorRecord, err := p.StratosAuthService.GetUser(cnsiRecord.CreatedBy)
if err != nil {
return c.NoContent(http.StatusUnauthorized)
}
creator = creatorRecord
}

if creator.Admin == true && u.Admin == false {
return handleSessionError(p.Config, c, errors.New("Unauthorized"), false, "You must be Stratos admin to modify this endpoint.")
}

if creator.Admin == false && u.Admin == false && creator.GUID != userID.(string) {
if creator.Admin == false && u.Admin == false && len(creator.GUID) != 0 && creator.GUID != userID.(string) {
return handleSessionError(p.Config, c, errors.New("Unauthorized"), false, "Endpoint-admins are not allowed to modify endpoints created by other endpoint-admins.")
}
}
Expand Down
1 change: 1 addition & 0 deletions src/jetstream/repository/interfaces/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ type Info struct {
ListAllowLoadMaxed bool `json:"listAllowLoadMaxed,omitempty"`
APIKeysEnabled string `json:"APIKeysEnabled"`
HomeViewShowFavoritesOnly bool `json:"homeViewShowFavoritesOnly"`
EnableUserEndpoints bool `json:"enableUserEndpoints"`
} `json:"config"`
}

Expand Down

0 comments on commit 98c769e

Please sign in to comment.