Compare commits
13 Commits
79fabd5348
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ad8bb2d320 | |||
| b10c57bdb8 | |||
| 9304db2391 | |||
| 27f1ad5780 | |||
| 4e52544c79 | |||
| e6e1112060 | |||
| b5dd24b4c9 | |||
| f8d698ba42 | |||
| 86c7b0d46d | |||
| fd2931e59c | |||
| a5ebecc8b5 | |||
| 956c3ead0c | |||
| 0100def25a |
@@ -12,32 +12,44 @@ public class ClubService
|
|||||||
private readonly AppDbContext _context;
|
private readonly AppDbContext _context;
|
||||||
private readonly ITenantProvider _tenantProvider;
|
private readonly ITenantProvider _tenantProvider;
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
private readonly ILogger<ClubService> _logger;
|
||||||
|
|
||||||
public ClubService(
|
public ClubService(
|
||||||
AppDbContext context,
|
AppDbContext context,
|
||||||
ITenantProvider tenantProvider,
|
ITenantProvider tenantProvider,
|
||||||
IHttpContextAccessor httpContextAccessor)
|
IHttpContextAccessor httpContextAccessor,
|
||||||
|
ILogger<ClubService> logger)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_tenantProvider = tenantProvider;
|
_tenantProvider = tenantProvider;
|
||||||
_httpContextAccessor = httpContextAccessor;
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<ClubListDto>> GetMyClubsAsync()
|
public async Task<List<ClubListDto>> GetMyClubsAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var clubsClaim = _httpContextAccessor.HttpContext?.User.FindFirst("clubs")?.Value;
|
var clubsClaim = _httpContextAccessor.HttpContext?.User.FindFirst("clubs")?.Value;
|
||||||
|
_logger.LogInformation("GetMyClubsAsync: Clubs claim value: {ClubsClaim}", clubsClaim);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(clubsClaim))
|
if (string.IsNullOrEmpty(clubsClaim))
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning("GetMyClubsAsync: No clubs claim found for user");
|
||||||
return new List<ClubListDto>();
|
return new List<ClubListDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse UUIDs from comma-separated claim, filtering out non-UUID values (like role names)
|
||||||
var tenantIds = clubsClaim.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
var tenantIds = clubsClaim.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Select(t => t.Trim())
|
.Select(t => t.Trim())
|
||||||
.Where(t => !string.IsNullOrEmpty(t) && Guid.TryParse(t, out _))
|
.Where(t => !string.IsNullOrEmpty(t) && Guid.TryParse(t, out _))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
_logger.LogInformation("GetMyClubsAsync: Parsed {Count} valid tenant IDs from claim", tenantIds.Count);
|
||||||
|
|
||||||
if (tenantIds.Count == 0)
|
if (tenantIds.Count == 0)
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning("GetMyClubsAsync: No valid tenant IDs found in clubs claim: {ClubsClaim}", clubsClaim);
|
||||||
return new List<ClubListDto>();
|
return new List<ClubListDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,13 +57,16 @@ public class ClubService
|
|||||||
var connectionString = _context.Database.GetConnectionString();
|
var connectionString = _context.Database.GetConnectionString();
|
||||||
|
|
||||||
foreach (var tenantId in tenantIds)
|
foreach (var tenantId in tenantIds)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await using var connection = new NpgsqlConnection(connectionString);
|
await using var connection = new NpgsqlConnection(connectionString);
|
||||||
await connection.OpenAsync();
|
await connection.OpenAsync();
|
||||||
|
|
||||||
await using var transaction = await connection.BeginTransactionAsync();
|
await using var transaction = await connection.BeginTransactionAsync();
|
||||||
|
|
||||||
// Set RLS context
|
// Set RLS context - tenantId is already validated as a valid GUID
|
||||||
|
// Use direct string since SET LOCAL doesn't support parameters
|
||||||
using (var command = connection.CreateCommand())
|
using (var command = connection.CreateCommand())
|
||||||
{
|
{
|
||||||
command.Transaction = transaction;
|
command.Transaction = transaction;
|
||||||
@@ -120,11 +135,27 @@ public class ClubService
|
|||||||
|
|
||||||
await transaction.CommitAsync();
|
await transaction.CommitAsync();
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "GetMyClubsAsync: Error processing tenant {TenantId}", tenantId);
|
||||||
|
// Continue with next tenant instead of failing entirely
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("GetMyClubsAsync: Returning {Count} clubs", clubDtos.Count);
|
||||||
return clubDtos;
|
return clubDtos;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "GetMyClubsAsync: Unexpected error getting user clubs");
|
||||||
|
// Return empty list instead of throwing to prevent 500 error
|
||||||
|
return new List<ClubListDto>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ClubDetailDto?> GetCurrentClubAsync()
|
public async Task<ClubDetailDto?> GetCurrentClubAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var tenantId = _tenantProvider.GetTenantId();
|
var tenantId = _tenantProvider.GetTenantId();
|
||||||
|
|
||||||
@@ -143,4 +174,10 @@ public class ClubService
|
|||||||
club.UpdatedAt
|
club.UpdatedAt
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "GetCurrentClubAsync: Error getting current club");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"DefaultConnection": "Host=localhost;Port=5432;Database=workclub;Username=app;Password=apppass"
|
"DefaultConnection": "Host=localhost;Port=5432;Database=workclub;Username=app;Password=apppass"
|
||||||
},
|
},
|
||||||
"Keycloak": {
|
"Keycloak": {
|
||||||
"Authority": "http://localhost:8080/realms/workclub",
|
"Authority": "http://localhost:30808/realms/workclub",
|
||||||
"Audience": "workclub-api"
|
"Audience": "workclub-api"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -39,7 +39,7 @@ services:
|
|||||||
KC_DB_PASSWORD: keycloakpass
|
KC_DB_PASSWORD: keycloakpass
|
||||||
KC_HEALTH_ENABLED: "true"
|
KC_HEALTH_ENABLED: "true"
|
||||||
KC_LOG_LEVEL: INFO
|
KC_LOG_LEVEL: INFO
|
||||||
KC_HOSTNAME: "http://localhost:8080"
|
KC_HOSTNAME: "http://localhost:30808"
|
||||||
KC_HOSTNAME_STRICT: "false"
|
KC_HOSTNAME_STRICT: "false"
|
||||||
KC_PROXY: "edge"
|
KC_PROXY: "edge"
|
||||||
KC_HTTP_PORT: "8081"
|
KC_HTTP_PORT: "8081"
|
||||||
@@ -47,7 +47,7 @@ services:
|
|||||||
KC_HOSTNAME_ADMIN: "http://keycloak:8081"
|
KC_HOSTNAME_ADMIN: "http://keycloak:8081"
|
||||||
KC_SPI_HOSTNAME_DEFAULT_ADMIN: "keycloak:8081"
|
KC_SPI_HOSTNAME_DEFAULT_ADMIN: "keycloak:8081"
|
||||||
ports:
|
ports:
|
||||||
- "8080:8081"
|
- "30808:8081"
|
||||||
volumes:
|
volumes:
|
||||||
- ./infra/keycloak:/opt/keycloak/data/import
|
- ./infra/keycloak:/opt/keycloak/data/import
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -71,7 +71,7 @@ services:
|
|||||||
Keycloak__Audience: "workclub-api"
|
Keycloak__Audience: "workclub-api"
|
||||||
Keycloak__TokenValidationParameters__ValidateIssuer: "false"
|
Keycloak__TokenValidationParameters__ValidateIssuer: "false"
|
||||||
ports:
|
ports:
|
||||||
- "5001:8080"
|
- "30501:8080"
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "localhost:172.18.0.1"
|
- "localhost:172.18.0.1"
|
||||||
- "127.0.0.1:172.18.0.1"
|
- "127.0.0.1:172.18.0.1"
|
||||||
@@ -93,18 +93,18 @@ services:
|
|||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "localhost:host-gateway"
|
- "localhost:host-gateway"
|
||||||
environment:
|
environment:
|
||||||
NEXT_PUBLIC_API_URL: "http://localhost:5001"
|
NEXT_PUBLIC_API_URL: "http://localhost:30501"
|
||||||
API_INTERNAL_URL: "http://dotnet-api:8080"
|
API_INTERNAL_URL: "http://dotnet-api:8080"
|
||||||
NEXTAUTH_SECRET: "dev-secret-change-in-production-use-openssl-rand-base64-32"
|
NEXTAUTH_SECRET: "dev-secret-change-in-production-use-openssl-rand-base64-32"
|
||||||
AUTH_SECRET: "dev-secret-change-in-production-use-openssl-rand-base64-32"
|
AUTH_SECRET: "dev-secret-change-in-production-use-openssl-rand-base64-32"
|
||||||
AUTH_TRUST_HOST: "true"
|
AUTH_TRUST_HOST: "true"
|
||||||
KEYCLOAK_CLIENT_ID: "workclub-app"
|
KEYCLOAK_CLIENT_ID: "workclub-app"
|
||||||
KEYCLOAK_CLIENT_SECRET: "dev-secret-workclub-api-change-in-production"
|
KEYCLOAK_CLIENT_SECRET: "dev-secret-workclub-api-change-in-production"
|
||||||
KEYCLOAK_ISSUER: "http://localhost:8080/realms/workclub"
|
KEYCLOAK_ISSUER: "http://localhost:30808/realms/workclub"
|
||||||
KEYCLOAK_ISSUER_INTERNAL: "http://keycloak:8081/realms/workclub"
|
KEYCLOAK_ISSUER_INTERNAL: "http://keycloak:8081/realms/workclub"
|
||||||
NEXT_PUBLIC_KEYCLOAK_ISSUER: "http://localhost:8080/realms/workclub"
|
NEXT_PUBLIC_KEYCLOAK_ISSUER: "http://localhost:30808/realms/workclub"
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "30080:3000"
|
||||||
volumes:
|
volumes:
|
||||||
- ./frontend:/app:cached
|
- ./frontend:/app:cached
|
||||||
- /app/node_modules
|
- /app/node_modules
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ COPY . .
|
|||||||
# Set environment for build to ensure server binds to all interfaces
|
# Set environment for build to ensure server binds to all interfaces
|
||||||
ENV HOSTNAME="0.0.0.0"
|
ENV HOSTNAME="0.0.0.0"
|
||||||
ENV PORT="3000"
|
ENV PORT="3000"
|
||||||
|
# Set API_INTERNAL_URL for build-time Next.js rewrites evaluation
|
||||||
|
ENV API_INTERNAL_URL="http://workclub-api:8080"
|
||||||
RUN bun run build
|
RUN bun run build
|
||||||
|
|
||||||
# Stage 3: Runtime
|
# Stage 3: Runtime
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ function LoginContent() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSwitchAccount = () => {
|
const handleSwitchAccount = () => {
|
||||||
const keycloakLogoutUrl = `${process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER || 'http://localhost:8080/realms/workclub'}/protocol/openid-connect/logout?redirect_uri=${encodeURIComponent(window.location.origin + '/login')}`;
|
const keycloakLogoutUrl = `${process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER || 'http://localhost:30808/realms/workclub'}/protocol/openid-connect/logout?redirect_uri=${encodeURIComponent(window.location.origin + '/login')}`;
|
||||||
signOut({ redirect: false }).then(() => {
|
signOut({ redirect: false }).then(() => {
|
||||||
window.location.href = keycloakLogoutUrl;
|
window.location.href = keycloakLogoutUrl;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ declare module "next-auth" {
|
|||||||
// In Docker, the Next.js server reaches Keycloak via internal hostname
|
// In Docker, the Next.js server reaches Keycloak via internal hostname
|
||||||
// (keycloak:8080) but the browser uses localhost:8080. Explicit endpoint
|
// (keycloak:8080) but the browser uses localhost:8080. Explicit endpoint
|
||||||
// URLs bypass OIDC discovery, avoiding issuer mismatch validation errors.
|
// URLs bypass OIDC discovery, avoiding issuer mismatch validation errors.
|
||||||
const issuerPublic = process.env.KEYCLOAK_ISSUER || 'http://localhost:8080/realms/workclub'
|
const issuerPublic = process.env.KEYCLOAK_ISSUER || 'http://localhost:30808/realms/workclub'
|
||||||
const issuerInternal = process.env.KEYCLOAK_ISSUER_INTERNAL || issuerPublic
|
const issuerInternal = process.env.KEYCLOAK_ISSUER_INTERNAL || issuerPublic
|
||||||
const oidcPublic = `${issuerPublic}/protocol/openid-connect`
|
const oidcPublic = `${issuerPublic}/protocol/openid-connect`
|
||||||
const oidcInternal = `${issuerInternal.replace(':8080', ':8081')}/protocol/openid-connect`
|
const oidcInternal = `${issuerInternal}/protocol/openid-connect`
|
||||||
|
|
||||||
export const { handlers, signIn, signOut, auth } = NextAuth({
|
export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||||
providers: [
|
providers: [
|
||||||
@@ -71,14 +71,21 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
|||||||
// Add clubs claim from Keycloak access token
|
// Add clubs claim from Keycloak access token
|
||||||
token.clubs = (account as { clubs?: Record<string, string> }).clubs || {}
|
token.clubs = (account as { clubs?: Record<string, string> }).clubs || {}
|
||||||
token.accessToken = account.access_token
|
token.accessToken = account.access_token
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always check admin status from the access token if available
|
||||||
|
if (token.accessToken) {
|
||||||
try {
|
try {
|
||||||
const payload = JSON.parse(Buffer.from((token.accessToken as string).split('.')[1], 'base64').toString());
|
const payload = JSON.parse(Buffer.from((token.accessToken as string).split('.')[1], 'base64').toString());
|
||||||
const roles = (payload.realm_access?.roles as string[]) || [];
|
const roles = (payload.realm_access?.roles as string[]) || [];
|
||||||
token.isAdmin = roles.includes('admin');
|
token.isAdmin = roles.includes('admin');
|
||||||
} catch {
|
console.log('[Auth Debug] Checking admin status:', { roles, isAdmin: token.isAdmin });
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[Auth Debug] Failed to check admin status:', e);
|
||||||
token.isAdmin = false;
|
token.isAdmin = false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.log('[Auth Debug] No access token available');
|
||||||
}
|
}
|
||||||
return token
|
return token
|
||||||
},
|
},
|
||||||
@@ -89,6 +96,12 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
|||||||
session.user.isAdmin = token.isAdmin as boolean | undefined
|
session.user.isAdmin = token.isAdmin as boolean | undefined
|
||||||
}
|
}
|
||||||
session.accessToken = token.accessToken as string | undefined
|
session.accessToken = token.accessToken as string | undefined
|
||||||
|
|
||||||
|
// Log session data for debugging
|
||||||
|
console.log('[Session Debug] Session user:', session.user);
|
||||||
|
console.log('[Session Debug] Token isAdmin:', token.isAdmin);
|
||||||
|
console.log('[Session Debug] Session isAdmin:', session.user?.isAdmin);
|
||||||
|
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,13 @@ export function AuthGuard({ children }: { children: ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isAdmin = data?.user?.isAdmin;
|
const isAdmin = data?.user?.isAdmin;
|
||||||
|
|
||||||
|
// Debug: Log auth state
|
||||||
|
console.log('[AuthGuard Debug] status:', status);
|
||||||
|
console.log('[AuthGuard Debug] isAdmin:', isAdmin);
|
||||||
|
console.log('[AuthGuard Debug] data?.user:', data?.user);
|
||||||
|
console.log('[AuthGuard Debug] clubs.length:', clubs.length);
|
||||||
|
|
||||||
if (clubs.length === 0 && status === 'authenticated' && !isAdmin) {
|
if (clubs.length === 0 && status === 'authenticated' && !isAdmin) {
|
||||||
const handleSwitchAccount = () => {
|
const handleSwitchAccount = () => {
|
||||||
const keycloakLogoutUrl = `${process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER || 'http://localhost:8080/realms/workclub'}/protocol/openid-connect/logout?redirect_uri=${encodeURIComponent(window.location.origin + '/login')}`;
|
const keycloakLogoutUrl = `${process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER || 'http://localhost:8080/realms/workclub'}/protocol/openid-connect/logout?redirect_uri=${encodeURIComponent(window.location.origin + '/login')}`;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ spec:
|
|||||||
app: workclub-api
|
app: workclub-api
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 8080
|
||||||
targetPort: 8080
|
targetPort: 8080
|
||||||
nodePort: 30081
|
nodePort: 30501
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ metadata:
|
|||||||
app: workclub
|
app: workclub
|
||||||
data:
|
data:
|
||||||
log-level: "Information"
|
log-level: "Information"
|
||||||
cors-origins: "http://localhost:3000,http://192.168.240.200:30080"
|
cors-origins: "http://localhost:30080,http://192.168.240.200:30080,http://192.168.240.200:30808"
|
||||||
api-base-url: "http://192.168.240.200:30081"
|
api-base-url: "http://192.168.240.200:30501"
|
||||||
keycloak-url: "http://192.168.240.200:30082"
|
keycloak-url: "http://192.168.240.200:30808"
|
||||||
keycloak-authority: "http://192.168.240.200:30082/realms/workclub"
|
keycloak-authority: "http://192.168.240.200:30808/realms/workclub"
|
||||||
keycloak-audience: "workclub-api"
|
keycloak-audience: "workclub-api"
|
||||||
keycloak-realm: "workclub"
|
keycloak-realm: "workclub"
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ spec:
|
|||||||
periodSeconds: 15
|
periodSeconds: 15
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 5
|
||||||
failureThreshold: 3
|
failureThreshold: 3
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
@@ -48,10 +47,11 @@ spec:
|
|||||||
limits:
|
limits:
|
||||||
cpu: 500m
|
cpu: 500m
|
||||||
memory: 512Mi
|
memory: 512Mi
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- name: NODE_ENV
|
- name: NODE_ENV
|
||||||
value: "production"
|
value: "production"
|
||||||
|
- name: API_INTERNAL_URL
|
||||||
|
value: "http://workclub-api:8080"
|
||||||
- name: NEXT_PUBLIC_API_URL
|
- name: NEXT_PUBLIC_API_URL
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
@@ -89,4 +89,4 @@ spec:
|
|||||||
name: workclub-config
|
name: workclub-config
|
||||||
key: keycloak-authority
|
key: keycloak-authority
|
||||||
- name: KEYCLOAK_ISSUER_INTERNAL
|
- name: KEYCLOAK_ISSUER_INTERNAL
|
||||||
value: "http://workclub-keycloak/realms/workclub"
|
value: "http://workclub-keycloak:8080/realms/workclub"
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: workclub-frontend
|
||||||
|
labels:
|
||||||
|
app: workclub-frontend
|
||||||
|
component: frontend
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: workclub-frontend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: workclub-frontend
|
||||||
|
component: frontend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: frontend
|
||||||
|
image: 192.168.241.13:8080/workclub-frontend:latest
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 3000
|
||||||
|
protocol: TCP
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 2
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 15
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
|
||||||
|
env:
|
||||||
|
- name: NODE_ENV
|
||||||
|
value: "production"
|
||||||
|
- name: NEXT_PUBLIC_API_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: workclub-config
|
||||||
|
key: api-base-url
|
||||||
|
- name: NEXT_PUBLIC_KEYCLOAK_URL
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: workclub-config
|
||||||
|
key: keycloak-url
|
||||||
|
- name: NEXT_PUBLIC_KEYCLOAK_ISSUER
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: workclub-config
|
||||||
|
key: keycloak-authority
|
||||||
|
- name: NEXTAUTH_URL
|
||||||
|
value: "http://192.168.240.200:3000"
|
||||||
|
- name: AUTH_TRUST_HOST
|
||||||
|
value: "true"
|
||||||
|
- name: NEXTAUTH_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: workclub-secrets
|
||||||
|
key: nextauth-secret
|
||||||
|
- name: KEYCLOAK_CLIENT_ID
|
||||||
|
value: "workclub-app"
|
||||||
|
- name: KEYCLOAK_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: workclub-secrets
|
||||||
|
key: keycloak-client-secret
|
||||||
|
- name: KEYCLOAK_ISSUER
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: workclub-config
|
||||||
|
key: keycloak-authority
|
||||||
|
- name: KEYCLOAK_ISSUER_INTERNAL
|
||||||
|
value: "http://workclub-keycloak/realms/workclub"
|
||||||
@@ -11,7 +11,7 @@ spec:
|
|||||||
app: workclub-frontend
|
app: workclub-frontend
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 3000
|
||||||
targetPort: 3000
|
targetPort: 3000
|
||||||
nodePort: 30080
|
nodePort: 30080
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ spec:
|
|||||||
args:
|
args:
|
||||||
- start-dev
|
- start-dev
|
||||||
- --import-realm
|
- --import-realm
|
||||||
|
- --import-realm-overwrite
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 8080
|
containerPort: 8080
|
||||||
|
|||||||
@@ -69,14 +69,14 @@ data:
|
|||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"publicClient": true,
|
"publicClient": true,
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"http://localhost:3000/*",
|
"http://localhost:30080/*",
|
||||||
"http://localhost:3001/*",
|
"http://localhost:30081/*",
|
||||||
"http://workclub-frontend/*",
|
"http://workclub-frontend/*",
|
||||||
"http://192.168.240.200:30080/*"
|
"http://192.168.240.200:30080/*"
|
||||||
],
|
],
|
||||||
"webOrigins": [
|
"webOrigins": [
|
||||||
"http://localhost:3000",
|
"http://localhost:30080",
|
||||||
"http://localhost:3001",
|
"http://localhost:30081",
|
||||||
"http://workclub-frontend",
|
"http://workclub-frontend",
|
||||||
"http://192.168.240.200:30080"
|
"http://192.168.240.200:30080"
|
||||||
],
|
],
|
||||||
@@ -152,7 +152,7 @@ data:
|
|||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"clubs": [
|
"clubs": [
|
||||||
"64e05b5e-ef45-81d7-f2e8-3d14bd197383,Admin,3b4afcfa-1352-8fc7-b497-8ab52a0d5fda,Member"
|
"64e05b5e-ef45-81d7-f2e8-3d14bd197383,3b4afcfa-1352-8fc7-b497-8ab52a0d5fda"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -174,7 +174,7 @@ data:
|
|||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"clubs": [
|
"clubs": [
|
||||||
"64e05b5e-ef45-81d7-f2e8-3d14bd197383,Manager"
|
"64e05b5e-ef45-81d7-f2e8-3d14bd197383"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -196,7 +196,7 @@ data:
|
|||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"clubs": [
|
"clubs": [
|
||||||
"64e05b5e-ef45-81d7-f2e8-3d14bd197383,Member,3b4afcfa-1352-8fc7-b497-8ab52a0d5fda,Member"
|
"64e05b5e-ef45-81d7-f2e8-3d14bd197383,3b4afcfa-1352-8fc7-b497-8ab52a0d5fda"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -218,7 +218,7 @@ data:
|
|||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"clubs": [
|
"clubs": [
|
||||||
"64e05b5e-ef45-81d7-f2e8-3d14bd197383,Member"
|
"64e05b5e-ef45-81d7-f2e8-3d14bd197383"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -240,7 +240,7 @@ data:
|
|||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"clubs": [
|
"clubs": [
|
||||||
"64e05b5e-ef45-81d7-f2e8-3d14bd197383,Viewer"
|
"64e05b5e-ef45-81d7-f2e8-3d14bd197383"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ spec:
|
|||||||
app: workclub-keycloak
|
app: workclub-keycloak
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 8080
|
||||||
targetPort: 8080
|
targetPort: 8080
|
||||||
nodePort: 30082
|
nodePort: 30808
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
|||||||
@@ -86,14 +86,14 @@
|
|||||||
"authorizationServicesEnabled": false,
|
"authorizationServicesEnabled": false,
|
||||||
"protocol": "openid-connect",
|
"protocol": "openid-connect",
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"http://localhost:3000/*"
|
"http://localhost:30080/*"
|
||||||
],
|
],
|
||||||
"webOrigins": [
|
"webOrigins": [
|
||||||
"http://localhost:3000"
|
"http://localhost:30080"
|
||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"pkce.code.challenge.method": "S256",
|
"pkce.code.challenge.method": "S256",
|
||||||
"post.logout.redirect.uris": "http://localhost:3000/*",
|
"post.logout.redirect.uris": "http://localhost:30080/*",
|
||||||
"access.token.lifespan": "3600"
|
"access.token.lifespan": "3600"
|
||||||
},
|
},
|
||||||
"protocolMappers": [
|
"protocolMappers": [
|
||||||
@@ -162,7 +162,9 @@
|
|||||||
"firstName": "Admin",
|
"firstName": "Admin",
|
||||||
"lastName": "User",
|
"lastName": "User",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"clubs": []
|
"clubs": [
|
||||||
|
"64e05b5e-ef45-81d7-f2e8-3d14bd197383,3b4afcfa-1352-8fc7-b497-8ab52a0d5fda"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"credentials": [
|
"credentials": [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user