Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e52701dba3 | |||
| b1bcfc69e4 |
@@ -17,10 +17,13 @@ Ops panel at `/admin` (`backend/src/admin/`). Resources are a **manual allowlist
|
|||||||
3. **Renamed / removed model** → update or remove the matching resource (broken `getModelByName` breaks `/admin` boot).
|
3. **Renamed / removed model** → update or remove the matching resource (broken `getModelByName` breaks `/admin` boot).
|
||||||
4. **New secret fields** (hashes, tokens, share tokens) → hide via `isVisible: false` (list/filter/show/edit).
|
4. **New secret fields** (hashes, tokens, share tokens) → hide via `isVisible: false` (list/filter/show/edit).
|
||||||
5. **Catalog-like reference data** → list/show/edit only; disable `new` / `delete` / `bulkDelete`.
|
5. **Catalog-like reference data** → list/show/edit only; disable `new` / `delete` / `bulkDelete`.
|
||||||
6. Skip pure join/cursor tables unless ops need them (`LabCaseUserReadState`, `LabCaseUserTabReadState`, working-hours, `LabCaseAttachment`).
|
6. **Composite `@@id` only** (no single `@id`) → **do not register** — AdminJS list returns 500 (`Resource does not have an id property`). Examples: `LabCaseDetail`, `MembershipPermission`, read-cursor tables.
|
||||||
|
7. Skip pure join/cursor tables unless ops need them and they have a single id.
|
||||||
|
|
||||||
Auth: `ADMINJS_EMAIL` / `ADMINJS_PASSWORD` — production login disabled if password missing or still `admin123`.
|
Auth: `ADMINJS_EMAIL` / `ADMINJS_PASSWORD` — production login disabled if password missing or still `admin123`.
|
||||||
|
|
||||||
|
Production Docker: `ADMIN_JS_TMP_DIR=/app/adminjs-tmp` (not `.adminjs`) so `components.bundle.js` can be written/served.
|
||||||
|
|
||||||
## Secrets to hide
|
## Secrets to hide
|
||||||
|
|
||||||
`passwordHash`, session `token`/`refreshToken`, invite/OTP `tokenHash`/`codeHash`, `LabCase.accessToken`.
|
`passwordHash`, session `token`/`refreshToken`, invite/OTP `tokenHash`/`codeHash`, `LabCase.accessToken`.
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ backend/src/
|
|||||||
|
|
||||||
Errors: `AppException` + `ErrorCode` → frontend `getUserFacingError()`. Unexpected 500s: GlitchTip (`SENTRY_DSN`). Never throw raw strings for user-facing failures.
|
Errors: `AppException` + `ErrorCode` → frontend `getUserFacingError()`. Unexpected 500s: GlitchTip (`SENTRY_DSN`). Never throw raw strings for user-facing failures.
|
||||||
|
|
||||||
**AdminJS:** Manual resource allowlist in `backend/src/admin/resources.ts`. **Whenever `schema.prisma` changes**, update AdminJS resources in the same task (new/renamed/removed models, hide secrets). Rule: `.cursor/rules/adminjs.mdc`.
|
**AdminJS:** Manual resource allowlist in `backend/src/admin/resources.ts`. **Whenever `schema.prisma` changes**, update AdminJS resources in the same task (new/renamed/removed models, hide secrets). Models with only composite `@@id` must not be registered (list 500). Rule: `.cursor/rules/adminjs.mdc`.
|
||||||
|
|
||||||
## Git & commits
|
## Git & commits
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,11 @@ COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
|||||||
# Windows git/build context may use CRLF; strip before chmod (fixes dumb-init "No such file or directory").
|
# Windows git/build context may use CRLF; strip before chmod (fixes dumb-init "No such file or directory").
|
||||||
RUN sed -i 's/\r$//' /usr/local/bin/docker-entrypoint.sh && chmod +x /usr/local/bin/docker-entrypoint.sh
|
RUN sed -i 's/\r$//' /usr/local/bin/docker-entrypoint.sh && chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||||
|
|
||||||
RUN mkdir -p /app/logs && \
|
# AdminJS writes/serves the custom-components bundle here. Avoid the default
|
||||||
|
# ".adminjs" path — Express sendFile + nosniff can 500 on dot-directories.
|
||||||
|
ENV ADMIN_JS_TMP_DIR=/app/adminjs-tmp
|
||||||
|
|
||||||
|
RUN mkdir -p /app/logs /app/adminjs-tmp && \
|
||||||
chown -R dyolink:nodejs /app
|
chown -R dyolink:nodejs /app
|
||||||
|
|
||||||
USER dyolink
|
USER dyolink
|
||||||
|
|||||||
@@ -76,9 +76,7 @@ export function buildAdminResources(prisma: PrismaService): AdminResource[] {
|
|||||||
resource(prisma, 'Permission', {
|
resource(prisma, 'Permission', {
|
||||||
navigation: { name: 'Orgs & access', icon: 'Settings' },
|
navigation: { name: 'Orgs & access', icon: 'Settings' },
|
||||||
}),
|
}),
|
||||||
resource(prisma, 'MembershipPermission', {
|
// MembershipPermission omitted: composite @@id — AdminJS list 500s without a single id
|
||||||
navigation: { name: 'Orgs & access', icon: 'Settings' },
|
|
||||||
}),
|
|
||||||
resource(prisma, 'Feature', {
|
resource(prisma, 'Feature', {
|
||||||
navigation: { name: 'Orgs & access', icon: 'Settings' },
|
navigation: { name: 'Orgs & access', icon: 'Settings' },
|
||||||
}),
|
}),
|
||||||
@@ -119,9 +117,8 @@ export function buildAdminResources(prisma: PrismaService): AdminResource[] {
|
|||||||
resource(prisma, 'LabCaseLine', {
|
resource(prisma, 'LabCaseLine', {
|
||||||
navigation: { name: 'Lab', icon: 'Archive' },
|
navigation: { name: 'Lab', icon: 'Archive' },
|
||||||
}),
|
}),
|
||||||
resource(prisma, 'LabCaseDetail', {
|
// LabCaseDetail omitted: composite @@id — AdminJS list 500s without a single id
|
||||||
navigation: { name: 'Lab', icon: 'Archive' },
|
// (inspect LabCase + TreatmentDetail instead)
|
||||||
}),
|
|
||||||
resource(prisma, 'LabCaseSend', {
|
resource(prisma, 'LabCaseSend', {
|
||||||
navigation: { name: 'Lab', icon: 'Archive' },
|
navigation: { name: 'Lab', icon: 'Archive' },
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ FRONTEND_URL=https://nudentic.ir
|
|||||||
# Change these — the code defaults are only for local development.
|
# Change these — the code defaults are only for local development.
|
||||||
ADMINJS_EMAIL=admin@nudentic.ir
|
ADMINJS_EMAIL=admin@nudentic.ir
|
||||||
ADMINJS_PASSWORD=CHANGE_ME_STRONG_ADMINJS_PASSWORD
|
ADMINJS_PASSWORD=CHANGE_ME_STRONG_ADMINJS_PASSWORD
|
||||||
|
# Optional override; Docker image sets /app/adminjs-tmp (do not use ".adminjs").
|
||||||
|
# ADMIN_JS_TMP_DIR=/app/adminjs-tmp
|
||||||
|
|
||||||
# Required for HTTPS — browsers reject Secure cookies over plain HTTP
|
# Required for HTTPS — browsers reject Secure cookies over plain HTTP
|
||||||
COOKIE_SECURE=true
|
COOKIE_SECURE=true
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ FRONTEND_URL=https://wixur.ir
|
|||||||
# AdminJS at https://wixur.ir/admin (nginx proxies /admin to the API).
|
# AdminJS at https://wixur.ir/admin (nginx proxies /admin to the API).
|
||||||
ADMINJS_EMAIL=admin@wixur.ir
|
ADMINJS_EMAIL=admin@wixur.ir
|
||||||
ADMINJS_PASSWORD=CHANGE_ME_STRONG_ADMINJS_PASSWORD
|
ADMINJS_PASSWORD=CHANGE_ME_STRONG_ADMINJS_PASSWORD
|
||||||
|
# Optional override; Docker image sets /app/adminjs-tmp (do not use ".adminjs").
|
||||||
|
# ADMIN_JS_TMP_DIR=/app/adminjs-tmp
|
||||||
|
|
||||||
# TLS is terminated on Windows nginx :443 — cookies must be Secure
|
# TLS is terminated on Windows nginx :443 — cookies must be Secure
|
||||||
COOKIE_SECURE=true
|
COOKIE_SECURE=true
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ services:
|
|||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
TZ: UTC
|
TZ: UTC
|
||||||
PORT: "3000"
|
PORT: "3000"
|
||||||
|
ADMIN_JS_TMP_DIR: /app/adminjs-tmp
|
||||||
SENTRY_ENVIRONMENT: production
|
SENTRY_ENVIRONMENT: production
|
||||||
SENTRY_RELEASE: ${TAG:-latest}
|
SENTRY_RELEASE: ${TAG:-latest}
|
||||||
expose:
|
expose:
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ services:
|
|||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
TZ: UTC
|
TZ: UTC
|
||||||
PORT: "3000"
|
PORT: "3000"
|
||||||
|
ADMIN_JS_TMP_DIR: /app/adminjs-tmp
|
||||||
SENTRY_ENVIRONMENT: staging
|
SENTRY_ENVIRONMENT: staging
|
||||||
SENTRY_RELEASE: ${IMAGE_TAG:-latest}
|
SENTRY_RELEASE: ${IMAGE_TAG:-latest}
|
||||||
expose:
|
expose:
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ services:
|
|||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
TZ: UTC
|
TZ: UTC
|
||||||
PORT: "3000"
|
PORT: "3000"
|
||||||
|
ADMIN_JS_TMP_DIR: /app/adminjs-tmp
|
||||||
SENTRY_ENVIRONMENT: staging
|
SENTRY_ENVIRONMENT: staging
|
||||||
expose:
|
expose:
|
||||||
- "3000"
|
- "3000"
|
||||||
|
|||||||
Reference in New Issue
Block a user