diff --git a/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-cf-step-1/create-endpoint-cf-step-1.component.html b/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-cf-step-1/create-endpoint-cf-step-1.component.html index 07c3a7c620..53bff3bfbb 100644 --- a/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-cf-step-1/create-endpoint-cf-step-1.component.html +++ b/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-cf-step-1/create-endpoint-cf-step-1.component.html @@ -2,14 +2,14 @@

{{endpoint.definition.label}} Information

+ [appUnique]="registerForm.value.createUserEndpointField ? (existingPersonalEndpoints | async)?.names : (customEndpoints | async)?.names"> Name is required Name is not unique + [appUnique]="registerForm.value.createUserEndpointField ? (existingPersonalEndpoints | async)?.urls : (customEndpoints | async)?.urls"> URL is required Invalid API URL URL is not unique diff --git a/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-helper.ts b/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-helper.ts index d198b839c6..789a60e721 100644 --- a/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-helper.ts +++ b/src/frontend/packages/core/src/features/endpoints/create-endpoint/create-endpoint-helper.ts @@ -16,25 +16,28 @@ export class CreateEndpointHelperComponent { userEndpointsAndIsAdmin: Observable; 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)), @@ -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; diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/base-endpoints-data-source.ts b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/base-endpoints-data-source.ts index bd1a2a8b00..cb329f65d0 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/base-endpoints-data-source.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/endpoint/base-endpoints-data-source.ts @@ -125,7 +125,8 @@ export class BaseEndpointsDataSource extends ListDataSource { sso_allowed: false, creator: { name: '', - admin: false + admin: false, + system: false } }), paginationKey: action.paginationKey, diff --git a/src/frontend/packages/git/src/shared/components/git-registration/git-registration.component.html b/src/frontend/packages/git/src/shared/components/git-registration/git-registration.component.html index 21572423a8..67198988be 100644 --- a/src/frontend/packages/git/src/shared/components/git-registration/git-registration.component.html +++ b/src/frontend/packages/git/src/shared/components/git-registration/git-registration.component.html @@ -19,14 +19,14 @@

Select the type of {{gitTypes[epSubType].label}} to register

+ [appUnique]="registerForm.value.createUserEndpointField ? (existingPersonalEndpoints | async)?.names : (customEndpoints | async)?.names"> Name is required Name is not unique + [appUnique]="registerForm.value.createUserEndpointField ? (existingPersonalEndpoints | async)?.urls : (customEndpoints | async)?.urls"> URL is required Invalid API URL URL is not unique diff --git a/src/frontend/packages/store/src/types/endpoint.types.ts b/src/frontend/packages/store/src/types/endpoint.types.ts index 68a77ed2a3..feb3c51906 100644 --- a/src/frontend/packages/store/src/types/endpoint.types.ts +++ b/src/frontend/packages/store/src/types/endpoint.types.ts @@ -68,6 +68,7 @@ export interface EndpointUser { export interface CreatorInfo { name: string; admin: boolean; + system: boolean; } export interface EndpointState { diff --git a/src/jetstream/cnsi.go b/src/jetstream/cnsi.go index ac6159ca67..de595ab422 100644 --- a/src/jetstream/cnsi.go +++ b/src/jetstream/cnsi.go @@ -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", @@ -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, @@ -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 { @@ -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 } diff --git a/src/jetstream/info.go b/src/jetstream/info.go index ea4a57b719..e449f2b67f 100644 --- a/src/jetstream/info.go +++ b/src/jetstream/info.go @@ -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 } } diff --git a/src/jetstream/repository/interfaces/structs.go b/src/jetstream/repository/interfaces/structs.go index fccdc53ebc..66d38e25f1 100644 --- a/src/jetstream/repository/interfaces/structs.go +++ b/src/jetstream/repository/interfaces/structs.go @@ -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 {