diff --git a/.env.example b/.env.example
index b690b70..d76473f 100644
--- a/.env.example
+++ b/.env.example
@@ -81,5 +81,5 @@ KAVENEGAR_API_KEY=4C30786935496261332B41685870444E47657A5367453369374F6E2F433346
SNAPPFOOD_WEBHOOK_SECRET=change-me-snappfood-secret
# ── Docker image overrides (if direct MCR pull fails) ────────────────────────
-# DOTNET_SDK_IMAGE=171.22.25.73:5002/dotnet/sdk:10.0
-# DOTNET_ASPNET_IMAGE=171.22.25.73:5002/dotnet/aspnet:10.0
+# DOTNET_SDK_IMAGE=mirror.soroushasadi.com/dotnet/sdk:10.0
+# DOTNET_ASPNET_IMAGE=mirror.soroushasadi.com/dotnet/aspnet:10.0
diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml
index c2e7822..07789f8 100644
--- a/.gitea/workflows/ci-cd.yml
+++ b/.gitea/workflows/ci-cd.yml
@@ -17,13 +17,12 @@ concurrency:
# ubuntu-latest:docker://node:20-alpine ← CI jobs run in real Docker containers
# self-hosted:host ← deploy runs directly on the server
#
-# All images/packages served from local Nexus at 171.22.25.73:
-# Docker images → 171.22.25.73:8087 (docker-group connector: Docker Hub + MCR)
-# NuGet → http://171.22.25.73:8081/repository/nuget-group/
-# npm → http://171.22.25.73:8081/repository/npm-group/
+# All images/packages served from Nexus at mirror.soroushasadi.com:
+# Docker images → mirror.soroushasadi.com (docker-group: Docker Hub + MCR)
+# NuGet → https://mirror.soroushasadi.com/repository/nuget-group/
+# npm → https://mirror.soroushasadi.com/repository/npm-group/
#
-# The runner host is 171.22.25.73, so Nexus is always reachable directly.
-# Daemon must have: "insecure-registries": ["171.22.25.73:8087"]
+# Docker daemon: merge docker/daemon-registry-mirror.example.json into daemon.json
# ─────────────────────────────────────────────────────────────────────────────
jobs:
@@ -32,12 +31,12 @@ jobs:
name: "CI · API (dotnet build + test)"
runs-on: ubuntu-latest
container:
- image: 171.22.25.73:8087/dotnet/sdk:10.0
+ image: mirror.soroushasadi.com/dotnet/sdk:10.0
options: >-
--add-host=gitea:host-gateway
services:
postgres:
- image: 171.22.25.73:8087/postgres:16-alpine
+ image: mirror.soroushasadi.com/postgres:16-alpine
env:
POSTGRES_DB: meezi_test
POSTGRES_USER: meezi
@@ -48,7 +47,7 @@ jobs:
--health-timeout 5s
--health-retries 10
redis:
- image: 171.22.25.73:8087/redis:7-alpine
+ image: mirror.soroushasadi.com/redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
@@ -74,9 +73,9 @@ jobs:
+ />
EOF
@@ -99,7 +98,7 @@ jobs:
name: "CI · Admin API (dotnet build)"
runs-on: ubuntu-latest
container:
- image: 171.22.25.73:8087/dotnet/sdk:10.0
+ image: mirror.soroushasadi.com/dotnet/sdk:10.0
options: >-
--add-host=gitea:host-gateway
steps:
@@ -122,9 +121,9 @@ jobs:
+ />
EOF
@@ -141,7 +140,7 @@ jobs:
name: "CI · Dashboard (tsc)"
runs-on: ubuntu-latest
container:
- image: 171.22.25.73:8087/node:20-alpine
+ image: mirror.soroushasadi.com/node:20-alpine
options: >-
--add-host=gitea:host-gateway
steps:
@@ -159,7 +158,7 @@ jobs:
- name: Install dependencies
working-directory: web/dashboard
- run: npm install --legacy-peer-deps --ignore-scripts --registry http://171.22.25.73:8081/repository/npm-group/
+ run: npm install --legacy-peer-deps --ignore-scripts --registry https://mirror.soroushasadi.com/repository/npm-group/
- name: TypeScript check
working-directory: web/dashboard
@@ -171,7 +170,7 @@ jobs:
name: "CI · Admin Web (tsc)"
runs-on: ubuntu-latest
container:
- image: 171.22.25.73:8087/node:20-alpine
+ image: mirror.soroushasadi.com/node:20-alpine
options: >-
--add-host=gitea:host-gateway
steps:
@@ -189,7 +188,7 @@ jobs:
- name: Install dependencies
working-directory: web/admin
- run: npm install --legacy-peer-deps --ignore-scripts --registry http://171.22.25.73:8081/repository/npm-group/
+ run: npm install --legacy-peer-deps --ignore-scripts --registry https://mirror.soroushasadi.com/repository/npm-group/
- name: TypeScript check
working-directory: web/admin
@@ -201,7 +200,7 @@ jobs:
name: "CI · Website (tsc)"
runs-on: ubuntu-latest
container:
- image: 171.22.25.73:8087/node:20-alpine
+ image: mirror.soroushasadi.com/node:20-alpine
options: >-
--add-host=gitea:host-gateway
steps:
@@ -219,7 +218,7 @@ jobs:
- name: Install dependencies
working-directory: web/website
- run: npm install --legacy-peer-deps --ignore-scripts --registry http://171.22.25.73:8081/repository/npm-group/
+ run: npm install --legacy-peer-deps --ignore-scripts --registry https://mirror.soroushasadi.com/repository/npm-group/
- name: TypeScript check
working-directory: web/website
@@ -231,7 +230,7 @@ jobs:
name: "CI · Koja (tsc)"
runs-on: ubuntu-latest
container:
- image: 171.22.25.73:8087/node:20-alpine
+ image: mirror.soroushasadi.com/node:20-alpine
options: >-
--add-host=gitea:host-gateway
steps:
@@ -249,7 +248,7 @@ jobs:
- name: Install dependencies
working-directory: web/koja
- run: npm install --legacy-peer-deps --ignore-scripts --registry http://171.22.25.73:8081/repository/npm-group/
+ run: npm install --legacy-peer-deps --ignore-scripts --registry https://mirror.soroushasadi.com/repository/npm-group/
- name: TypeScript check
working-directory: web/koja
diff --git a/DEPLOY.md b/DEPLOY.md
index b26aecb..870bcab 100644
--- a/DEPLOY.md
+++ b/DEPLOY.md
@@ -6,7 +6,7 @@
Server: 171.22.25.73
│
├── Gitea :3000 ← source control + CI runner
-├── Nexus :8081 ← package mirror (NuGet, npm, Docker)
+├── Nexus mirror.soroushasadi.com ← package mirror (NuGet, npm, Docker, MCR)
│
├── meezi-api :5080 ← .NET main API
├── meezi-admin-api:5081 ← .NET admin API
@@ -128,7 +128,7 @@ CI takes ~5–10 minutes: builds 6 Docker images, runs all checks, then deploys.
| Main API (Swagger) | http://171.22.25.73:5080/swagger |
| Admin API (Swagger) | http://171.22.25.73:5081/swagger |
| Gitea | http://171.22.25.73:3000 |
-| Nexus | http://171.22.25.73:8081 |
+| Nexus | https://mirror.soroushasadi.com/ |
---
@@ -255,8 +255,8 @@ Nexus runs separately and should always be running:
# Start (first time or after server reboot)
docker compose -f docker-compose.mirror.yml up -d
-# Health check
-curl -s http://localhost:8081/service/rest/v1/status
+# Health check (on server or via domain)
+curl -s https://mirror.soroushasadi.com/service/rest/v1/status
```
Provisioned repos:
diff --git a/docker-compose.admin.yml b/docker-compose.admin.yml
index 56f1694..146d9b5 100644
--- a/docker-compose.admin.yml
+++ b/docker-compose.admin.yml
@@ -16,8 +16,8 @@ services:
extra_hosts:
- "mirror:host-gateway"
args:
- DOTNET_SDK_IMAGE: ${DOTNET_SDK_IMAGE:-171.22.25.73:8087/dotnet/sdk:10.0}
- DOTNET_ASPNET_IMAGE: ${DOTNET_ASPNET_IMAGE:-171.22.25.73:8087/dotnet/aspnet:10.0}
+ DOTNET_SDK_IMAGE: ${DOTNET_SDK_IMAGE:-mirror.soroushasadi.com/dotnet/sdk:10.0}
+ DOTNET_ASPNET_IMAGE: ${DOTNET_ASPNET_IMAGE:-mirror.soroushasadi.com/dotnet/aspnet:10.0}
container_name: meezi-admin-api
restart: unless-stopped
depends_on:
@@ -52,8 +52,8 @@ services:
extra_hosts:
- "mirror:host-gateway"
args:
- NODE_IMAGE: ${NODE_IMAGE:-171.22.25.73:8087/node:20-alpine}
- NPM_REGISTRY: ${NPM_REGISTRY:-http://171.22.25.73:8081/repository/npm-group/}
+ NODE_IMAGE: ${NODE_IMAGE:-mirror.soroushasadi.com/node:20-alpine}
+ NPM_REGISTRY: ${NPM_REGISTRY:-https://mirror.soroushasadi.com/repository/npm-group/}
NEXT_PUBLIC_ADMIN_API_URL: ${NEXT_PUBLIC_ADMIN_API_URL:-http://localhost:5081}
container_name: meezi-admin-web
restart: unless-stopped
diff --git a/docker-compose.mirror.yml b/docker-compose.mirror.yml
index c185e4c..68e9c7a 100644
--- a/docker-compose.mirror.yml
+++ b/docker-compose.mirror.yml
@@ -6,10 +6,10 @@
# ./mirrors/nexus/provision.sh # creates all proxy repos + enables anon access
#
# Endpoints (after provisioning):
-# UI → http://SERVER_IP:8081 (admin / see provision.sh output)
-# NuGet → http://SERVER_IP:8081/repository/nuget-proxy/index.json
-# npm → http://SERVER_IP:8081/repository/npm-proxy/
-# Docker → http://SERVER_IP:5000 (add to /etc/docker/daemon.json)
+# UI → https://mirror.soroushasadi.com/ (admin / see provision.sh output)
+# NuGet → https://mirror.soroushasadi.com/repository/nuget-group/index.json
+# npm → https://mirror.soroushasadi.com/repository/npm-group/
+# Docker → https://mirror.soroushasadi.com (add to daemon.json registry-mirrors)
#
# Memory: needs ~2 GB JVM heap — recommended on a server with 4 GB+ total RAM.
# Adjust INSTALL4J_ADD_VM_PARAMS below if your server has more/less RAM.
diff --git a/docker-compose.yml b/docker-compose.yml
index bc5c5e7..66cc9aa 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,12 +1,11 @@
# Meezi — main stack (Postgres, Redis, API, Dashboard, Website, Koja)
#
-# All images/packages served from local Nexus at 171.22.25.73:
-# Docker images → 171.22.25.73:8087 (docker-group connector: proxies Docker Hub + MCR)
-# NuGet → http://171.22.25.73:8081/repository/nuget-group/
-# npm → http://171.22.25.73:8081/repository/npm-group/
+# All images/packages served from Nexus at mirror.soroushasadi.com:
+# Docker images → mirror.soroushasadi.com (docker-group: Docker Hub + MCR)
+# NuGet → https://mirror.soroushasadi.com/repository/nuget-group/
+# npm → https://mirror.soroushasadi.com/repository/npm-group/
#
-# Docker Desktop: add "insecure-registries": ["171.22.25.73:8087"] to daemon.json
-# (8087 is the Nexus Docker connector port; it serves images at the root path)
+# Docker Desktop: merge docker/daemon-registry-mirror.example.json into daemon.json
#
# Local dev:
# cp .env.example .env
@@ -26,7 +25,7 @@
services:
postgres:
- image: ${POSTGRES_IMAGE:-171.22.25.73:8087/postgres:16-alpine}
+ image: ${POSTGRES_IMAGE:-mirror.soroushasadi.com/postgres:16-alpine}
container_name: meezi-db
restart: unless-stopped
environment:
@@ -44,7 +43,7 @@ services:
retries: 10
redis:
- image: ${REDIS_IMAGE:-171.22.25.73:8087/redis:7-alpine}
+ image: ${REDIS_IMAGE:-mirror.soroushasadi.com/redis:7-alpine}
container_name: meezi-redis
restart: unless-stopped
ports:
@@ -65,8 +64,8 @@ services:
extra_hosts:
- "mirror:host-gateway"
args:
- DOTNET_SDK_IMAGE: ${DOTNET_SDK_IMAGE:-171.22.25.73:8087/dotnet/sdk:10.0}
- DOTNET_ASPNET_IMAGE: ${DOTNET_ASPNET_IMAGE:-171.22.25.73:8087/dotnet/aspnet:10.0}
+ DOTNET_SDK_IMAGE: ${DOTNET_SDK_IMAGE:-mirror.soroushasadi.com/dotnet/sdk:10.0}
+ DOTNET_ASPNET_IMAGE: ${DOTNET_ASPNET_IMAGE:-mirror.soroushasadi.com/dotnet/aspnet:10.0}
container_name: meezi-api
restart: unless-stopped
depends_on:
@@ -111,8 +110,8 @@ services:
extra_hosts:
- "mirror:host-gateway"
args:
- NODE_IMAGE: ${NODE_IMAGE:-171.22.25.73:8087/node:20-alpine}
- NPM_REGISTRY: ${NPM_REGISTRY:-http://171.22.25.73:8081/repository/npm-group/}
+ NODE_IMAGE: ${NODE_IMAGE:-mirror.soroushasadi.com/node:20-alpine}
+ NPM_REGISTRY: ${NPM_REGISTRY:-https://mirror.soroushasadi.com/repository/npm-group/}
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:5080}
container_name: meezi-web
restart: unless-stopped
@@ -132,8 +131,8 @@ services:
extra_hosts:
- "mirror:host-gateway"
args:
- NODE_IMAGE: ${NODE_IMAGE:-171.22.25.73:8087/node:20-alpine}
- NPM_REGISTRY: ${NPM_REGISTRY:-http://171.22.25.73:8081/repository/npm-group/}
+ NODE_IMAGE: ${NODE_IMAGE:-mirror.soroushasadi.com/node:20-alpine}
+ NPM_REGISTRY: ${NPM_REGISTRY:-https://mirror.soroushasadi.com/repository/npm-group/}
MEEZI_API_URL: http://api:8080
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-http://localhost:3010}
container_name: meezi-website
@@ -156,8 +155,8 @@ services:
extra_hosts:
- "mirror:host-gateway"
args:
- NODE_IMAGE: ${NODE_IMAGE:-171.22.25.73:8087/node:20-alpine}
- NPM_REGISTRY: ${NPM_REGISTRY:-http://171.22.25.73:8081/repository/npm-group/}
+ NODE_IMAGE: ${NODE_IMAGE:-mirror.soroushasadi.com/node:20-alpine}
+ NPM_REGISTRY: ${NPM_REGISTRY:-https://mirror.soroushasadi.com/repository/npm-group/}
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:5080}
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_KOJA_URL:-http://localhost:3103}
container_name: meezi-koja
diff --git a/docker/admin-api/Dockerfile b/docker/admin-api/Dockerfile
index 7883b1f..de6928b 100644
--- a/docker/admin-api/Dockerfile
+++ b/docker/admin-api/Dockerfile
@@ -1,11 +1,11 @@
-ARG DOTNET_SDK_IMAGE=171.22.25.73:8087/dotnet/sdk:10.0
-ARG DOTNET_ASPNET_IMAGE=171.22.25.73:8087/dotnet/aspnet:10.0
+ARG DOTNET_SDK_IMAGE=mirror.soroushasadi.com/dotnet/sdk:10.0
+ARG DOTNET_ASPNET_IMAGE=mirror.soroushasadi.com/dotnet/aspnet:10.0
FROM ${DOTNET_SDK_IMAGE} AS build
WORKDIR /src
COPY global.json Directory.Build.props Directory.Packages.props ./
-# nuget.docker.config points to local Nexus mirror (171.22.25.73:8081)
+# nuget.docker.config points to Nexus mirror (mirror.soroushasadi.com)
COPY nuget.docker.config ./nuget.config
COPY src/Meezi.Shared/Meezi.Shared.csproj src/Meezi.Shared/
diff --git a/docker/admin-web/Dockerfile b/docker/admin-web/Dockerfile
index 771b015..3d3c085 100644
--- a/docker/admin-web/Dockerfile
+++ b/docker/admin-web/Dockerfile
@@ -1,9 +1,9 @@
-ARG NODE_IMAGE=171.22.25.73:8087/node:20-alpine
+ARG NODE_IMAGE=mirror.soroushasadi.com/node:20-alpine
FROM ${NODE_IMAGE} AS deps
WORKDIR /app
COPY web/admin/package*.json ./
-ARG NPM_REGISTRY=http://171.22.25.73:8081/repository/npm-group/
+ARG NPM_REGISTRY=https://mirror.soroushasadi.com/repository/npm-group/
# Install deps then ensure Alpine (musl) SWC binary is present
RUN npm install --legacy-peer-deps --ignore-scripts --registry ${NPM_REGISTRY} \
&& NEXT_VER=$(node -e "process.stdout.write(require('./node_modules/next/package.json').version)") \
diff --git a/docker/api/Dockerfile b/docker/api/Dockerfile
index 8142f77..70f299d 100644
--- a/docker/api/Dockerfile
+++ b/docker/api/Dockerfile
@@ -1,11 +1,11 @@
-ARG DOTNET_SDK_IMAGE=171.22.25.73:8087/dotnet/sdk:10.0
-ARG DOTNET_ASPNET_IMAGE=171.22.25.73:8087/dotnet/aspnet:10.0
+ARG DOTNET_SDK_IMAGE=mirror.soroushasadi.com/dotnet/sdk:10.0
+ARG DOTNET_ASPNET_IMAGE=mirror.soroushasadi.com/dotnet/aspnet:10.0
FROM ${DOTNET_SDK_IMAGE} AS build
WORKDIR /src
COPY global.json Directory.Build.props Directory.Packages.props ./
-# nuget.docker.config points to local Nexus mirror (171.22.25.73:8081)
+# nuget.docker.config points to Nexus mirror (mirror.soroushasadi.com)
COPY nuget.docker.config ./nuget.config
COPY src/Meezi.Shared/Meezi.Shared.csproj src/Meezi.Shared/
diff --git a/docker/daemon-registry-mirror.example.json b/docker/daemon-registry-mirror.example.json
index b314262..92ca33a 100644
--- a/docker/daemon-registry-mirror.example.json
+++ b/docker/daemon-registry-mirror.example.json
@@ -1,8 +1,5 @@
{
- "insecure-registries": [
- "171.22.25.73:8087"
- ],
"registry-mirrors": [
- "http://171.22.25.73:8087"
+ "https://mirror.soroushasadi.com"
]
}
diff --git a/docker/koja/Dockerfile b/docker/koja/Dockerfile
index 6efb033..6541fe9 100644
--- a/docker/koja/Dockerfile
+++ b/docker/koja/Dockerfile
@@ -1,9 +1,9 @@
-ARG NODE_IMAGE=171.22.25.73:8087/node:20-alpine
+ARG NODE_IMAGE=mirror.soroushasadi.com/node:20-alpine
FROM ${NODE_IMAGE} AS deps
WORKDIR /app
COPY web/koja/package*.json ./
-ARG NPM_REGISTRY=http://171.22.25.73:8081/repository/npm-group/
+ARG NPM_REGISTRY=https://mirror.soroushasadi.com/repository/npm-group/
RUN npm install --legacy-peer-deps --ignore-scripts --registry ${NPM_REGISTRY}
FROM ${NODE_IMAGE} AS builder
diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile
index cb4c2a9..ecb572e 100644
--- a/docker/web/Dockerfile
+++ b/docker/web/Dockerfile
@@ -1,9 +1,9 @@
-ARG NODE_IMAGE=171.22.25.73:8087/node:20-alpine
+ARG NODE_IMAGE=mirror.soroushasadi.com/node:20-alpine
FROM ${NODE_IMAGE} AS deps
WORKDIR /app
COPY web/dashboard/package*.json ./
-ARG NPM_REGISTRY=http://171.22.25.73:8081/repository/npm-group/
+ARG NPM_REGISTRY=https://mirror.soroushasadi.com/repository/npm-group/
RUN npm install --legacy-peer-deps --ignore-scripts --registry ${NPM_REGISTRY}
FROM ${NODE_IMAGE} AS builder
diff --git a/docker/website/Dockerfile b/docker/website/Dockerfile
index fce0327..9a5ac91 100644
--- a/docker/website/Dockerfile
+++ b/docker/website/Dockerfile
@@ -1,9 +1,9 @@
-ARG NODE_IMAGE=171.22.25.73:8087/node:20-alpine
+ARG NODE_IMAGE=mirror.soroushasadi.com/node:20-alpine
FROM ${NODE_IMAGE} AS deps
WORKDIR /app
COPY web/website/package*.json ./
-ARG NPM_REGISTRY=http://171.22.25.73:8081/repository/npm-group/
+ARG NPM_REGISTRY=https://mirror.soroushasadi.com/repository/npm-group/
# Install deps then ensure Alpine (musl) SWC binary is present
RUN npm install --legacy-peer-deps --ignore-scripts --registry ${NPM_REGISTRY} \
&& NEXT_VER=$(node -e "process.stdout.write(require('./node_modules/next/package.json').version)") \
diff --git a/mirrors/nexus/add-liara-mirrors.sh b/mirrors/nexus/add-liara-mirrors.sh
index 0a17aa8..12f541a 100644
--- a/mirrors/nexus/add-liara-mirrors.sh
+++ b/mirrors/nexus/add-liara-mirrors.sh
@@ -136,18 +136,18 @@ echo "════════════════════════
echo "🎉 Done!"
echo "═══════════════════════════════════════════════════════════════"
echo ""
-echo " npm-group → http://SERVER:8081/repository/npm-group/"
+echo " npm-group → https://mirror.soroushasadi.com/repository/npm-group/"
echo " Liara first, Runflare as fallback"
echo ""
-echo " pypi-group → http://SERVER:8081/repository/pypi-group/"
+echo " pypi-group → https://mirror.soroushasadi.com/repository/pypi-group/"
echo " Liara first, Runflare as fallback"
echo ""
-echo " Ubuntu APT → http://SERVER:8081/repository/ubuntu-proxy/"
+echo " Ubuntu APT → https://mirror.soroushasadi.com/repository/ubuntu-proxy/"
echo " distribution: $UBUNTU_DIST"
-echo " security: http://SERVER:8081/repository/ubuntu-security-proxy/"
+echo " security: https://mirror.soroushasadi.com/repository/ubuntu-security-proxy/"
echo ""
echo "To use Ubuntu APT in a Dockerfile:"
-echo " RUN echo 'deb http://SERVER:8081/repository/ubuntu-proxy/ $UBUNTU_DIST main restricted universe' > /etc/apt/sources.list && \\"
-echo " echo 'deb http://SERVER:8081/repository/ubuntu-security-proxy/ $UBUNTU_DIST-security main restricted universe' >> /etc/apt/sources.list && \\"
+echo " RUN echo 'deb https://mirror.soroushasadi.com/repository/ubuntu-proxy/ $UBUNTU_DIST main restricted universe' > /etc/apt/sources.list && \\"
+echo " echo 'deb https://mirror.soroushasadi.com/repository/ubuntu-security-proxy/ $UBUNTU_DIST-security main restricted universe' >> /etc/apt/sources.list && \\"
echo " apt-get update"
echo ""
diff --git a/mirrors/nexus/provision.sh b/mirrors/nexus/provision.sh
index 7b91466..1ec68c5 100644
--- a/mirrors/nexus/provision.sh
+++ b/mirrors/nexus/provision.sh
@@ -176,12 +176,12 @@ echo "════════════════════════
echo "🎉 Nexus provisioned!"
echo "═══════════════════════════════════════════════════════════════"
echo ""
-echo " UI → http://$(hostname -I | awk '{print $1}'):8081"
+echo " UI → https://mirror.soroushasadi.com/"
echo " admin / $ADMIN_PASS"
echo ""
-echo " NuGet → http://$(hostname -I | awk '{print $1}'):8081/repository/nuget-proxy/index.json"
-echo " npm → http://$(hostname -I | awk '{print $1}'):8081/repository/npm-proxy/"
-echo " Docker → http://$(hostname -I | awk '{print $1}'):8083 ← upstream: $DOCKER_UPSTREAM"
+echo " NuGet → https://mirror.soroushasadi.com/repository/nuget-group/index.json"
+echo " npm → https://mirror.soroushasadi.com/repository/npm-group/"
+echo " Docker → https://mirror.soroushasadi.com ← upstream: $DOCKER_UPSTREAM"
echo ""
if [ -z "$DOCKER_USER" ]; then
echo " 💡 To switch Docker upstream to Liara mirror (faster in Iran):"
@@ -194,7 +194,7 @@ if [ -z "$DOCKER_USER" ]; then
echo ""
fi
echo "To activate Docker Hub mirror on this server:"
-echo " Edit /etc/docker/daemon.json:"
-echo ' { "insecure-registries": ["'"$(hostname -I | awk '{print $1}'):8083"'"], "registry-mirrors": ["http://'"$(hostname -I | awk '{print $1}'):8083"'"] }'
+echo " Merge docker/daemon-registry-mirror.example.json into /etc/docker/daemon.json"
+echo ' { "registry-mirrors": ["https://mirror.soroushasadi.com"] }'
echo " systemctl restart docker"
echo ""
diff --git a/nuget.docker.config b/nuget.docker.config
index fd102e9..9c1bf4e 100644
--- a/nuget.docker.config
+++ b/nuget.docker.config
@@ -1,12 +1,11 @@
-
+
+ value="https://mirror.soroushasadi.com/repository/nuget-group/index.json"
+ protocolVersion="3" />
diff --git a/nuget.mirror.config b/nuget.mirror.config
index bd177cf..ef0b6cc 100644
--- a/nuget.mirror.config
+++ b/nuget.mirror.config
@@ -8,7 +8,7 @@
-
+
diff --git a/src/Meezi.API/Controllers/AuditController.cs b/src/Meezi.API/Controllers/AuditController.cs
new file mode 100644
index 0000000..a7c1324
--- /dev/null
+++ b/src/Meezi.API/Controllers/AuditController.cs
@@ -0,0 +1,91 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Meezi.API.Models.Audit;
+using Meezi.Core.Authorization;
+using Meezi.Core.Interfaces;
+using Meezi.Infrastructure.Data;
+using Meezi.Shared;
+
+namespace Meezi.API.Controllers;
+
+///
+/// Read-only access to the immutable POS / management audit trail. Gated by
+/// ; branch-scoped sessions only ever see
+/// their own branch's entries (enforced by the DB-level branch isolation filter),
+/// café-wide owners see everything.
+///
+[Route("api/cafes/{cafeId}/audit-logs")]
+public class AuditController : CafeApiControllerBase
+{
+ private const int MaxPageSize = 100;
+
+ private readonly AppDbContext _db;
+
+ public AuditController(AppDbContext db)
+ {
+ _db = db;
+ }
+
+ [HttpGet]
+ public async Task List(
+ string cafeId,
+ ITenantContext tenant,
+ CancellationToken ct,
+ [FromQuery] string? category = null,
+ [FromQuery] string? action = null,
+ [FromQuery] string? branchId = null,
+ [FromQuery] string? entityType = null,
+ [FromQuery] string? entityId = null,
+ [FromQuery] DateTime? from = null,
+ [FromQuery] DateTime? to = null,
+ [FromQuery] int page = 1,
+ [FromQuery] int pageSize = 50)
+ {
+ if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
+ if (EnsurePermission(tenant, Permission.ViewReports) is { } forbidden) return forbidden;
+
+ if (page < 1) page = 1;
+ if (pageSize < 1) pageSize = 50;
+ if (pageSize > MaxPageSize) pageSize = MaxPageSize;
+
+ var query = _db.AuditLogs.AsNoTracking().Where(x => x.CafeId == cafeId);
+
+ if (!string.IsNullOrWhiteSpace(category))
+ query = query.Where(x => x.Category == category);
+ if (!string.IsNullOrWhiteSpace(action))
+ query = query.Where(x => x.Action == action);
+ if (!string.IsNullOrWhiteSpace(branchId))
+ query = query.Where(x => x.BranchId == branchId);
+ if (!string.IsNullOrWhiteSpace(entityType))
+ query = query.Where(x => x.EntityType == entityType);
+ if (!string.IsNullOrWhiteSpace(entityId))
+ query = query.Where(x => x.EntityId == entityId);
+ if (from is { } f)
+ query = query.Where(x => x.CreatedAt >= f);
+ if (to is { } t)
+ query = query.Where(x => x.CreatedAt <= t);
+
+ var total = await query.CountAsync(ct);
+
+ var items = await query
+ .OrderByDescending(x => x.CreatedAt)
+ .Skip((page - 1) * pageSize)
+ .Take(pageSize)
+ .Select(x => new AuditLogDto(
+ x.Id,
+ x.Category,
+ x.Action,
+ x.EntityType,
+ x.EntityId,
+ x.BranchId,
+ x.ActorId,
+ x.ActorName,
+ x.ActorRole,
+ x.Summary,
+ x.DetailsJson,
+ x.CreatedAt))
+ .ToListAsync(ct);
+
+ return Ok(new PagedApiResponse(true, items, new PagedMeta(total, page, pageSize)));
+ }
+}
diff --git a/src/Meezi.API/Controllers/AuthController.cs b/src/Meezi.API/Controllers/AuthController.cs
index 529fb8f..5d089a6 100644
--- a/src/Meezi.API/Controllers/AuthController.cs
+++ b/src/Meezi.API/Controllers/AuthController.cs
@@ -90,6 +90,27 @@ public class AuthController : ControllerBase
return Ok(new ApiResponse(true, data));
}
+ [HttpPost("switch-branch")]
+ [Authorize]
+ [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)]
+ public async Task SwitchBranch([FromBody] SwitchBranchRequest request, CancellationToken cancellationToken)
+ {
+ var userId = User.FindFirstValue(JwtRegisteredClaimNames.Sub)
+ ?? User.FindFirstValue(ClaimTypes.NameIdentifier);
+ if (string.IsNullOrEmpty(userId))
+ return Unauthorized();
+
+ var cafeId = User.FindFirstValue(MeeziClaimTypes.CafeId);
+ if (string.IsNullOrEmpty(cafeId))
+ return Unauthorized();
+
+ var (success, data, code, message) = await _authService.SwitchBranchAsync(userId, cafeId, request.BranchId, cancellationToken);
+ if (!success)
+ return ErrorResult(code!, message!);
+
+ return Ok(new ApiResponse(true, data));
+ }
+
[HttpPost("refresh")]
[ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)]
public async Task Refresh([FromBody] RefreshTokenRequest request, CancellationToken cancellationToken)
@@ -178,6 +199,8 @@ public class AuthController : ControllerBase
new ApiResponse