mirror of
https://github.com/Infisical/infisical.git
synced 2025-07-15 09:42:14 +00:00
Compare commits
4 Commits
project-gr
...
daniel/gat
Author | SHA1 | Date | |
---|---|---|---|
4c8bf9bd92 | |||
a6554deb80 | |||
4bd1eb6f70 | |||
022ecf75e1 |
@ -42,10 +42,6 @@ export type TListGroupUsersDTO = {
|
||||
filter?: EFilterReturnedUsers;
|
||||
} & TGenericPermission;
|
||||
|
||||
export type TListProjectGroupUsersDTO = TListGroupUsersDTO & {
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export type TAddUserToGroupDTO = {
|
||||
id: string;
|
||||
username: string;
|
||||
|
@ -89,7 +89,6 @@ export const GROUPS = {
|
||||
limit: "The number of users to return.",
|
||||
username: "The username to search for.",
|
||||
search: "The text string that user email or name will be filtered by.",
|
||||
projectId: "The ID of the project the group belongs to.",
|
||||
filterUsers:
|
||||
"Whether to filter the list of returned users. 'existingMembers' will only return existing users in the group, 'nonMembers' will only return users not in the group, undefined will return all users in the organization."
|
||||
},
|
||||
|
@ -4,11 +4,9 @@ import {
|
||||
GroupProjectMembershipsSchema,
|
||||
GroupsSchema,
|
||||
ProjectMembershipRole,
|
||||
ProjectUserMembershipRolesSchema,
|
||||
UsersSchema
|
||||
ProjectUserMembershipRolesSchema
|
||||
} from "@app/db/schemas";
|
||||
import { EFilterReturnedUsers } from "@app/ee/services/group/group-types";
|
||||
import { ApiDocsTags, GROUPS, PROJECTS } from "@app/lib/api-docs";
|
||||
import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
|
||||
import { ms } from "@app/lib/ms";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@ -303,61 +301,4 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
|
||||
return { groupMembership };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:projectId/groups/:groupId/users",
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.ProjectGroups],
|
||||
description: "Return project group users",
|
||||
params: z.object({
|
||||
projectId: z.string().trim().describe(GROUPS.LIST_USERS.projectId),
|
||||
groupId: z.string().trim().describe(GROUPS.LIST_USERS.id)
|
||||
}),
|
||||
querystring: z.object({
|
||||
offset: z.coerce.number().min(0).max(100).default(0).describe(GROUPS.LIST_USERS.offset),
|
||||
limit: z.coerce.number().min(1).max(100).default(10).describe(GROUPS.LIST_USERS.limit),
|
||||
username: z.string().trim().optional().describe(GROUPS.LIST_USERS.username),
|
||||
search: z.string().trim().optional().describe(GROUPS.LIST_USERS.search),
|
||||
filter: z.nativeEnum(EFilterReturnedUsers).optional().describe(GROUPS.LIST_USERS.filterUsers)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
users: UsersSchema.pick({
|
||||
email: true,
|
||||
username: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
id: true
|
||||
})
|
||||
.merge(
|
||||
z.object({
|
||||
isPartOfGroup: z.boolean(),
|
||||
joinedGroupAt: z.date().nullable()
|
||||
})
|
||||
)
|
||||
.array(),
|
||||
totalCount: z.number()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { users, totalCount } = await server.services.groupProject.listProjectGroupUsers({
|
||||
id: req.params.groupId,
|
||||
projectId: req.params.projectId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.query
|
||||
});
|
||||
|
||||
return { users, totalCount };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
|
||||
import { ActionProjectType, ProjectMembershipRole, SecretKeyEncoding, TGroups } from "@app/db/schemas";
|
||||
import { TListProjectGroupUsersDTO } from "@app/ee/services/group/group-types";
|
||||
import {
|
||||
constructPermissionErrorMessage,
|
||||
validatePrivilegeChangeOperation
|
||||
@ -43,7 +42,7 @@ type TGroupProjectServiceFactoryDep = {
|
||||
projectKeyDAL: Pick<TProjectKeyDALFactory, "findLatestProjectKey" | "delete" | "insertMany" | "transaction">;
|
||||
projectRoleDAL: Pick<TProjectRoleDALFactory, "find">;
|
||||
projectBotDAL: TProjectBotDALFactory;
|
||||
groupDAL: Pick<TGroupDALFactory, "findOne" | "findAllGroupPossibleMembers">;
|
||||
groupDAL: Pick<TGroupDALFactory, "findOne">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissionByRole">;
|
||||
};
|
||||
|
||||
@ -472,54 +471,11 @@ export const groupProjectServiceFactory = ({
|
||||
return groupMembership;
|
||||
};
|
||||
|
||||
const listProjectGroupUsers = async ({
|
||||
id,
|
||||
projectId,
|
||||
offset,
|
||||
limit,
|
||||
username,
|
||||
actor,
|
||||
actorId,
|
||||
actorAuthMethod,
|
||||
actorOrgId,
|
||||
search,
|
||||
filter
|
||||
}: TListProjectGroupUsersDTO) => {
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
if (!project) {
|
||||
throw new NotFoundError({ message: `Failed to find project with ID ${projectId}` });
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission({
|
||||
actor,
|
||||
actorId,
|
||||
projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId,
|
||||
actionProjectType: ActionProjectType.Any
|
||||
});
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups);
|
||||
|
||||
const { members, totalCount } = await groupDAL.findAllGroupPossibleMembers({
|
||||
orgId: project.orgId,
|
||||
groupId: id,
|
||||
offset,
|
||||
limit,
|
||||
username,
|
||||
search,
|
||||
filter
|
||||
});
|
||||
|
||||
return { users: members, totalCount };
|
||||
};
|
||||
|
||||
return {
|
||||
addGroupToProject,
|
||||
updateGroupInProject,
|
||||
removeGroupFromProject,
|
||||
listGroupsInProject,
|
||||
getGroupInProject,
|
||||
listProjectGroupUsers
|
||||
getGroupInProject
|
||||
};
|
||||
};
|
||||
|
@ -274,9 +274,27 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
|
||||
if (identityKubernetesAuth.tokenReviewMode === IdentityKubernetesAuthTokenReviewMode.Gateway) {
|
||||
const { kubernetesHost } = identityKubernetesAuth;
|
||||
const lastColonIndex = kubernetesHost.lastIndexOf(":");
|
||||
const k8sHost = kubernetesHost.substring(0, lastColonIndex);
|
||||
const k8sPort = kubernetesHost.substring(lastColonIndex + 1);
|
||||
|
||||
let urlString = kubernetesHost;
|
||||
if (!kubernetesHost.startsWith("http://") && !kubernetesHost.startsWith("https://")) {
|
||||
urlString = `https://${kubernetesHost}`;
|
||||
}
|
||||
|
||||
const url = new URL(urlString);
|
||||
let { port: k8sPort } = url;
|
||||
const { protocol, hostname: k8sHost } = url;
|
||||
|
||||
const cleanedProtocol = new RE2(/[^a-zA-Z0-9]/g).replace(protocol, "").toLowerCase();
|
||||
|
||||
if (!["https", "http"].includes(cleanedProtocol)) {
|
||||
throw new BadRequestError({
|
||||
message: "Invalid Kubernetes host URL, must start with http:// or https://"
|
||||
});
|
||||
}
|
||||
|
||||
if (!k8sPort) {
|
||||
k8sPort = cleanedProtocol === "https" ? "443" : "80";
|
||||
}
|
||||
|
||||
if (!identityKubernetesAuth.gatewayId) {
|
||||
throw new BadRequestError({
|
||||
@ -287,7 +305,7 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
data = await $gatewayProxyWrapper(
|
||||
{
|
||||
gatewayId: identityKubernetesAuth.gatewayId,
|
||||
targetHost: k8sHost, // note(daniel): must include the protocol (https|http)
|
||||
targetHost: `${cleanedProtocol}://${k8sHost}`, // note(daniel): must include the protocol (https|http)
|
||||
targetPort: k8sPort ? Number(k8sPort) : 443,
|
||||
caCert,
|
||||
reviewTokenThroughGateway: true
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -25,9 +26,13 @@ func handleConnection(ctx context.Context, quicConn quic.Connection) {
|
||||
log.Info().Msgf("New connection from: %s", quicConn.RemoteAddr().String())
|
||||
// Use WaitGroup to track all streams
|
||||
var wg sync.WaitGroup
|
||||
|
||||
contextWithTimeout, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
for {
|
||||
// Accept the first stream, which we'll use for commands
|
||||
stream, err := quicConn.AcceptStream(ctx)
|
||||
stream, err := quicConn.AcceptStream(contextWithTimeout)
|
||||
if err != nil {
|
||||
log.Printf("Failed to accept QUIC stream: %v", err)
|
||||
break
|
||||
@ -51,7 +56,12 @@ func handleStream(stream quic.Stream, quicConn quic.Connection) {
|
||||
|
||||
// Use buffered reader for better handling of fragmented data
|
||||
reader := bufio.NewReader(stream)
|
||||
defer stream.Close()
|
||||
defer func() {
|
||||
log.Info().Msgf("Closing stream %d", streamID)
|
||||
if stream != nil {
|
||||
stream.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
msg, err := reader.ReadBytes('\n')
|
||||
@ -106,6 +116,11 @@ func handleStream(stream quic.Stream, quicConn quic.Connection) {
|
||||
|
||||
targetURL := string(argParts[0])
|
||||
|
||||
if !isValidURL(targetURL) {
|
||||
log.Error().Msgf("Invalid target URL: %s", targetURL)
|
||||
return
|
||||
}
|
||||
|
||||
// Parse optional parameters
|
||||
var caCertB64, verifyParam string
|
||||
for _, part := range argParts[1:] {
|
||||
@ -160,7 +175,6 @@ func handleHTTPProxy(stream quic.Stream, reader *bufio.Reader, targetURL string,
|
||||
}
|
||||
}
|
||||
|
||||
// set certificate verification based on what the gateway client sent
|
||||
if verifyParam != "" {
|
||||
tlsConfig.InsecureSkipVerify = verifyParam == "false"
|
||||
log.Info().Msgf("TLS verification set to: %s", verifyParam)
|
||||
@ -169,82 +183,94 @@ func handleHTTPProxy(stream quic.Stream, reader *bufio.Reader, targetURL string,
|
||||
transport.TLSClientConfig = tlsConfig
|
||||
}
|
||||
|
||||
// read and parse the http request from the stream
|
||||
req, err := http.ReadRequest(reader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read HTTP request: %v", err)
|
||||
}
|
||||
|
||||
actionHeader := req.Header.Get("x-infisical-action")
|
||||
if actionHeader != "" {
|
||||
|
||||
if actionHeader == "inject-k8s-sa-auth-token" {
|
||||
token, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
|
||||
|
||||
if err != nil {
|
||||
stream.Write([]byte(buildHttpInternalServerError("failed to read k8s sa auth token")))
|
||||
return fmt.Errorf("failed to read k8s sa auth token: %v", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(token)))
|
||||
log.Info().Msgf("Injected gateway k8s SA auth token in request to %s", targetURL)
|
||||
}
|
||||
|
||||
req.Header.Del("x-infisical-action")
|
||||
}
|
||||
|
||||
var targetFullURL string
|
||||
if strings.HasPrefix(targetURL, "http://") || strings.HasPrefix(targetURL, "https://") {
|
||||
baseURL := strings.TrimSuffix(targetURL, "/")
|
||||
targetFullURL = baseURL + req.URL.Path
|
||||
if req.URL.RawQuery != "" {
|
||||
targetFullURL += "?" + req.URL.RawQuery
|
||||
}
|
||||
} else {
|
||||
baseURL := strings.TrimSuffix("http://"+targetURL, "/")
|
||||
targetFullURL = baseURL + req.URL.Path
|
||||
if req.URL.RawQuery != "" {
|
||||
targetFullURL += "?" + req.URL.RawQuery
|
||||
}
|
||||
}
|
||||
|
||||
// create the request to the target
|
||||
proxyReq, err := http.NewRequest(req.Method, targetFullURL, req.Body)
|
||||
proxyReq.Header = req.Header.Clone()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create proxy request: %v", err)
|
||||
}
|
||||
|
||||
log.Info().Msgf("Proxying %s %s to %s", req.Method, req.URL.Path, targetFullURL)
|
||||
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: 30 * time.Second,
|
||||
}
|
||||
|
||||
// make the request to the target
|
||||
resp, err := client.Do(proxyReq)
|
||||
if err != nil {
|
||||
stream.Write([]byte(buildHttpInternalServerError(fmt.Sprintf("failed to reach target due to networking error: %s", err.Error()))))
|
||||
return fmt.Errorf("failed to reach target due to networking error: %v", err)
|
||||
// Loop to handle multiple HTTP requests on the same stream
|
||||
for {
|
||||
req, err := http.ReadRequest(reader)
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
log.Info().Msg("Client closed HTTP connection")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed to read HTTP request: %v", err)
|
||||
}
|
||||
log.Info().Msgf("Received HTTP request: %s", req.URL.Path)
|
||||
|
||||
actionHeader := req.Header.Get("x-infisical-action")
|
||||
if actionHeader != "" {
|
||||
if actionHeader == "inject-k8s-sa-auth-token" {
|
||||
token, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
|
||||
if err != nil {
|
||||
stream.Write([]byte(buildHttpInternalServerError("failed to read k8s sa auth token")))
|
||||
continue // Continue to next request instead of returning
|
||||
}
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", string(token)))
|
||||
log.Info().Msgf("Injected gateway k8s SA auth token in request to %s", targetURL)
|
||||
}
|
||||
req.Header.Del("x-infisical-action")
|
||||
}
|
||||
|
||||
// Build full target URL
|
||||
var targetFullURL string
|
||||
if strings.HasPrefix(targetURL, "http://") || strings.HasPrefix(targetURL, "https://") {
|
||||
baseURL := strings.TrimSuffix(targetURL, "/")
|
||||
targetFullURL = baseURL + req.URL.Path
|
||||
if req.URL.RawQuery != "" {
|
||||
targetFullURL += "?" + req.URL.RawQuery
|
||||
}
|
||||
} else {
|
||||
baseURL := strings.TrimSuffix("http://"+targetURL, "/")
|
||||
targetFullURL = baseURL + req.URL.Path
|
||||
if req.URL.RawQuery != "" {
|
||||
targetFullURL += "?" + req.URL.RawQuery
|
||||
}
|
||||
}
|
||||
|
||||
// create the request to the target
|
||||
proxyReq, err := http.NewRequest(req.Method, targetFullURL, req.Body)
|
||||
if err != nil {
|
||||
log.Error().Msgf("Failed to create proxy request: %v", err)
|
||||
stream.Write([]byte(buildHttpInternalServerError("failed to create proxy request")))
|
||||
continue // Continue to next request
|
||||
}
|
||||
proxyReq.Header = req.Header.Clone()
|
||||
|
||||
log.Info().Msgf("Proxying %s %s to %s", req.Method, req.URL.Path, targetFullURL)
|
||||
|
||||
resp, err := client.Do(proxyReq)
|
||||
if err != nil {
|
||||
log.Error().Msgf("Failed to reach target: %v", err)
|
||||
stream.Write([]byte(buildHttpInternalServerError(fmt.Sprintf("failed to reach target due to networking error: %s", err.Error()))))
|
||||
continue // Continue to next request
|
||||
}
|
||||
|
||||
// Write the entire response (status line, headers, body) to the stream
|
||||
// http.Response.Write handles this for "Connection: close" correctly.
|
||||
// For other connection tokens, manual removal might be needed if they cause issues with QUIC.
|
||||
// For a simple proxy, this is generally sufficient.
|
||||
resp.Header.Del("Connection") // Good practice for proxies
|
||||
|
||||
log.Info().Msgf("Writing response to stream: %s", resp.Status)
|
||||
|
||||
if err := resp.Write(stream); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to write response to stream")
|
||||
resp.Body.Close()
|
||||
return fmt.Errorf("failed to write response to stream: %w", err)
|
||||
}
|
||||
|
||||
resp.Body.Close()
|
||||
|
||||
// Check if client wants to close connection
|
||||
if req.Header.Get("Connection") == "close" {
|
||||
log.Info().Msg("Client requested connection close")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Write the entire response (status line, headers, body) to the stream
|
||||
// http.Response.Write handles this for "Connection: close" correctly.
|
||||
// For other connection tokens, manual removal might be needed if they cause issues with QUIC.
|
||||
// For a simple proxy, this is generally sufficient.
|
||||
resp.Header.Del("Connection") // Good practice for proxies
|
||||
|
||||
log.Info().Msgf("Writing response to stream: %s", resp.Status)
|
||||
if err := resp.Write(stream); err != nil {
|
||||
// If writing the response fails, the connection to the client might be broken.
|
||||
// Logging the error is important. The original error will be returned.
|
||||
log.Error().Err(err).Msg("Failed to write response to stream")
|
||||
return fmt.Errorf("failed to write response to stream: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildHttpInternalServerError(message string) string {
|
||||
@ -255,6 +281,11 @@ type CloseWrite interface {
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
func isValidURL(str string) bool {
|
||||
u, err := url.Parse(str)
|
||||
return err == nil && u.Scheme != "" && u.Host != ""
|
||||
}
|
||||
|
||||
func CopyDataFromQuicToTcp(quicStream quic.Stream, tcpConn net.Conn) {
|
||||
// Create a WaitGroup to wait for both copy operations
|
||||
var wg sync.WaitGroup
|
||||
|
@ -21,27 +21,7 @@ export const groupKeys = {
|
||||
limit: number;
|
||||
search: string;
|
||||
filter?: EFilterReturnedUsers;
|
||||
}) => [...groupKeys.forGroupUserMemberships(slug), { offset, limit, search, filter }] as const,
|
||||
specificProjectGroupUserMemberships: ({
|
||||
projectId,
|
||||
slug,
|
||||
offset,
|
||||
limit,
|
||||
search,
|
||||
filter
|
||||
}: {
|
||||
slug: string;
|
||||
projectId: string;
|
||||
offset: number;
|
||||
limit: number;
|
||||
search: string;
|
||||
filter?: EFilterReturnedUsers;
|
||||
}) =>
|
||||
[
|
||||
...groupKeys.forGroupUserMemberships(slug),
|
||||
projectId,
|
||||
{ offset, limit, search, filter }
|
||||
] as const
|
||||
}) => [...groupKeys.forGroupUserMemberships(slug), { offset, limit, search, filter }] as const
|
||||
};
|
||||
|
||||
export const useGetGroupById = (groupId: string) => {
|
||||
@ -100,51 +80,3 @@ export const useListGroupUsers = ({
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useListProjectGroupUsers = ({
|
||||
id,
|
||||
projectId,
|
||||
groupSlug,
|
||||
offset = 0,
|
||||
limit = 10,
|
||||
search,
|
||||
filter
|
||||
}: {
|
||||
id: string;
|
||||
groupSlug: string;
|
||||
projectId: string;
|
||||
offset: number;
|
||||
limit: number;
|
||||
search: string;
|
||||
filter?: EFilterReturnedUsers;
|
||||
}) => {
|
||||
return useQuery({
|
||||
queryKey: groupKeys.specificProjectGroupUserMemberships({
|
||||
slug: groupSlug,
|
||||
projectId,
|
||||
offset,
|
||||
limit,
|
||||
search,
|
||||
filter
|
||||
}),
|
||||
enabled: Boolean(groupSlug),
|
||||
placeholderData: (previousData) => previousData,
|
||||
queryFn: async () => {
|
||||
const params = new URLSearchParams({
|
||||
offset: String(offset),
|
||||
limit: String(limit),
|
||||
search,
|
||||
...(filter && { filter })
|
||||
});
|
||||
|
||||
const { data } = await apiRequest.get<{ users: TGroupUser[]; totalCount: number }>(
|
||||
`/api/v2/workspace/${projectId}/groups/${id}/users`,
|
||||
{
|
||||
params
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -50,13 +50,10 @@ export const useUpdateGroupWorkspaceRole = () => {
|
||||
|
||||
return groupMembership;
|
||||
},
|
||||
onSuccess: (_, { projectId, groupId }) => {
|
||||
onSuccess: (_, { projectId }) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: workspaceKeys.getWorkspaceGroupMemberships(projectId)
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: workspaceKeys.getWorkspaceGroupMembershipDetails(projectId, groupId)
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -691,21 +691,6 @@ export const useGetWorkspaceIdentityMembershipDetails = (projectId: string, iden
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetWorkspaceGroupMembershipDetails = (projectId: string, groupId: string) => {
|
||||
return useQuery({
|
||||
enabled: Boolean(projectId && groupId),
|
||||
queryKey: workspaceKeys.getWorkspaceGroupMembershipDetails(projectId, groupId),
|
||||
queryFn: async () => {
|
||||
const {
|
||||
data: { groupMembership }
|
||||
} = await apiRequest.get<{ groupMembership: TGroupMembership }>(
|
||||
`/api/v2/workspace/${projectId}/groups/${groupId}`
|
||||
);
|
||||
return groupMembership;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useListWorkspaceGroups = (projectId: string) => {
|
||||
return useQuery({
|
||||
queryKey: workspaceKeys.getWorkspaceGroupMemberships(projectId),
|
||||
|
@ -36,8 +36,6 @@ export const workspaceKeys = {
|
||||
searchWorkspace: (dto: TSearchProjectsDTO) => ["search-projects", dto] as const,
|
||||
getWorkspaceGroupMemberships: (workspaceId: string) =>
|
||||
[{ workspaceId }, "workspace-groups"] as const,
|
||||
getWorkspaceGroupMembershipDetails: (workspaceId: string, groupId: string) =>
|
||||
[{ workspaceId, groupId }, "workspace-group-membership-details"] as const,
|
||||
getWorkspaceCas: ({ projectSlug }: { projectSlug: string }) =>
|
||||
[{ projectSlug }, "workspace-cas"] as const,
|
||||
specificWorkspaceCas: ({ projectSlug, status }: { projectSlug: string; status?: CaStatus }) =>
|
||||
|
@ -152,7 +152,7 @@ export const GroupMembersTable = ({ groupId, groupSlug, handlePopUpOpen }: Props
|
||||
</Th>
|
||||
<Th>Email</Th>
|
||||
<Th>Added On</Th>
|
||||
<Th className="w-5" />
|
||||
<Th />
|
||||
</Tr>
|
||||
</THead>
|
||||
<TBody>
|
||||
|
@ -1,17 +1,8 @@
|
||||
import { faEllipsisV, faUserMinus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faUserMinus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
IconButton,
|
||||
Td,
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { IconButton, Td, Tooltip, Tr } from "@app/components/v2";
|
||||
import { OrgPermissionGroupActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
||||
import { useOidcManageGroupMembershipsEnabled } from "@app/hooks/api";
|
||||
import { TGroupUser } from "@app/hooks/api/groups/types";
|
||||
@ -47,47 +38,30 @@ export const GroupMembershipRow = ({
|
||||
<p>{new Date(joinedGroupAt).toLocaleDateString()}</p>
|
||||
</Tooltip>
|
||||
</Td>
|
||||
<Td>
|
||||
<Tooltip className="max-w-sm text-center" content="Options">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<IconButton
|
||||
ariaLabel="Options"
|
||||
colorSchema="secondary"
|
||||
className="w-6"
|
||||
variant="plain"
|
||||
<Td className="justify-end">
|
||||
<OrgPermissionCan I={OrgPermissionGroupActions.Edit} a={OrgPermissionSubjects.Groups}>
|
||||
{(isAllowed) => {
|
||||
return (
|
||||
<Tooltip
|
||||
content={
|
||||
isOidcManageGroupMembershipsEnabled
|
||||
? "OIDC Group Membership Mapping Enabled. Remove user from this group in your OIDC provider."
|
||||
: "Remove user from group"
|
||||
}
|
||||
>
|
||||
<FontAwesomeIcon icon={faEllipsisV} />
|
||||
</IconButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent sideOffset={2} align="end">
|
||||
<OrgPermissionCan I={OrgPermissionGroupActions.Edit} a={OrgPermissionSubjects.Groups}>
|
||||
{(isAllowed) => {
|
||||
return (
|
||||
<Tooltip
|
||||
content={
|
||||
isOidcManageGroupMembershipsEnabled
|
||||
? "OIDC Group Membership Mapping Enabled. Remove user from this group in your OIDC provider."
|
||||
: undefined
|
||||
}
|
||||
position="left"
|
||||
>
|
||||
<div>
|
||||
<DropdownMenuItem
|
||||
icon={<FontAwesomeIcon icon={faUserMinus} />}
|
||||
onClick={() => handlePopUpOpen("removeMemberFromGroup", { username })}
|
||||
isDisabled={!isAllowed || isOidcManageGroupMembershipsEnabled}
|
||||
>
|
||||
Remove User From Group
|
||||
</DropdownMenuItem>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}}
|
||||
</OrgPermissionCan>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</Tooltip>
|
||||
<IconButton
|
||||
isDisabled={!isAllowed || isOidcManageGroupMembershipsEnabled}
|
||||
ariaLabel="Remove user from group"
|
||||
onClick={() => handlePopUpOpen("removeMemberFromGroup", { username })}
|
||||
variant="plain"
|
||||
colorSchema="danger"
|
||||
>
|
||||
<FontAwesomeIcon icon={faUserMinus} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
);
|
||||
}}
|
||||
</OrgPermissionCan>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
|
@ -3,7 +3,6 @@ import { Controller, useForm } from "react-hook-form";
|
||||
import { faCheck, faClock, faEdit, faSearch } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { PopperContentProps } from "@radix-ui/react-popper";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { z } from "zod";
|
||||
|
||||
@ -29,7 +28,6 @@ import { formatProjectRoleName } from "@app/helpers/roles";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useGetProjectRoles, useUpdateGroupWorkspaceRole } from "@app/hooks/api";
|
||||
import { TGroupMembership } from "@app/hooks/api/groups/types";
|
||||
import { TProjectRole } from "@app/hooks/api/roles/types";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/hooks/api/workspace/types";
|
||||
import { groupBy } from "@app/lib/fn/array";
|
||||
|
||||
@ -198,38 +196,33 @@ type TForm = z.infer<typeof formSchema>;
|
||||
export type TMemberRolesProp = {
|
||||
disableEdit?: boolean;
|
||||
groupId: string;
|
||||
className?: string;
|
||||
roles: TGroupMembership["roles"];
|
||||
popperContentProps?: PopperContentProps;
|
||||
};
|
||||
|
||||
const MAX_ROLES_TO_BE_SHOWN_IN_TABLE = 2;
|
||||
|
||||
type FormProps = {
|
||||
projectRoles: Omit<TProjectRole, "permissions">[] | undefined;
|
||||
roles: TGroupMembership["roles"];
|
||||
groupId: string;
|
||||
onClose: VoidFunction;
|
||||
};
|
||||
|
||||
const GroupRolesForm = ({ projectRoles, roles, groupId, onClose }: FormProps) => {
|
||||
export const GroupRoles = ({ roles = [], disableEdit = false, groupId }: TMemberRolesProp) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
const { popUp, handlePopUpToggle } = usePopUp(["editRole"] as const);
|
||||
const [searchRoles, setSearchRoles] = useState("");
|
||||
|
||||
const userRolesGroupBySlug = groupBy(roles, ({ customRoleSlug, role }) => customRoleSlug || role);
|
||||
|
||||
const updateGroupWorkspaceRole = useUpdateGroupWorkspaceRole();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
reset,
|
||||
setValue,
|
||||
formState: { isSubmitting, isDirty }
|
||||
} = useForm<TForm>({
|
||||
resolver: zodResolver(formSchema)
|
||||
});
|
||||
|
||||
const { data: projectRoles, isPending: isRolesLoading } = useGetProjectRoles(
|
||||
currentWorkspace?.id ?? ""
|
||||
);
|
||||
const userRolesGroupBySlug = groupBy(roles, ({ customRoleSlug, role }) => customRoleSlug || role);
|
||||
|
||||
const updateGroupWorkspaceRole = useUpdateGroupWorkspaceRole();
|
||||
|
||||
const handleRoleUpdate = async (data: TForm) => {
|
||||
const selectedRoles = Object.keys(data)
|
||||
.filter((el) => Boolean(data[el].isChecked))
|
||||
@ -260,7 +253,7 @@ const GroupRolesForm = ({ projectRoles, roles, groupId, onClose }: FormProps) =>
|
||||
roles: selectedRoles
|
||||
});
|
||||
createNotification({ text: "Successfully updated group role", type: "success" });
|
||||
onClose();
|
||||
handlePopUpToggle("editRole");
|
||||
setSearchRoles("");
|
||||
} catch {
|
||||
createNotification({ text: "Failed to update group role", type: "error" });
|
||||
@ -268,120 +261,7 @@ const GroupRolesForm = ({ projectRoles, roles, groupId, onClose }: FormProps) =>
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(handleRoleUpdate)} id="role-update-form">
|
||||
<div className="thin-scrollbar max-h-80 space-y-4 overflow-y-auto">
|
||||
{projectRoles
|
||||
?.filter(
|
||||
({ name, slug }) =>
|
||||
name.toLowerCase().includes(searchRoles.toLowerCase()) ||
|
||||
slug.toLowerCase().includes(searchRoles.toLowerCase())
|
||||
)
|
||||
?.map(({ id, name, slug }) => {
|
||||
const userProjectRoleDetails = userRolesGroupBySlug?.[slug]?.[0];
|
||||
|
||||
return (
|
||||
<div key={id} className="flex items-center space-x-4">
|
||||
<div className="flex-grow">
|
||||
<Controller
|
||||
control={control}
|
||||
defaultValue={Boolean(userProjectRoleDetails?.id)}
|
||||
name={`${slug}.isChecked`}
|
||||
render={({ field }) => (
|
||||
<Checkbox
|
||||
id={slug}
|
||||
isChecked={field.value}
|
||||
onCheckedChange={(isChecked) => {
|
||||
field.onChange(isChecked);
|
||||
setValue(`${slug}.temporaryAccess`, false);
|
||||
}}
|
||||
>
|
||||
{name}
|
||||
</Checkbox>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Controller
|
||||
control={control}
|
||||
name={`${slug}.temporaryAccess`}
|
||||
defaultValue={
|
||||
userProjectRoleDetails?.isTemporary
|
||||
? {
|
||||
isTemporary: true,
|
||||
temporaryAccessStartTime:
|
||||
userProjectRoleDetails.temporaryAccessStartTime as string,
|
||||
temporaryRange: userProjectRoleDetails.temporaryRange as string,
|
||||
temporaryAccessEndTime: userProjectRoleDetails.temporaryAccessEndTime
|
||||
}
|
||||
: false
|
||||
}
|
||||
render={({ field }) => (
|
||||
<IdentityTemporaryRoleForm
|
||||
temporaryConfig={
|
||||
typeof field.value === "boolean"
|
||||
? { isTemporary: field.value }
|
||||
: field.value
|
||||
}
|
||||
onSetTemporary={(data) => {
|
||||
setValue(`${slug}.isChecked`, true, { shouldDirty: true });
|
||||
field.onChange({ isTemporary: true, ...data });
|
||||
}}
|
||||
onRemoveTemporary={() => {
|
||||
setValue(`${slug}.isChecked`, false, { shouldDirty: true });
|
||||
field.onChange(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="mt-3 flex items-center space-x-2 border-t border-t-gray-700 pt-3">
|
||||
<div>
|
||||
<Input
|
||||
className="w-full p-1.5 pl-8"
|
||||
size="xs"
|
||||
value={searchRoles}
|
||||
onChange={(el) => setSearchRoles(el.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faSearch} />}
|
||||
placeholder="Search roles.."
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
size="xs"
|
||||
type="submit"
|
||||
form="role-update-form"
|
||||
leftIcon={<FontAwesomeIcon icon={faCheck} />}
|
||||
isDisabled={!isDirty || isSubmitting}
|
||||
isLoading={isSubmitting}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export const GroupRoles = ({
|
||||
roles = [],
|
||||
disableEdit = false,
|
||||
groupId,
|
||||
className,
|
||||
popperContentProps
|
||||
}: TMemberRolesProp) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { popUp, handlePopUpToggle } = usePopUp(["editRole"] as const);
|
||||
|
||||
const { data: projectRoles, isPending: isRolesLoading } = useGetProjectRoles(
|
||||
currentWorkspace?.id ?? ""
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={twMerge("flex items-center space-x-1", className)}>
|
||||
<div className="flex items-center space-x-2">
|
||||
{roles
|
||||
.slice(0, MAX_ROLES_TO_BE_SHOWN_IN_TABLE)
|
||||
.map(({ role, customRoleName, id, isTemporary, temporaryAccessEndTime }) => {
|
||||
@ -445,32 +325,119 @@ export const GroupRoles = ({
|
||||
open={popUp.editRole.isOpen}
|
||||
onOpenChange={(isOpen) => {
|
||||
handlePopUpToggle("editRole", isOpen);
|
||||
reset();
|
||||
}}
|
||||
>
|
||||
{!disableEdit && (
|
||||
<PopoverTrigger onClick={(e) => e.stopPropagation()}>
|
||||
<PopoverTrigger>
|
||||
<IconButton size="sm" variant="plain" ariaLabel="update">
|
||||
<FontAwesomeIcon icon={faEdit} />
|
||||
</IconButton>
|
||||
</PopoverTrigger>
|
||||
)}
|
||||
<PopoverContent
|
||||
{...popperContentProps}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
hideCloseBtn
|
||||
className="pt-4"
|
||||
>
|
||||
<PopoverContent hideCloseBtn className="pt-4">
|
||||
{isRolesLoading ? (
|
||||
<div className="flex h-8 w-full items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<GroupRolesForm
|
||||
projectRoles={projectRoles}
|
||||
groupId={groupId}
|
||||
roles={roles}
|
||||
onClose={() => handlePopUpToggle("editRole")}
|
||||
/>
|
||||
<form onSubmit={handleSubmit(handleRoleUpdate)} id="role-update-form">
|
||||
<div className="thin-scrollbar max-h-80 space-y-4 overflow-y-auto">
|
||||
{projectRoles
|
||||
?.filter(
|
||||
({ name, slug }) =>
|
||||
name.toLowerCase().includes(searchRoles.toLowerCase()) ||
|
||||
slug.toLowerCase().includes(searchRoles.toLowerCase())
|
||||
)
|
||||
?.map(({ id, name, slug }) => {
|
||||
const userProjectRoleDetails = userRolesGroupBySlug?.[slug]?.[0];
|
||||
|
||||
return (
|
||||
<div key={id} className="flex items-center space-x-4">
|
||||
<div className="flex-grow">
|
||||
<Controller
|
||||
control={control}
|
||||
defaultValue={Boolean(userProjectRoleDetails?.id)}
|
||||
name={`${slug}.isChecked`}
|
||||
render={({ field }) => (
|
||||
<Checkbox
|
||||
id={slug}
|
||||
isChecked={field.value}
|
||||
onCheckedChange={(isChecked) => {
|
||||
field.onChange(isChecked);
|
||||
setValue(`${slug}.temporaryAccess`, false);
|
||||
}}
|
||||
>
|
||||
{name}
|
||||
</Checkbox>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Controller
|
||||
control={control}
|
||||
name={`${slug}.temporaryAccess`}
|
||||
defaultValue={
|
||||
userProjectRoleDetails?.isTemporary
|
||||
? {
|
||||
isTemporary: true,
|
||||
temporaryAccessStartTime:
|
||||
userProjectRoleDetails.temporaryAccessStartTime as string,
|
||||
temporaryRange:
|
||||
userProjectRoleDetails.temporaryRange as string,
|
||||
temporaryAccessEndTime:
|
||||
userProjectRoleDetails.temporaryAccessEndTime
|
||||
}
|
||||
: false
|
||||
}
|
||||
render={({ field }) => (
|
||||
<IdentityTemporaryRoleForm
|
||||
temporaryConfig={
|
||||
typeof field.value === "boolean"
|
||||
? { isTemporary: field.value }
|
||||
: field.value
|
||||
}
|
||||
onSetTemporary={(data) => {
|
||||
setValue(`${slug}.isChecked`, true, { shouldDirty: true });
|
||||
field.onChange({ isTemporary: true, ...data });
|
||||
}}
|
||||
onRemoveTemporary={() => {
|
||||
setValue(`${slug}.isChecked`, false, { shouldDirty: true });
|
||||
field.onChange(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="mt-3 flex items-center space-x-2 border-t border-t-gray-700 pt-3">
|
||||
<div>
|
||||
<Input
|
||||
className="w-full p-1.5 pl-8"
|
||||
size="xs"
|
||||
value={searchRoles}
|
||||
onChange={(el) => setSearchRoles(el.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faSearch} />}
|
||||
placeholder="Search roles.."
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
size="xs"
|
||||
type="submit"
|
||||
form="role-update-form"
|
||||
leftIcon={<FontAwesomeIcon icon={faCheck} />}
|
||||
isDisabled={!isDirty || isSubmitting}
|
||||
isLoading={isSubmitting}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
)}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
faUsers
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
import { format } from "date-fns";
|
||||
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
@ -56,7 +55,6 @@ enum GroupsOrderBy {
|
||||
|
||||
export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const {
|
||||
search,
|
||||
@ -145,32 +143,7 @@ export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
||||
.slice(offset, perPage * page)
|
||||
.map(({ group: { id, name }, roles, createdAt }) => {
|
||||
return (
|
||||
<Tr
|
||||
className="group h-10 w-full cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||
key={`st-v3-${id}`}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onKeyDown={(evt) => {
|
||||
if (evt.key === "Enter") {
|
||||
navigate({
|
||||
to: `/${currentWorkspace.type}/$projectId/groups/$groupId` as const,
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
groupId: id
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
onClick={() =>
|
||||
navigate({
|
||||
to: `/${currentWorkspace.type}/$projectId/groups/$groupId` as const,
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
groupId: id
|
||||
}
|
||||
})
|
||||
}
|
||||
>
|
||||
<Tr className="group h-10" key={`st-v3-${id}`}>
|
||||
<Td>{name}</Td>
|
||||
<Td>
|
||||
<ProjectPermissionCan
|
||||
@ -192,8 +165,7 @@ export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
||||
<div className="opacity-0 transition-opacity duration-300 group-hover:opacity-100">
|
||||
<Tooltip content="Remove">
|
||||
<IconButton
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onClick={() => {
|
||||
handlePopUpOpen("deleteGroup", {
|
||||
id,
|
||||
name
|
||||
|
@ -1,70 +0,0 @@
|
||||
import { Helmet } from "react-helmet";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useParams } from "@tanstack/react-router";
|
||||
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { EmptyState, PageHeader, Spinner } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { useGetWorkspaceGroupMembershipDetails } from "@app/hooks/api/workspace/queries";
|
||||
|
||||
import { GroupDetailsSection } from "./components/GroupDetailsSection";
|
||||
import { GroupMembersSection } from "./components/GroupMembersSection";
|
||||
|
||||
const Page = () => {
|
||||
const groupId = useParams({
|
||||
strict: false,
|
||||
select: (el) => el.groupId as string
|
||||
});
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
const { data: groupMembership, isPending } = useGetWorkspaceGroupMembershipDetails(
|
||||
currentWorkspace.id,
|
||||
groupId
|
||||
);
|
||||
|
||||
if (isPending)
|
||||
return (
|
||||
<div className="flex w-full items-center justify-center p-24">
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||
{groupMembership ? (
|
||||
<div className="mx-auto mb-6 w-full max-w-7xl">
|
||||
<PageHeader title={groupMembership.group.name} />
|
||||
<div className="flex">
|
||||
<div className="mr-4 w-96">
|
||||
<GroupDetailsSection groupMembership={groupMembership} />
|
||||
</div>
|
||||
<GroupMembersSection groupMembership={groupMembership} />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<EmptyState title="Error: Unable to find the group." className="py-12" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const GroupDetailsByIDPage = () => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{t("common.head-title", { title: "Project Group" })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Helmet>
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Read}
|
||||
a={ProjectPermissionSub.Groups}
|
||||
passThrough={false}
|
||||
renderGuardBanner
|
||||
>
|
||||
<Page />
|
||||
</ProjectPermissionCan>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,152 +0,0 @@
|
||||
import { faEllipsisV, faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
import { format } from "date-fns";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import {
|
||||
DeleteActionModal,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
IconButton
|
||||
} from "@app/components/v2";
|
||||
import { CopyButton } from "@app/components/v2/CopyButton";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useDeleteGroupFromWorkspace } from "@app/hooks/api";
|
||||
import { TGroupMembership } from "@app/hooks/api/groups/types";
|
||||
import { GroupRoles } from "@app/pages/project/AccessControlPage/components/GroupsTab/components/GroupsSection/GroupRoles";
|
||||
|
||||
type Props = {
|
||||
groupMembership: TGroupMembership;
|
||||
};
|
||||
|
||||
export const GroupDetailsSection = ({ groupMembership }: Props) => {
|
||||
const { handlePopUpToggle, popUp, handlePopUpClose, handlePopUpOpen } = usePopUp([
|
||||
"deleteGroup"
|
||||
] as const);
|
||||
|
||||
const { mutateAsync: deleteMutateAsync } = useDeleteGroupFromWorkspace();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onRemoveGroupSubmit = async () => {
|
||||
try {
|
||||
await deleteMutateAsync({
|
||||
groupId: groupMembership.group.id,
|
||||
projectId: currentWorkspace.id
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully removed group from project",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
navigate({
|
||||
to: `/${currentWorkspace.type}/${currentWorkspace.id}/access-management?selectedTab=groups`
|
||||
});
|
||||
|
||||
handlePopUpClose("deleteGroup");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
const error = err as any;
|
||||
const text = error?.response?.data?.message ?? "Failed to remove group from project";
|
||||
|
||||
createNotification({
|
||||
text,
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
||||
<h3 className="text-lg font-semibold text-mineshaft-100">Group Details</h3>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<IconButton ariaLabel="Options" colorSchema="secondary" className="w-6" variant="plain">
|
||||
<FontAwesomeIcon icon={faEllipsisV} />
|
||||
</IconButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent sideOffset={2} align="end">
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Delete}
|
||||
a={ProjectPermissionSub.Groups}
|
||||
>
|
||||
{(isAllowed) => {
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
icon={<FontAwesomeIcon icon={faTrash} />}
|
||||
onClick={() => handlePopUpOpen("deleteGroup")}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Remove Group From Project
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
}}
|
||||
</ProjectPermissionCan>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<div className="pt-4">
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-semibold text-mineshaft-300">Group ID</p>
|
||||
<div className="group flex items-center gap-2">
|
||||
<p className="text-sm text-mineshaft-300">{groupMembership.group.id}</p>
|
||||
<CopyButton
|
||||
value={groupMembership.group.id}
|
||||
name="Group ID"
|
||||
size="xs"
|
||||
variant="plain"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-semibold text-mineshaft-300">Name</p>
|
||||
<p className="text-sm text-mineshaft-300">{groupMembership.group.name}</p>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-semibold text-mineshaft-300">Slug</p>
|
||||
<div className="group flex items-center gap-2">
|
||||
<p className="text-sm text-mineshaft-300">{groupMembership.group.slug}</p>
|
||||
<CopyButton value={groupMembership.group.slug} name="Slug" size="xs" variant="plain" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-semibold text-mineshaft-300">Project Role</p>
|
||||
<ProjectPermissionCan I={ProjectPermissionActions.Edit} a={ProjectPermissionSub.Groups}>
|
||||
{(isAllowed) => (
|
||||
<GroupRoles
|
||||
className="mt-1"
|
||||
popperContentProps={{ side: "right" }}
|
||||
roles={groupMembership.roles}
|
||||
groupId={groupMembership.group.id}
|
||||
disableEdit={!isAllowed}
|
||||
/>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-semibold text-mineshaft-300">Assigned to Project</p>
|
||||
<p className="text-sm text-mineshaft-300">
|
||||
{format(groupMembership.createdAt, "M/d/yyyy")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.deleteGroup.isOpen}
|
||||
title={`Are you sure you want to remove the group ${
|
||||
groupMembership.group.name
|
||||
} from the project?`}
|
||||
onChange={(isOpen) => handlePopUpToggle("deleteGroup", isOpen)}
|
||||
deleteKey="confirm"
|
||||
buttonText="Remove"
|
||||
onDeleteApproved={onRemoveGroupSubmit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,20 +0,0 @@
|
||||
import { TGroupMembership } from "@app/hooks/api/groups/types";
|
||||
|
||||
import { GroupMembersTable } from "./GroupMembersTable";
|
||||
|
||||
type Props = {
|
||||
groupMembership: TGroupMembership;
|
||||
};
|
||||
|
||||
export const GroupMembersSection = ({ groupMembership }: Props) => {
|
||||
return (
|
||||
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
||||
<h3 className="text-lg font-semibold text-mineshaft-100">Group Members</h3>
|
||||
</div>
|
||||
<div className="py-4">
|
||||
<GroupMembersTable groupMembership={groupMembership} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,235 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
import {
|
||||
faArrowDown,
|
||||
faArrowUp,
|
||||
faFolder,
|
||||
faMagnifyingGlass,
|
||||
faSearch
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
ConfirmActionModal,
|
||||
EmptyState,
|
||||
IconButton,
|
||||
Input,
|
||||
Pagination,
|
||||
Table,
|
||||
TableContainer,
|
||||
TableSkeleton,
|
||||
TBody,
|
||||
Th,
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import {
|
||||
getUserTablePreference,
|
||||
PreferenceKey,
|
||||
setUserTablePreference
|
||||
} from "@app/helpers/userTablePreferences";
|
||||
import { usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
|
||||
import { useAssumeProjectPrivileges } from "@app/hooks/api";
|
||||
import { ActorType } from "@app/hooks/api/auditLogs/enums";
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
import { useListProjectGroupUsers } from "@app/hooks/api/groups/queries";
|
||||
import { EFilterReturnedUsers, TGroupMembership } from "@app/hooks/api/groups/types";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
import { GroupMembershipRow } from "./GroupMembershipRow";
|
||||
|
||||
type Props = {
|
||||
groupMembership: TGroupMembership;
|
||||
};
|
||||
|
||||
enum GroupMembersOrderBy {
|
||||
Name = "name"
|
||||
}
|
||||
|
||||
export const GroupMembersTable = ({ groupMembership }: Props) => {
|
||||
const {
|
||||
search,
|
||||
setSearch,
|
||||
setPage,
|
||||
page,
|
||||
perPage,
|
||||
setPerPage,
|
||||
offset,
|
||||
orderDirection,
|
||||
toggleOrderDirection
|
||||
} = usePagination(GroupMembersOrderBy.Name, {
|
||||
initPerPage: getUserTablePreference("projectGroupMembersTable", PreferenceKey.PerPage, 20)
|
||||
});
|
||||
|
||||
const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp(["assumePrivileges"] as const);
|
||||
|
||||
const handlePerPageChange = (newPerPage: number) => {
|
||||
setPerPage(newPerPage);
|
||||
setUserTablePreference("projectGroupMembersTable", PreferenceKey.PerPage, newPerPage);
|
||||
};
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
const { data: groupMemberships, isPending } = useListProjectGroupUsers({
|
||||
id: groupMembership.group.id,
|
||||
groupSlug: groupMembership.group.slug,
|
||||
projectId: currentWorkspace.id,
|
||||
offset,
|
||||
limit: perPage,
|
||||
search,
|
||||
filter: EFilterReturnedUsers.EXISTING_MEMBERS
|
||||
});
|
||||
|
||||
const filteredGroupMemberships = useMemo(() => {
|
||||
return groupMemberships && groupMemberships?.users
|
||||
? groupMemberships?.users
|
||||
?.filter((membership) => {
|
||||
const userSearchString = `${membership.firstName && membership.firstName} ${
|
||||
membership.lastName && membership.lastName
|
||||
} ${membership.email && membership.email} ${
|
||||
membership.username && membership.username
|
||||
}`;
|
||||
return userSearchString.toLowerCase().includes(search.trim().toLowerCase());
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const [membershipOne, membershipTwo] =
|
||||
orderDirection === OrderByDirection.ASC ? [a, b] : [b, a];
|
||||
|
||||
const membershipOneComparisonString = membershipOne.firstName
|
||||
? membershipOne.firstName
|
||||
: membershipOne.email;
|
||||
|
||||
const membershipTwoComparisonString = membershipTwo.firstName
|
||||
? membershipTwo.firstName
|
||||
: membershipTwo.email;
|
||||
|
||||
const comparison = membershipOneComparisonString
|
||||
.toLowerCase()
|
||||
.localeCompare(membershipTwoComparisonString.toLowerCase());
|
||||
|
||||
return comparison;
|
||||
})
|
||||
: [];
|
||||
}, [groupMemberships, orderDirection, search]);
|
||||
|
||||
useResetPageHelper({
|
||||
totalCount: filteredGroupMemberships?.length,
|
||||
offset,
|
||||
setPage
|
||||
});
|
||||
|
||||
const assumePrivileges = useAssumeProjectPrivileges();
|
||||
|
||||
const handleAssumePrivileges = async () => {
|
||||
const { userId } = popUp?.assumePrivileges?.data as { userId: string };
|
||||
assumePrivileges.mutate(
|
||||
{
|
||||
actorId: userId,
|
||||
actorType: ActorType.USER,
|
||||
projectId: currentWorkspace.id
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
createNotification({
|
||||
type: "success",
|
||||
text: "User privilege assumption has started"
|
||||
});
|
||||
|
||||
let overviewPage: string;
|
||||
|
||||
switch (currentWorkspace.type) {
|
||||
case ProjectType.SecretScanning:
|
||||
overviewPage = "data-sources";
|
||||
break;
|
||||
case ProjectType.CertificateManager:
|
||||
overviewPage = "subscribers";
|
||||
break;
|
||||
default:
|
||||
overviewPage = "overview";
|
||||
}
|
||||
|
||||
window.location.href = `/${currentWorkspace.type}/${currentWorkspace.id}/${overviewPage}`;
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
placeholder="Search users..."
|
||||
/>
|
||||
<TableContainer className="mt-4">
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th className="w-1/3">
|
||||
<div className="flex items-center">
|
||||
Name
|
||||
<IconButton
|
||||
variant="plain"
|
||||
className="ml-2"
|
||||
ariaLabel="sort"
|
||||
onClick={toggleOrderDirection}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={orderDirection === OrderByDirection.DESC ? faArrowUp : faArrowDown}
|
||||
/>
|
||||
</IconButton>
|
||||
</div>
|
||||
</Th>
|
||||
<Th>Email</Th>
|
||||
<Th>Added On</Th>
|
||||
<Th className="w-5" />
|
||||
</Tr>
|
||||
</THead>
|
||||
<TBody>
|
||||
{isPending && <TableSkeleton columns={4} innerKey="group-user-memberships" />}
|
||||
{!isPending &&
|
||||
filteredGroupMemberships.slice(offset, perPage * page).map((userGroupMembership) => {
|
||||
return (
|
||||
<GroupMembershipRow
|
||||
key={`user-group-membership-${userGroupMembership.id}`}
|
||||
user={userGroupMembership}
|
||||
onAssumePrivileges={(userId) => handlePopUpOpen("assumePrivileges", { userId })}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</TBody>
|
||||
</Table>
|
||||
{Boolean(filteredGroupMemberships.length) && (
|
||||
<Pagination
|
||||
count={filteredGroupMemberships.length}
|
||||
page={page}
|
||||
perPage={perPage}
|
||||
onChangePage={setPage}
|
||||
onChangePerPage={handlePerPageChange}
|
||||
/>
|
||||
)}
|
||||
{!isPending && !filteredGroupMemberships?.length && (
|
||||
<EmptyState
|
||||
title={
|
||||
groupMemberships?.users.length
|
||||
? "No users match this search..."
|
||||
: "This group does not have any members yet"
|
||||
}
|
||||
icon={groupMemberships?.users.length ? faSearch : faFolder}
|
||||
/>
|
||||
)}
|
||||
</TableContainer>
|
||||
<ConfirmActionModal
|
||||
isOpen={popUp.assumePrivileges.isOpen}
|
||||
confirmKey="assume"
|
||||
title="Do you want to assume privileges of this user?"
|
||||
subTitle="This will set your privileges to those of the user for the next hour."
|
||||
onChange={(isOpen) => handlePopUpToggle("assumePrivileges", isOpen)}
|
||||
onConfirmed={handleAssumePrivileges}
|
||||
buttonText="Confirm"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,76 +0,0 @@
|
||||
import { faEllipsisV, faUser } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
IconButton,
|
||||
Td,
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionMemberActions, ProjectPermissionSub } from "@app/context";
|
||||
import { TGroupUser } from "@app/hooks/api/groups/types";
|
||||
|
||||
type Props = {
|
||||
user: TGroupUser;
|
||||
onAssumePrivileges: (userId: string) => void;
|
||||
};
|
||||
|
||||
export const GroupMembershipRow = ({
|
||||
user: { firstName, lastName, joinedGroupAt, email, id },
|
||||
onAssumePrivileges
|
||||
}: Props) => {
|
||||
return (
|
||||
<Tr className="items-center" key={`group-user-${id}`}>
|
||||
<Td>
|
||||
<p>{`${firstName ?? "-"} ${lastName ?? ""}`}</p>
|
||||
</Td>
|
||||
<Td>
|
||||
<p>{email}</p>
|
||||
</Td>
|
||||
<Td>
|
||||
<Tooltip content={new Date(joinedGroupAt).toLocaleString()}>
|
||||
<p>{new Date(joinedGroupAt).toLocaleDateString()}</p>
|
||||
</Tooltip>
|
||||
</Td>
|
||||
<Td>
|
||||
<Tooltip className="max-w-sm text-center" content="Options">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<IconButton
|
||||
ariaLabel="Options"
|
||||
colorSchema="secondary"
|
||||
className="w-6"
|
||||
variant="plain"
|
||||
>
|
||||
<FontAwesomeIcon icon={faEllipsisV} />
|
||||
</IconButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent sideOffset={2} align="end">
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionMemberActions.AssumePrivileges}
|
||||
a={ProjectPermissionSub.Member}
|
||||
>
|
||||
{(isAllowed) => {
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
icon={<FontAwesomeIcon icon={faUser} />}
|
||||
onClick={() => onAssumePrivileges(id)}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Assume Privileges
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
}}
|
||||
</ProjectPermissionCan>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</Tooltip>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
};
|
@ -1 +0,0 @@
|
||||
export { GroupMembersSection } from "./GroupMembersSection";
|
@ -1 +0,0 @@
|
||||
export { GroupDetailsSection } from "./GroupDetailsSection";
|
@ -1,28 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { GroupDetailsByIDPage } from "./GroupDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/groups/$groupId"
|
||||
)({
|
||||
component: GroupDetailsByIDPage,
|
||||
beforeLoad: ({ context, params }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "Access Control",
|
||||
link: linkOptions({
|
||||
to: "/cert-manager/$projectId/access-management",
|
||||
params: {
|
||||
projectId: params.projectId
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
label: "Groups"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
@ -1,28 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { GroupDetailsByIDPage } from "./GroupDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/groups/$groupId"
|
||||
)({
|
||||
component: GroupDetailsByIDPage,
|
||||
beforeLoad: ({ context, params }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "Access Control",
|
||||
link: linkOptions({
|
||||
to: "/kms/$projectId/access-management",
|
||||
params: {
|
||||
projectId: params.projectId
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
label: "Groups"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
@ -1,28 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { GroupDetailsByIDPage } from "./GroupDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/groups/$groupId"
|
||||
)({
|
||||
component: GroupDetailsByIDPage,
|
||||
beforeLoad: ({ context, params }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "Access Control",
|
||||
link: linkOptions({
|
||||
to: "/secret-manager/$projectId/access-management",
|
||||
params: {
|
||||
projectId: params.projectId
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
label: "Groups"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
@ -1,28 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { GroupDetailsByIDPage } from "./GroupDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/groups/$groupId"
|
||||
)({
|
||||
component: GroupDetailsByIDPage,
|
||||
beforeLoad: ({ context, params }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "Access Control",
|
||||
link: linkOptions({
|
||||
to: "/secret-scanning/$projectId/access-management",
|
||||
params: {
|
||||
projectId: params.projectId
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
label: "Groups"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
@ -1,28 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { GroupDetailsByIDPage } from "./GroupDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/groups/$groupId"
|
||||
)({
|
||||
component: GroupDetailsByIDPage,
|
||||
beforeLoad: ({ context, params }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "Access Control",
|
||||
link: linkOptions({
|
||||
to: "/ssh/$projectId/access-management",
|
||||
params: {
|
||||
projectId: params.projectId
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
label: "Groups"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
@ -1,27 +0,0 @@
|
||||
import { faHome } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { GroupDetailsByIDPage } from "./GroupDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId"
|
||||
)({
|
||||
component: GroupDetailsByIDPage,
|
||||
context: () => ({
|
||||
breadcrumbs: [
|
||||
{
|
||||
label: "Home",
|
||||
icon: () => <FontAwesomeIcon icon={faHome} />,
|
||||
link: linkOptions({ to: "/organization/secret-manager/overview" })
|
||||
},
|
||||
{
|
||||
label: "Access Control",
|
||||
link: linkOptions({ to: "/organization/access-management" })
|
||||
},
|
||||
{
|
||||
label: "groups"
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
@ -115,24 +115,19 @@ import { Route as certManagerAlertingPageRouteImport } from './pages/cert-manage
|
||||
import { Route as projectRoleDetailsBySlugPageRouteSshImport } from './pages/project/RoleDetailsBySlugPage/route-ssh'
|
||||
import { Route as projectMemberDetailsByIDPageRouteSshImport } from './pages/project/MemberDetailsByIDPage/route-ssh'
|
||||
import { Route as projectIdentityDetailsByIDPageRouteSshImport } from './pages/project/IdentityDetailsByIDPage/route-ssh'
|
||||
import { Route as projectGroupDetailsByIDPageRouteSshImport } from './pages/project/GroupDetailsByIDPage/route-ssh'
|
||||
import { Route as projectRoleDetailsBySlugPageRouteSecretScanningImport } from './pages/project/RoleDetailsBySlugPage/route-secret-scanning'
|
||||
import { Route as projectMemberDetailsByIDPageRouteSecretScanningImport } from './pages/project/MemberDetailsByIDPage/route-secret-scanning'
|
||||
import { Route as projectIdentityDetailsByIDPageRouteSecretScanningImport } from './pages/project/IdentityDetailsByIDPage/route-secret-scanning'
|
||||
import { Route as projectGroupDetailsByIDPageRouteSecretScanningImport } from './pages/project/GroupDetailsByIDPage/route-secret-scanning'
|
||||
import { Route as projectRoleDetailsBySlugPageRouteSecretManagerImport } from './pages/project/RoleDetailsBySlugPage/route-secret-manager'
|
||||
import { Route as projectMemberDetailsByIDPageRouteSecretManagerImport } from './pages/project/MemberDetailsByIDPage/route-secret-manager'
|
||||
import { Route as projectIdentityDetailsByIDPageRouteSecretManagerImport } from './pages/project/IdentityDetailsByIDPage/route-secret-manager'
|
||||
import { Route as projectGroupDetailsByIDPageRouteSecretManagerImport } from './pages/project/GroupDetailsByIDPage/route-secret-manager'
|
||||
import { Route as projectRoleDetailsBySlugPageRouteKmsImport } from './pages/project/RoleDetailsBySlugPage/route-kms'
|
||||
import { Route as projectMemberDetailsByIDPageRouteKmsImport } from './pages/project/MemberDetailsByIDPage/route-kms'
|
||||
import { Route as projectIdentityDetailsByIDPageRouteKmsImport } from './pages/project/IdentityDetailsByIDPage/route-kms'
|
||||
import { Route as projectGroupDetailsByIDPageRouteKmsImport } from './pages/project/GroupDetailsByIDPage/route-kms'
|
||||
import { Route as projectRoleDetailsBySlugPageRouteCertManagerImport } from './pages/project/RoleDetailsBySlugPage/route-cert-manager'
|
||||
import { Route as certManagerPkiCollectionDetailsByIDPageRoutesImport } from './pages/cert-manager/PkiCollectionDetailsByIDPage/routes'
|
||||
import { Route as projectMemberDetailsByIDPageRouteCertManagerImport } from './pages/project/MemberDetailsByIDPage/route-cert-manager'
|
||||
import { Route as projectIdentityDetailsByIDPageRouteCertManagerImport } from './pages/project/IdentityDetailsByIDPage/route-cert-manager'
|
||||
import { Route as projectGroupDetailsByIDPageRouteCertManagerImport } from './pages/project/GroupDetailsByIDPage/route-cert-manager'
|
||||
import { Route as sshSshHostGroupDetailsByIDPageRouteImport } from './pages/ssh/SshHostGroupDetailsByIDPage/route'
|
||||
import { Route as sshSshCaByIDPageRouteImport } from './pages/ssh/SshCaByIDPage/route'
|
||||
import { Route as secretManagerSecretDashboardPageRouteImport } from './pages/secret-manager/SecretDashboardPage/route'
|
||||
@ -1154,13 +1149,6 @@ const projectIdentityDetailsByIDPageRouteSshRoute =
|
||||
getParentRoute: () => sshLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectGroupDetailsByIDPageRouteSshRoute =
|
||||
projectGroupDetailsByIDPageRouteSshImport.update({
|
||||
id: '/groups/$groupId',
|
||||
path: '/groups/$groupId',
|
||||
getParentRoute: () => sshLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectRoleDetailsBySlugPageRouteSecretScanningRoute =
|
||||
projectRoleDetailsBySlugPageRouteSecretScanningImport.update({
|
||||
id: '/roles/$roleSlug',
|
||||
@ -1182,13 +1170,6 @@ const projectIdentityDetailsByIDPageRouteSecretScanningRoute =
|
||||
getParentRoute: () => secretScanningLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectGroupDetailsByIDPageRouteSecretScanningRoute =
|
||||
projectGroupDetailsByIDPageRouteSecretScanningImport.update({
|
||||
id: '/groups/$groupId',
|
||||
path: '/groups/$groupId',
|
||||
getParentRoute: () => secretScanningLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectRoleDetailsBySlugPageRouteSecretManagerRoute =
|
||||
projectRoleDetailsBySlugPageRouteSecretManagerImport.update({
|
||||
id: '/roles/$roleSlug',
|
||||
@ -1210,13 +1191,6 @@ const projectIdentityDetailsByIDPageRouteSecretManagerRoute =
|
||||
getParentRoute: () => secretManagerLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectGroupDetailsByIDPageRouteSecretManagerRoute =
|
||||
projectGroupDetailsByIDPageRouteSecretManagerImport.update({
|
||||
id: '/groups/$groupId',
|
||||
path: '/groups/$groupId',
|
||||
getParentRoute: () => secretManagerLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectRoleDetailsBySlugPageRouteKmsRoute =
|
||||
projectRoleDetailsBySlugPageRouteKmsImport.update({
|
||||
id: '/roles/$roleSlug',
|
||||
@ -1238,13 +1212,6 @@ const projectIdentityDetailsByIDPageRouteKmsRoute =
|
||||
getParentRoute: () => kmsLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectGroupDetailsByIDPageRouteKmsRoute =
|
||||
projectGroupDetailsByIDPageRouteKmsImport.update({
|
||||
id: '/groups/$groupId',
|
||||
path: '/groups/$groupId',
|
||||
getParentRoute: () => kmsLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectRoleDetailsBySlugPageRouteCertManagerRoute =
|
||||
projectRoleDetailsBySlugPageRouteCertManagerImport.update({
|
||||
id: '/roles/$roleSlug',
|
||||
@ -1273,13 +1240,6 @@ const projectIdentityDetailsByIDPageRouteCertManagerRoute =
|
||||
getParentRoute: () => certManagerLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const projectGroupDetailsByIDPageRouteCertManagerRoute =
|
||||
projectGroupDetailsByIDPageRouteCertManagerImport.update({
|
||||
id: '/groups/$groupId',
|
||||
path: '/groups/$groupId',
|
||||
getParentRoute: () => certManagerLayoutRoute,
|
||||
} as any)
|
||||
|
||||
const sshSshHostGroupDetailsByIDPageRouteRoute =
|
||||
sshSshHostGroupDetailsByIDPageRouteImport.update({
|
||||
id: '/ssh-host-groups/$sshHostGroupId',
|
||||
@ -2901,13 +2861,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof sshSshHostGroupDetailsByIDPageRouteImport
|
||||
parentRoute: typeof sshLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/groups/$groupId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/groups/$groupId'
|
||||
path: '/groups/$groupId'
|
||||
fullPath: '/cert-manager/$projectId/groups/$groupId'
|
||||
preLoaderRoute: typeof projectGroupDetailsByIDPageRouteCertManagerImport
|
||||
parentRoute: typeof certManagerLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/identities/$identityId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/identities/$identityId'
|
||||
path: '/identities/$identityId'
|
||||
@ -2936,13 +2889,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof projectRoleDetailsBySlugPageRouteCertManagerImport
|
||||
parentRoute: typeof certManagerLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/groups/$groupId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/groups/$groupId'
|
||||
path: '/groups/$groupId'
|
||||
fullPath: '/kms/$projectId/groups/$groupId'
|
||||
preLoaderRoute: typeof projectGroupDetailsByIDPageRouteKmsImport
|
||||
parentRoute: typeof kmsLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/identities/$identityId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/identities/$identityId'
|
||||
path: '/identities/$identityId'
|
||||
@ -2964,13 +2910,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof projectRoleDetailsBySlugPageRouteKmsImport
|
||||
parentRoute: typeof kmsLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/groups/$groupId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/groups/$groupId'
|
||||
path: '/groups/$groupId'
|
||||
fullPath: '/secret-manager/$projectId/groups/$groupId'
|
||||
preLoaderRoute: typeof projectGroupDetailsByIDPageRouteSecretManagerImport
|
||||
parentRoute: typeof secretManagerLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/identities/$identityId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/identities/$identityId'
|
||||
path: '/identities/$identityId'
|
||||
@ -2992,13 +2931,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof projectRoleDetailsBySlugPageRouteSecretManagerImport
|
||||
parentRoute: typeof secretManagerLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/groups/$groupId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/groups/$groupId'
|
||||
path: '/groups/$groupId'
|
||||
fullPath: '/secret-scanning/$projectId/groups/$groupId'
|
||||
preLoaderRoute: typeof projectGroupDetailsByIDPageRouteSecretScanningImport
|
||||
parentRoute: typeof secretScanningLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/identities/$identityId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/identities/$identityId'
|
||||
path: '/identities/$identityId'
|
||||
@ -3020,13 +2952,6 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof projectRoleDetailsBySlugPageRouteSecretScanningImport
|
||||
parentRoute: typeof secretScanningLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/groups/$groupId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/groups/$groupId'
|
||||
path: '/groups/$groupId'
|
||||
fullPath: '/ssh/$projectId/groups/$groupId'
|
||||
preLoaderRoute: typeof projectGroupDetailsByIDPageRouteSshImport
|
||||
parentRoute: typeof sshLayoutImport
|
||||
}
|
||||
'/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/identities/$identityId': {
|
||||
id: '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/identities/$identityId'
|
||||
path: '/identities/$identityId'
|
||||
@ -3810,7 +3735,6 @@ interface certManagerLayoutRouteChildren {
|
||||
AuthenticateInjectOrgDetailsOrgLayoutCertManagerProjectIdCertManagerLayoutCertificateTemplatesRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutCertManagerProjectIdCertManagerLayoutCertificateTemplatesRouteWithChildren
|
||||
AuthenticateInjectOrgDetailsOrgLayoutCertManagerProjectIdCertManagerLayoutSubscribersRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutCertManagerProjectIdCertManagerLayoutSubscribersRouteWithChildren
|
||||
certManagerCertAuthDetailsByIDPageRouteRoute: typeof certManagerCertAuthDetailsByIDPageRouteRoute
|
||||
projectGroupDetailsByIDPageRouteCertManagerRoute: typeof projectGroupDetailsByIDPageRouteCertManagerRoute
|
||||
projectIdentityDetailsByIDPageRouteCertManagerRoute: typeof projectIdentityDetailsByIDPageRouteCertManagerRoute
|
||||
projectMemberDetailsByIDPageRouteCertManagerRoute: typeof projectMemberDetailsByIDPageRouteCertManagerRoute
|
||||
certManagerPkiCollectionDetailsByIDPageRoutesRoute: typeof certManagerPkiCollectionDetailsByIDPageRoutesRoute
|
||||
@ -3831,8 +3755,6 @@ const certManagerLayoutRouteChildren: certManagerLayoutRouteChildren = {
|
||||
AuthenticateInjectOrgDetailsOrgLayoutCertManagerProjectIdCertManagerLayoutSubscribersRouteWithChildren,
|
||||
certManagerCertAuthDetailsByIDPageRouteRoute:
|
||||
certManagerCertAuthDetailsByIDPageRouteRoute,
|
||||
projectGroupDetailsByIDPageRouteCertManagerRoute:
|
||||
projectGroupDetailsByIDPageRouteCertManagerRoute,
|
||||
projectIdentityDetailsByIDPageRouteCertManagerRoute:
|
||||
projectIdentityDetailsByIDPageRouteCertManagerRoute,
|
||||
projectMemberDetailsByIDPageRouteCertManagerRoute:
|
||||
@ -3865,7 +3787,6 @@ interface kmsLayoutRouteChildren {
|
||||
kmsOverviewPageRouteRoute: typeof kmsOverviewPageRouteRoute
|
||||
kmsSettingsPageRouteRoute: typeof kmsSettingsPageRouteRoute
|
||||
projectAccessControlPageRouteKmsRoute: typeof projectAccessControlPageRouteKmsRoute
|
||||
projectGroupDetailsByIDPageRouteKmsRoute: typeof projectGroupDetailsByIDPageRouteKmsRoute
|
||||
projectIdentityDetailsByIDPageRouteKmsRoute: typeof projectIdentityDetailsByIDPageRouteKmsRoute
|
||||
projectMemberDetailsByIDPageRouteKmsRoute: typeof projectMemberDetailsByIDPageRouteKmsRoute
|
||||
projectRoleDetailsBySlugPageRouteKmsRoute: typeof projectRoleDetailsBySlugPageRouteKmsRoute
|
||||
@ -3876,8 +3797,6 @@ const kmsLayoutRouteChildren: kmsLayoutRouteChildren = {
|
||||
kmsOverviewPageRouteRoute: kmsOverviewPageRouteRoute,
|
||||
kmsSettingsPageRouteRoute: kmsSettingsPageRouteRoute,
|
||||
projectAccessControlPageRouteKmsRoute: projectAccessControlPageRouteKmsRoute,
|
||||
projectGroupDetailsByIDPageRouteKmsRoute:
|
||||
projectGroupDetailsByIDPageRouteKmsRoute,
|
||||
projectIdentityDetailsByIDPageRouteKmsRoute:
|
||||
projectIdentityDetailsByIDPageRouteKmsRoute,
|
||||
projectMemberDetailsByIDPageRouteKmsRoute:
|
||||
@ -4159,7 +4078,6 @@ interface secretManagerLayoutRouteChildren {
|
||||
projectAccessControlPageRouteSecretManagerRoute: typeof projectAccessControlPageRouteSecretManagerRoute
|
||||
AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManagerLayoutIntegrationsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManagerLayoutIntegrationsRouteWithChildren
|
||||
secretManagerSecretDashboardPageRouteRoute: typeof secretManagerSecretDashboardPageRouteRoute
|
||||
projectGroupDetailsByIDPageRouteSecretManagerRoute: typeof projectGroupDetailsByIDPageRouteSecretManagerRoute
|
||||
projectIdentityDetailsByIDPageRouteSecretManagerRoute: typeof projectIdentityDetailsByIDPageRouteSecretManagerRoute
|
||||
projectMemberDetailsByIDPageRouteSecretManagerRoute: typeof projectMemberDetailsByIDPageRouteSecretManagerRoute
|
||||
projectRoleDetailsBySlugPageRouteSecretManagerRoute: typeof projectRoleDetailsBySlugPageRouteSecretManagerRoute
|
||||
@ -4180,8 +4098,6 @@ const secretManagerLayoutRouteChildren: secretManagerLayoutRouteChildren = {
|
||||
AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdSecretManagerLayoutIntegrationsRouteWithChildren,
|
||||
secretManagerSecretDashboardPageRouteRoute:
|
||||
secretManagerSecretDashboardPageRouteRoute,
|
||||
projectGroupDetailsByIDPageRouteSecretManagerRoute:
|
||||
projectGroupDetailsByIDPageRouteSecretManagerRoute,
|
||||
projectIdentityDetailsByIDPageRouteSecretManagerRoute:
|
||||
projectIdentityDetailsByIDPageRouteSecretManagerRoute,
|
||||
projectMemberDetailsByIDPageRouteSecretManagerRoute:
|
||||
@ -4230,7 +4146,6 @@ interface secretScanningLayoutRouteChildren {
|
||||
secretScanningSettingsPageRouteRoute: typeof secretScanningSettingsPageRouteRoute
|
||||
projectAccessControlPageRouteSecretScanningRoute: typeof projectAccessControlPageRouteSecretScanningRoute
|
||||
AuthenticateInjectOrgDetailsOrgLayoutSecretScanningProjectIdSecretScanningLayoutDataSourcesRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutSecretScanningProjectIdSecretScanningLayoutDataSourcesRouteWithChildren
|
||||
projectGroupDetailsByIDPageRouteSecretScanningRoute: typeof projectGroupDetailsByIDPageRouteSecretScanningRoute
|
||||
projectIdentityDetailsByIDPageRouteSecretScanningRoute: typeof projectIdentityDetailsByIDPageRouteSecretScanningRoute
|
||||
projectMemberDetailsByIDPageRouteSecretScanningRoute: typeof projectMemberDetailsByIDPageRouteSecretScanningRoute
|
||||
projectRoleDetailsBySlugPageRouteSecretScanningRoute: typeof projectRoleDetailsBySlugPageRouteSecretScanningRoute
|
||||
@ -4244,8 +4159,6 @@ const secretScanningLayoutRouteChildren: secretScanningLayoutRouteChildren = {
|
||||
projectAccessControlPageRouteSecretScanningRoute,
|
||||
AuthenticateInjectOrgDetailsOrgLayoutSecretScanningProjectIdSecretScanningLayoutDataSourcesRoute:
|
||||
AuthenticateInjectOrgDetailsOrgLayoutSecretScanningProjectIdSecretScanningLayoutDataSourcesRouteWithChildren,
|
||||
projectGroupDetailsByIDPageRouteSecretScanningRoute:
|
||||
projectGroupDetailsByIDPageRouteSecretScanningRoute,
|
||||
projectIdentityDetailsByIDPageRouteSecretScanningRoute:
|
||||
projectIdentityDetailsByIDPageRouteSecretScanningRoute,
|
||||
projectMemberDetailsByIDPageRouteSecretScanningRoute:
|
||||
@ -4279,7 +4192,6 @@ interface sshLayoutRouteChildren {
|
||||
projectAccessControlPageRouteSshRoute: typeof projectAccessControlPageRouteSshRoute
|
||||
sshSshCaByIDPageRouteRoute: typeof sshSshCaByIDPageRouteRoute
|
||||
sshSshHostGroupDetailsByIDPageRouteRoute: typeof sshSshHostGroupDetailsByIDPageRouteRoute
|
||||
projectGroupDetailsByIDPageRouteSshRoute: typeof projectGroupDetailsByIDPageRouteSshRoute
|
||||
projectIdentityDetailsByIDPageRouteSshRoute: typeof projectIdentityDetailsByIDPageRouteSshRoute
|
||||
projectMemberDetailsByIDPageRouteSshRoute: typeof projectMemberDetailsByIDPageRouteSshRoute
|
||||
projectRoleDetailsBySlugPageRouteSshRoute: typeof projectRoleDetailsBySlugPageRouteSshRoute
|
||||
@ -4294,8 +4206,6 @@ const sshLayoutRouteChildren: sshLayoutRouteChildren = {
|
||||
sshSshCaByIDPageRouteRoute: sshSshCaByIDPageRouteRoute,
|
||||
sshSshHostGroupDetailsByIDPageRouteRoute:
|
||||
sshSshHostGroupDetailsByIDPageRouteRoute,
|
||||
projectGroupDetailsByIDPageRouteSshRoute:
|
||||
projectGroupDetailsByIDPageRouteSshRoute,
|
||||
projectIdentityDetailsByIDPageRouteSshRoute:
|
||||
projectIdentityDetailsByIDPageRouteSshRoute,
|
||||
projectMemberDetailsByIDPageRouteSshRoute:
|
||||
@ -4651,24 +4561,19 @@ export interface FileRoutesByFullPath {
|
||||
'/secret-manager/$projectId/secrets/$envSlug': typeof secretManagerSecretDashboardPageRouteRoute
|
||||
'/ssh/$projectId/ca/$caId': typeof sshSshCaByIDPageRouteRoute
|
||||
'/ssh/$projectId/ssh-host-groups/$sshHostGroupId': typeof sshSshHostGroupDetailsByIDPageRouteRoute
|
||||
'/cert-manager/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteCertManagerRoute
|
||||
'/cert-manager/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteCertManagerRoute
|
||||
'/cert-manager/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteCertManagerRoute
|
||||
'/cert-manager/$projectId/pki-collections/$collectionId': typeof certManagerPkiCollectionDetailsByIDPageRoutesRoute
|
||||
'/cert-manager/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteCertManagerRoute
|
||||
'/kms/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteKmsRoute
|
||||
'/kms/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteKmsRoute
|
||||
'/kms/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteKmsRoute
|
||||
'/kms/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteKmsRoute
|
||||
'/secret-manager/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSecretManagerRoute
|
||||
'/secret-manager/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSecretManagerRoute
|
||||
'/secret-manager/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSecretManagerRoute
|
||||
'/secret-manager/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSecretManagerRoute
|
||||
'/secret-scanning/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSecretScanningRoute
|
||||
'/secret-scanning/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSecretScanningRoute
|
||||
'/secret-scanning/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSecretScanningRoute
|
||||
'/secret-scanning/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSecretScanningRoute
|
||||
'/ssh/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSshRoute
|
||||
'/ssh/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSshRoute
|
||||
'/ssh/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSshRoute
|
||||
'/ssh/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSshRoute
|
||||
@ -4859,24 +4764,19 @@ export interface FileRoutesByTo {
|
||||
'/secret-manager/$projectId/secrets/$envSlug': typeof secretManagerSecretDashboardPageRouteRoute
|
||||
'/ssh/$projectId/ca/$caId': typeof sshSshCaByIDPageRouteRoute
|
||||
'/ssh/$projectId/ssh-host-groups/$sshHostGroupId': typeof sshSshHostGroupDetailsByIDPageRouteRoute
|
||||
'/cert-manager/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteCertManagerRoute
|
||||
'/cert-manager/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteCertManagerRoute
|
||||
'/cert-manager/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteCertManagerRoute
|
||||
'/cert-manager/$projectId/pki-collections/$collectionId': typeof certManagerPkiCollectionDetailsByIDPageRoutesRoute
|
||||
'/cert-manager/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteCertManagerRoute
|
||||
'/kms/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteKmsRoute
|
||||
'/kms/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteKmsRoute
|
||||
'/kms/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteKmsRoute
|
||||
'/kms/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteKmsRoute
|
||||
'/secret-manager/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSecretManagerRoute
|
||||
'/secret-manager/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSecretManagerRoute
|
||||
'/secret-manager/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSecretManagerRoute
|
||||
'/secret-manager/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSecretManagerRoute
|
||||
'/secret-scanning/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSecretScanningRoute
|
||||
'/secret-scanning/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSecretScanningRoute
|
||||
'/secret-scanning/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSecretScanningRoute
|
||||
'/secret-scanning/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSecretScanningRoute
|
||||
'/ssh/$projectId/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSshRoute
|
||||
'/ssh/$projectId/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSshRoute
|
||||
'/ssh/$projectId/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSshRoute
|
||||
'/ssh/$projectId/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSshRoute
|
||||
@ -5090,24 +4990,19 @@ export interface FileRoutesById {
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/secrets/$envSlug': typeof secretManagerSecretDashboardPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/ca/$caId': typeof sshSshCaByIDPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/ssh-host-groups/$sshHostGroupId': typeof sshSshHostGroupDetailsByIDPageRouteRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/groups/$groupId': typeof projectGroupDetailsByIDPageRouteCertManagerRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteCertManagerRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/members/$membershipId': typeof projectMemberDetailsByIDPageRouteCertManagerRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/pki-collections/$collectionId': typeof certManagerPkiCollectionDetailsByIDPageRoutesRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteCertManagerRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/groups/$groupId': typeof projectGroupDetailsByIDPageRouteKmsRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteKmsRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/members/$membershipId': typeof projectMemberDetailsByIDPageRouteKmsRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteKmsRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSecretManagerRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSecretManagerRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSecretManagerRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSecretManagerRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSecretScanningRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSecretScanningRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSecretScanningRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSecretScanningRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/groups/$groupId': typeof projectGroupDetailsByIDPageRouteSshRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/identities/$identityId': typeof projectIdentityDetailsByIDPageRouteSshRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/members/$membershipId': typeof projectMemberDetailsByIDPageRouteSshRoute
|
||||
'/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/roles/$roleSlug': typeof projectRoleDetailsBySlugPageRouteSshRoute
|
||||
@ -5312,24 +5207,19 @@ export interface FileRouteTypes {
|
||||
| '/secret-manager/$projectId/secrets/$envSlug'
|
||||
| '/ssh/$projectId/ca/$caId'
|
||||
| '/ssh/$projectId/ssh-host-groups/$sshHostGroupId'
|
||||
| '/cert-manager/$projectId/groups/$groupId'
|
||||
| '/cert-manager/$projectId/identities/$identityId'
|
||||
| '/cert-manager/$projectId/members/$membershipId'
|
||||
| '/cert-manager/$projectId/pki-collections/$collectionId'
|
||||
| '/cert-manager/$projectId/roles/$roleSlug'
|
||||
| '/kms/$projectId/groups/$groupId'
|
||||
| '/kms/$projectId/identities/$identityId'
|
||||
| '/kms/$projectId/members/$membershipId'
|
||||
| '/kms/$projectId/roles/$roleSlug'
|
||||
| '/secret-manager/$projectId/groups/$groupId'
|
||||
| '/secret-manager/$projectId/identities/$identityId'
|
||||
| '/secret-manager/$projectId/members/$membershipId'
|
||||
| '/secret-manager/$projectId/roles/$roleSlug'
|
||||
| '/secret-scanning/$projectId/groups/$groupId'
|
||||
| '/secret-scanning/$projectId/identities/$identityId'
|
||||
| '/secret-scanning/$projectId/members/$membershipId'
|
||||
| '/secret-scanning/$projectId/roles/$roleSlug'
|
||||
| '/ssh/$projectId/groups/$groupId'
|
||||
| '/ssh/$projectId/identities/$identityId'
|
||||
| '/ssh/$projectId/members/$membershipId'
|
||||
| '/ssh/$projectId/roles/$roleSlug'
|
||||
@ -5519,24 +5409,19 @@ export interface FileRouteTypes {
|
||||
| '/secret-manager/$projectId/secrets/$envSlug'
|
||||
| '/ssh/$projectId/ca/$caId'
|
||||
| '/ssh/$projectId/ssh-host-groups/$sshHostGroupId'
|
||||
| '/cert-manager/$projectId/groups/$groupId'
|
||||
| '/cert-manager/$projectId/identities/$identityId'
|
||||
| '/cert-manager/$projectId/members/$membershipId'
|
||||
| '/cert-manager/$projectId/pki-collections/$collectionId'
|
||||
| '/cert-manager/$projectId/roles/$roleSlug'
|
||||
| '/kms/$projectId/groups/$groupId'
|
||||
| '/kms/$projectId/identities/$identityId'
|
||||
| '/kms/$projectId/members/$membershipId'
|
||||
| '/kms/$projectId/roles/$roleSlug'
|
||||
| '/secret-manager/$projectId/groups/$groupId'
|
||||
| '/secret-manager/$projectId/identities/$identityId'
|
||||
| '/secret-manager/$projectId/members/$membershipId'
|
||||
| '/secret-manager/$projectId/roles/$roleSlug'
|
||||
| '/secret-scanning/$projectId/groups/$groupId'
|
||||
| '/secret-scanning/$projectId/identities/$identityId'
|
||||
| '/secret-scanning/$projectId/members/$membershipId'
|
||||
| '/secret-scanning/$projectId/roles/$roleSlug'
|
||||
| '/ssh/$projectId/groups/$groupId'
|
||||
| '/ssh/$projectId/identities/$identityId'
|
||||
| '/ssh/$projectId/members/$membershipId'
|
||||
| '/ssh/$projectId/roles/$roleSlug'
|
||||
@ -5748,24 +5633,19 @@ export interface FileRouteTypes {
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/secrets/$envSlug'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/ca/$caId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/ssh-host-groups/$sshHostGroupId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/groups/$groupId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/identities/$identityId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/members/$membershipId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/pki-collections/$collectionId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/roles/$roleSlug'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/groups/$groupId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/identities/$identityId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/members/$membershipId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/roles/$roleSlug'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/groups/$groupId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/identities/$identityId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/members/$membershipId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/roles/$roleSlug'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/groups/$groupId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/identities/$identityId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/members/$membershipId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/roles/$roleSlug'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/groups/$groupId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/identities/$identityId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/members/$membershipId'
|
||||
| '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/roles/$roleSlug'
|
||||
@ -6326,7 +6206,6 @@ export const routeTree = rootRoute
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-templates",
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/subscribers",
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/ca/$caName",
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/groups/$groupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/identities/$identityId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/members/$membershipId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/pki-collections/$collectionId",
|
||||
@ -6341,7 +6220,6 @@ export const routeTree = rootRoute
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/overview",
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/settings",
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/access-management",
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/groups/$groupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/identities/$identityId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/members/$membershipId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/roles/$roleSlug"
|
||||
@ -6359,7 +6237,6 @@ export const routeTree = rootRoute
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/access-management",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/integrations",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/secrets/$envSlug",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/groups/$groupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/identities/$identityId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/members/$membershipId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/roles/$roleSlug"
|
||||
@ -6373,7 +6250,6 @@ export const routeTree = rootRoute
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/settings",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/access-management",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/data-sources",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/groups/$groupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/identities/$identityId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/members/$membershipId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/roles/$roleSlug"
|
||||
@ -6390,7 +6266,6 @@ export const routeTree = rootRoute
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/access-management",
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/ca/$caId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/ssh-host-groups/$sshHostGroupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/groups/$groupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/identities/$identityId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/members/$membershipId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/roles/$roleSlug"
|
||||
@ -6683,10 +6558,6 @@ export const routeTree = rootRoute
|
||||
"filePath": "ssh/SshHostGroupDetailsByIDPage/route.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/groups/$groupId": {
|
||||
"filePath": "project/GroupDetailsByIDPage/route-cert-manager.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/identities/$identityId": {
|
||||
"filePath": "project/IdentityDetailsByIDPage/route-cert-manager.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout"
|
||||
@ -6703,10 +6574,6 @@ export const routeTree = rootRoute
|
||||
"filePath": "project/RoleDetailsBySlugPage/route-cert-manager.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/groups/$groupId": {
|
||||
"filePath": "project/GroupDetailsByIDPage/route-kms.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/identities/$identityId": {
|
||||
"filePath": "project/IdentityDetailsByIDPage/route-kms.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout"
|
||||
@ -6719,10 +6586,6 @@ export const routeTree = rootRoute
|
||||
"filePath": "project/RoleDetailsBySlugPage/route-kms.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/groups/$groupId": {
|
||||
"filePath": "project/GroupDetailsByIDPage/route-secret-manager.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout/identities/$identityId": {
|
||||
"filePath": "project/IdentityDetailsByIDPage/route-secret-manager.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout"
|
||||
@ -6735,10 +6598,6 @@ export const routeTree = rootRoute
|
||||
"filePath": "project/RoleDetailsBySlugPage/route-secret-manager.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/groups/$groupId": {
|
||||
"filePath": "project/GroupDetailsByIDPage/route-secret-scanning.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout/identities/$identityId": {
|
||||
"filePath": "project/IdentityDetailsByIDPage/route-secret-scanning.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout"
|
||||
@ -6751,10 +6610,6 @@ export const routeTree = rootRoute
|
||||
"filePath": "project/RoleDetailsBySlugPage/route-secret-scanning.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/secret-scanning/$projectId/_secret-scanning-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/groups/$groupId": {
|
||||
"filePath": "project/GroupDetailsByIDPage/route-ssh.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout"
|
||||
},
|
||||
"/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/identities/$identityId": {
|
||||
"filePath": "project/IdentityDetailsByIDPage/route-ssh.tsx",
|
||||
"parent": "/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout"
|
||||
|
@ -270,8 +270,7 @@ const secretManagerRoutes = route("/secret-manager/$projectId", [
|
||||
route("/access-management", "project/AccessControlPage/route-secret-manager.tsx"),
|
||||
route("/roles/$roleSlug", "project/RoleDetailsBySlugPage/route-secret-manager.tsx"),
|
||||
route("/identities/$identityId", "project/IdentityDetailsByIDPage/route-secret-manager.tsx"),
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-secret-manager.tsx"),
|
||||
route("/groups/$groupId", "project/GroupDetailsByIDPage/route-secret-manager.tsx")
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-secret-manager.tsx")
|
||||
])
|
||||
]);
|
||||
|
||||
@ -315,8 +314,7 @@ const certManagerRoutes = route("/cert-manager/$projectId", [
|
||||
route("/access-management", "project/AccessControlPage/route-cert-manager.tsx"),
|
||||
route("/roles/$roleSlug", "project/RoleDetailsBySlugPage/route-cert-manager.tsx"),
|
||||
route("/identities/$identityId", "project/IdentityDetailsByIDPage/route-cert-manager.tsx"),
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-cert-manager.tsx"),
|
||||
route("/groups/$groupId", "project/GroupDetailsByIDPage/route-cert-manager.tsx")
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-cert-manager.tsx")
|
||||
])
|
||||
]);
|
||||
|
||||
@ -328,8 +326,7 @@ const kmsRoutes = route("/kms/$projectId", [
|
||||
route("/access-management", "project/AccessControlPage/route-kms.tsx"),
|
||||
route("/roles/$roleSlug", "project/RoleDetailsBySlugPage/route-kms.tsx"),
|
||||
route("/identities/$identityId", "project/IdentityDetailsByIDPage/route-kms.tsx"),
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-kms.tsx"),
|
||||
route("/groups/$groupId", "project/GroupDetailsByIDPage/route-kms.tsx")
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-kms.tsx")
|
||||
])
|
||||
]);
|
||||
|
||||
@ -344,8 +341,7 @@ const sshRoutes = route("/ssh/$projectId", [
|
||||
route("/access-management", "project/AccessControlPage/route-ssh.tsx"),
|
||||
route("/roles/$roleSlug", "project/RoleDetailsBySlugPage/route-ssh.tsx"),
|
||||
route("/identities/$identityId", "project/IdentityDetailsByIDPage/route-ssh.tsx"),
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-ssh.tsx"),
|
||||
route("/groups/$groupId", "project/GroupDetailsByIDPage/route-ssh.tsx")
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-ssh.tsx")
|
||||
])
|
||||
]);
|
||||
|
||||
@ -360,8 +356,7 @@ const secretScanningRoutes = route("/secret-scanning/$projectId", [
|
||||
route("/access-management", "project/AccessControlPage/route-secret-scanning.tsx"),
|
||||
route("/roles/$roleSlug", "project/RoleDetailsBySlugPage/route-secret-scanning.tsx"),
|
||||
route("/identities/$identityId", "project/IdentityDetailsByIDPage/route-secret-scanning.tsx"),
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-secret-scanning.tsx"),
|
||||
route("/groups/$groupId", "project/GroupDetailsByIDPage/route-secret-scanning.tsx")
|
||||
route("/members/$membershipId", "project/MemberDetailsByIDPage/route-secret-scanning.tsx")
|
||||
])
|
||||
]);
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
## 0.0.3 (June 6, 2025)
|
||||
|
||||
* Minor fix for handling malformed URLs for HTTP forwarding
|
||||
|
||||
## 0.0.2 (June 6, 2025)
|
||||
|
||||
* Bumped default CLI image version from 0.41.1 -> 0.41.8.
|
||||
|
@ -15,10 +15,10 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.0.2
|
||||
version: 0.0.3
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "0.0.2"
|
||||
appVersion: "0.0.3"
|
||||
|
@ -1,6 +1,6 @@
|
||||
image:
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "0.41.8"
|
||||
tag: "0.41.82"
|
||||
|
||||
secret:
|
||||
# The secret that contains the environment variables to be used by the gateway, such as INFISICAL_API_URL and TOKEN
|
||||
|
Reference in New Issue
Block a user