Skip to content

Commit

Permalink
Admins can create personal endpoints (#4876)
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Quandt <[email protected]>
  • Loading branch information
thquad authored and richard-cox committed Apr 16, 2021
1 parent 18add26 commit 1cad542
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<h1 class="create-endpoint__section-title">{{endpoint.definition.label}} Information</h1>
<mat-form-field>
<input matInput id="name" name="name" formControlName="nameField" placeholder="Name"
[appUnique]="(customEndpoints | async)?.names">
[appUnique]="registerForm.value.createUserEndpointField ? (existingPersonalEndpoints | async)?.names : (customEndpoints | async)?.names">
<mat-error *ngIf="registerForm.controls.nameField.errors?.required">Name is required</mat-error>
<mat-error *ngIf="registerForm.controls.nameField.errors?.appUnique">Name is not unique</mat-error>
</mat-form-field>
<mat-form-field novalidate>
<input matInput id="url" name="url" formControlName="urlField" type="url" required placeholder="Endpoint Address"
pattern="{{urlValidation}}"
[appUnique]="(customEndpoints | async)?.urls">
[appUnique]="registerForm.value.createUserEndpointField ? (existingPersonalEndpoints | async)?.urls : (customEndpoints | async)?.urls">
<mat-error *ngIf="registerForm.controls.urlField.errors?.required">URL is required</mat-error>
<mat-error *ngIf="registerForm.controls.urlField.errors?.pattern">Invalid API URL</mat-error>
<mat-error *ngIf="registerForm.controls.urlField.errors?.appUnique">URL is not unique</mat-error>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,28 @@ export class CreateEndpointHelperComponent {

userEndpointsAndIsAdmin: Observable<boolean>;
customEndpoints: EndpointObservable;
existingSystemEndpoints: EndpointObservable;
existingPersonalEndpoints: EndpointObservable;
existingEndpoints: EndpointObservable;

constructor(
public sessionService: SessionService,
public currentUserPermissionsService: CurrentUserPermissionsService
) {
const currentPage$ = stratosEntityCatalog.endpoint.store.getAll.getPaginationMonitor().currentPage$;
const existingAdminEndpoints = currentPage$.pipe(
this.existingSystemEndpoints = currentPage$.pipe(
map(endpoints => ({
names: endpoints.filter(ep => ep.creator.admin).map(ep => ep.name),
urls: endpoints.filter(ep => ep.creator.admin).map(ep => getFullEndpointApiUrl(ep)),
names: endpoints.filter(ep => ep.creator.system).map(ep => ep.name),
urls: endpoints.filter(ep => ep.creator.system).map(ep => getFullEndpointApiUrl(ep)),
}))
);
const existingUserEndpoints = currentPage$.pipe(
this.existingPersonalEndpoints = currentPage$.pipe(
map(endpoints => ({
names: endpoints.filter(ep => !ep.creator.admin).map(ep => ep.name),
urls: endpoints.filter(ep => !ep.creator.admin).map(ep => getFullEndpointApiUrl(ep)),
names: endpoints.filter(ep => !ep.creator.system).map(ep => ep.name),
urls: endpoints.filter(ep => !ep.creator.system).map(ep => getFullEndpointApiUrl(ep)),
}))
);
const existingEndpoints = currentPage$.pipe(
this.existingEndpoints = currentPage$.pipe(
map(endpoints => ({
names: endpoints.map(ep => ep.name),
urls: endpoints.map(ep => getFullEndpointApiUrl(ep)),
Expand All @@ -54,16 +57,16 @@ export class CreateEndpointHelperComponent {
this.customEndpoints = combineLatest([
userEndpointsNotDisabled,
isAdmin,
existingEndpoints,
existingAdminEndpoints,
existingUserEndpoints
this.existingEndpoints,
this.existingSystemEndpoints,
this.existingPersonalEndpoints
]).pipe(
map(([userEndpointsEnabled, admin, endpoints, adminEndpoints, userEndpoints]) => {
map(([userEndpointsEnabled, admin, endpoints, systemEndpoints, personalEndpoints]) => {
if (userEndpointsEnabled){
if (admin){
return adminEndpoints;
return systemEndpoints;
}else{
return userEndpoints;
return personalEndpoints;
}
}
return endpoints;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ export class BaseEndpointsDataSource extends ListDataSource<EndpointModel> {
sso_allowed: false,
creator: {
name: '',
admin: false
admin: false,
system: false
}
}),
paginationKey: action.paginationKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ <h3>Select the type of {{gitTypes[epSubType].label}} to register</h3>
<div *ngIf="showEndpointFields" class="select-step__endpoint-form">
<mat-form-field>
<input matInput id="name" name="name" formControlName="nameField" placeholder="Name"
[appUnique]="(customEndpoints | async)?.names">
[appUnique]="registerForm.value.createUserEndpointField ? (existingPersonalEndpoints | async)?.names : (customEndpoints | async)?.names">
<mat-error *ngIf="registerForm.controls.nameField.errors?.required">Name is required</mat-error>
<mat-error *ngIf="registerForm.controls.nameField.errors?.appUnique">Name is not unique</mat-error>
</mat-form-field>
<mat-form-field novalidate>
<input matInput id="url" name="url" formControlName="urlField" type="url" required
placeholder="Endpoint Address" pattern="{{urlValidation}}"
[appUnique]="(customEndpoints | async)?.urls">
[appUnique]="registerForm.value.createUserEndpointField ? (existingPersonalEndpoints | async)?.urls : (customEndpoints | async)?.urls">
<mat-error *ngIf="registerForm.controls.urlField.errors?.required">URL is required</mat-error>
<mat-error *ngIf="registerForm.controls.urlField.errors?.pattern">Invalid API URL</mat-error>
<mat-error *ngIf="registerForm.controls.urlField.errors?.appUnique">URL is not unique</mat-error>
Expand Down
1 change: 1 addition & 0 deletions src/frontend/packages/store/src/types/endpoint.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export interface EndpointUser {
export interface CreatorInfo {
name: string;
admin: boolean;
system: boolean;
}

export interface EndpointState {
Expand Down
24 changes: 3 additions & 21 deletions src/jetstream/cnsi.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func (p *portalProxy) DoRegisterEndpoint(cnsiName string, apiEndpoint string, sk
// check if we've already got this APIEndpoint in this DB
for _, duplicate := range duplicateEndpoints {
// cant create same system endpoint
if len(duplicate.Creator) == 0 && isAdmin {
if len(duplicate.Creator) == 0 && isAdmin && !createUserEndpoint {
return interfaces.CNSIRecord{}, interfaces.NewHTTPShadowError(
http.StatusBadRequest,
"Can not register same system endpoint multiple times",
Expand All @@ -159,7 +159,6 @@ func (p *portalProxy) DoRegisterEndpoint(cnsiName string, apiEndpoint string, sk
}

// cant create same user endpoint
// can create same user endpoint if overwriteEndpoint true
if duplicate.Creator == userId {
return interfaces.CNSIRecord{}, interfaces.NewHTTPShadowError(
http.StatusBadRequest,
Expand All @@ -168,28 +167,11 @@ func (p *portalProxy) DoRegisterEndpoint(cnsiName string, apiEndpoint string, sk
)
}
}

/*
if isAdmin && overwriteEndpoints {
for _, duplicate := range duplicateEndpoints {
log.Infof("An administrator is registering an endpoint with the same API URL ('%+v') as an endpoint administrator's. The existing duplicate endpoint ('%+v') will be removed", apiEndpoint, duplicate.GUID)
err := p.doUnregisterCluster(duplicate.GUID)
if err != nil {
return interfaces.CNSIRecord{}, interfaces.NewHTTPShadowError(
http.StatusInternalServerError,
"Failed to unregister cluster",
"Failed to unregister cluster: %v",
err)
}
}
}
*/

}

h := sha1.New()
// see why its generated this way in Issue #4753 / #3031
if p.GetConfig().UserEndpointsEnabled != config.UserEndpointsConfigEnum.Disabled && !isAdmin {
if p.GetConfig().UserEndpointsEnabled != config.UserEndpointsConfigEnum.Disabled && (!isAdmin || createUserEndpoint) {
// Make the new guid unique per api url AND user id
h.Write([]byte(apiEndpointURL.String() + userId))
} else {
Expand Down Expand Up @@ -222,7 +204,7 @@ func (p *portalProxy) DoRegisterEndpoint(cnsiName string, apiEndpoint string, sk
newCNSI.SubType = subType

// admins currently can't create user endpoints
if p.GetConfig().UserEndpointsEnabled != config.UserEndpointsConfigEnum.Disabled && !isAdmin {
if p.GetConfig().UserEndpointsEnabled != config.UserEndpointsConfigEnum.Disabled && (!isAdmin || createUserEndpoint) {
newCNSI.Creator = userId
}

Expand Down
10 changes: 7 additions & 3 deletions src/jetstream/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,22 @@ func (p *portalProxy) getInfo(c echo.Context) (*interfaces.Info, error) {

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

// assume it's a user when len != 0
if len(cnsi.Creator) != 0 {
endpoint.Creator.Admin = false
endpoint.Creator.System = false
u, err := p.StratosAuthService.GetUser(cnsi.Creator)
// add an anonymous user if no user is found
if err != nil {
endpoint.Creator.Name = "user"
endpoint.Creator.Admin = false
} else {
endpoint.Creator.Name = u.Name
endpoint.Creator.Admin = u.Admin
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/jetstream/repository/interfaces/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,9 @@ type ConnectedUser struct {

// CreatorInfo - additional information about the user who created an endpoint
type CreatorInfo struct {
Name string `json:"name"`
Admin bool `json:"admin"`
Name string `json:"name"`
Admin bool `json:"admin"`
System bool `json:"system"`
}

type JWTUserTokenInfo struct {
Expand Down

0 comments on commit 1cad542

Please sign in to comment.