Compare commits
30 Commits
backup-mai
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
2e372d1aae | ||
|
1496eefc14 | ||
|
e93b5e653a | ||
|
8fa28a31ce | ||
|
64da6f4553 | ||
|
5e74f45855 | ||
|
ab8b409725 | ||
|
35ac1ece0e | ||
|
b8a92095d8 | ||
|
9ce6eb5bcc | ||
|
ee243f7d20 | ||
|
9edb207991 | ||
|
e060d942f0 | ||
|
c09862c702 | ||
|
fdfbce506e | ||
|
f16e874f31 | ||
|
8d05864c15 | ||
|
90f1750945 | ||
|
abe4a3c883 | ||
|
519df326ce | ||
|
3d4499fb80 | ||
|
a27c335113 | ||
|
199234a7e2 | ||
|
95a00c63ea | ||
8a85724baf | |||
|
b25a83b164 | ||
23357f0934 | |||
|
83ea63dde4 | ||
efd4be35f7 | |||
|
b6e56b0f83 |
@ -12,7 +12,7 @@ steps:
|
|||||||
auto_tag: true
|
auto_tag: true
|
||||||
registry: git.autonomic.zone
|
registry: git.autonomic.zone
|
||||||
dockerfile: ./Dockerfile
|
dockerfile: ./Dockerfile
|
||||||
repo: git.autonomic.zone/autonomic-cooperative/nextjs
|
repo: git.autonomic.zone/autonomic-cooperative/nextload
|
||||||
|
|
||||||
- name: deploy stack
|
- name: deploy stack
|
||||||
image: git.coopcloud.tech/coop-cloud/stack-ssh-deploy:latest
|
image: git.coopcloud.tech/coop-cloud/stack-ssh-deploy:latest
|
||||||
|
@ -44,5 +44,6 @@ ENV PNPM_HOME="/pnpm"
|
|||||||
ENV PATH="$PNPM_HOME:$PATH"
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
CMD ["pnpm", "start:standalone"]
|
CMD ["pnpm", "start:standalone"]
|
||||||
|
49
Makefile
Normal file
49
Makefile
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
.PHONY: sync_db
|
||||||
|
|
||||||
|
# Define variables
|
||||||
|
REMOTE_USER=tma
|
||||||
|
REMOTE_SERVER=swarm-demo.autonomic.zone
|
||||||
|
REMOTE_PORT=222
|
||||||
|
REMOTE_CONTAINER_PATH=/data/db/mongodump
|
||||||
|
LOCAL_PATH=/tmp/mongodump
|
||||||
|
LOCAL_DB=test
|
||||||
|
LOCAL_CONTAINER_NAME=nextload-mongo-1
|
||||||
|
REMOTE_VOLUME_NAME = nextload-demo_autonomic_zone_payload_uploads
|
||||||
|
LOCAL_VOLUME_NAME = nextload_payload_uploads
|
||||||
|
ENV_FILE=.env
|
||||||
|
|
||||||
|
include $(ENV_FILE)
|
||||||
|
|
||||||
|
sync_db:
|
||||||
|
@echo "Step 1: Dump the database on production"
|
||||||
|
docker --context swarm-demo.autonomic.zone exec -it $$(docker --context swarm-demo.autonomic.zone ps -q -f name=nextload-demo_autonomic_zone_mongo) \
|
||||||
|
bash -c 'rm -rf $(REMOTE_CONTAINER_PATH) && mongodump -u mongo -p "$$(cat /run/secrets/mongo_password)" -o $(REMOTE_CONTAINER_PATH) && ls -l $(REMOTE_CONTAINER_PATH)'
|
||||||
|
|
||||||
|
@echo "Step 2: Copy the dump from the remote MongoDB container to the local machine"
|
||||||
|
rm -rf $(LOCAL_PATH)
|
||||||
|
mkdir -p $(LOCAL_PATH) # Create the target directory if it doesn't exist
|
||||||
|
ssh -p $(REMOTE_PORT) $(REMOTE_USER)@$(REMOTE_SERVER) \
|
||||||
|
"docker exec $$(docker --context swarm-demo.autonomic.zone ps -q -f name=nextload-demo_autonomic_zone_mongo) \
|
||||||
|
tar -cC $(REMOTE_CONTAINER_PATH) ." | tar -xC $(LOCAL_PATH)
|
||||||
|
|
||||||
|
@echo "Step 3: Copy the dump from local machine to MongoDB container"
|
||||||
|
docker cp $(LOCAL_PATH)/ $(LOCAL_CONTAINER_NAME):/tmp/mongodump
|
||||||
|
|
||||||
|
@echo "Step 4: Drop the existing local database and restore the dump"
|
||||||
|
docker exec -it $(LOCAL_CONTAINER_NAME) mongorestore --drop --username $(MONGO_USER) --password $(MONGO_PASSWORD) --authenticationDatabase admin --db $(LOCAL_DB) /tmp/mongodump/$(LOCAL_DB)
|
||||||
|
|
||||||
|
sync_media:
|
||||||
|
@echo "Step 1: Create a tar archive of the remote Docker volume"
|
||||||
|
rm -rf /tmp/$(REMOTE_VOLUME_NAME)
|
||||||
|
mkdir -p /tmp/$(REMOTE_VOLUME_NAME)
|
||||||
|
ssh -p $(REMOTE_PORT) $(REMOTE_USER)@$(REMOTE_SERVER) \
|
||||||
|
"docker run --rm -v $(REMOTE_VOLUME_NAME):/volume -v /tmp:/backup alpine tar -czf /backup/$(REMOTE_VOLUME_NAME).tar.gz -C /volume ."
|
||||||
|
|
||||||
|
@echo "Step 2: Copy the media from remote volume to local volume"
|
||||||
|
scp -P $(REMOTE_PORT) $(REMOTE_USER)@$(REMOTE_SERVER):/tmp/$(REMOTE_VOLUME_NAME).tar.gz /tmp/$(REMOTE_VOLUME_NAME).tar.gz
|
||||||
|
docker run --rm -v /tmp:/volume -v $(LOCAL_VOLUME_NAME):/backup alpine tar -xzf /volume/$(REMOTE_VOLUME_NAME).tar.gz -C /backup
|
||||||
|
|
||||||
|
@echo "Step 3: Cleanup temporary files"
|
||||||
|
rm /tmp/$(REMOTE_VOLUME_NAME).tar.gz
|
||||||
|
|
||||||
|
@echo "Media synchronization complete."
|
@ -4,6 +4,7 @@ version: "3.8"
|
|||||||
services:
|
services:
|
||||||
nextjs:
|
nextjs:
|
||||||
image: git.autonomic.zone/autonomic-cooperative/nextload:latest
|
image: git.autonomic.zone/autonomic-cooperative/nextload:latest
|
||||||
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- "NAME=${STACK_NAME}"
|
- "NAME=${STACK_NAME}"
|
||||||
- "PAYLOAD_SECRET_FILE=/run/secrets/payload_secret"
|
- "PAYLOAD_SECRET_FILE=/run/secrets/payload_secret"
|
||||||
@ -19,7 +20,7 @@ services:
|
|||||||
- mongo_password
|
- mongo_password
|
||||||
- payload_secret
|
- payload_secret
|
||||||
volumes:
|
volumes:
|
||||||
- payload_uploads:/runner/.next/standalone/.next/media
|
- payload_uploads:/prod/.next/standalone/media
|
||||||
networks:
|
networks:
|
||||||
- proxy
|
- proxy
|
||||||
- internal
|
- internal
|
||||||
|
@ -18,7 +18,7 @@ services:
|
|||||||
- "HOSTNAME=0.0.0.0"
|
- "HOSTNAME=0.0.0.0"
|
||||||
- "MONGODB_URI=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@mongo:27017"
|
- "MONGODB_URI=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@mongo:27017"
|
||||||
volumes:
|
volumes:
|
||||||
- /base/media
|
- payload_uploads:/base/media
|
||||||
- ./:/base
|
- ./:/base
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
|
@ -11,7 +11,7 @@ const nextConfig = {
|
|||||||
HOSTNAME: process.env.HOSTNAME,
|
HOSTNAME: process.env.HOSTNAME,
|
||||||
},
|
},
|
||||||
// Disable minification & chunking for debugging
|
// Disable minification & chunking for debugging
|
||||||
/* webpack(config, { dev }) {
|
webpack(config, { dev }) {
|
||||||
config.optimization.minimize = false
|
config.optimization.minimize = false
|
||||||
config.optimization.splitChunks = {
|
config.optimization.splitChunks = {
|
||||||
cacheGroups: {
|
cacheGroups: {
|
||||||
@ -20,7 +20,7 @@ const nextConfig = {
|
|||||||
}
|
}
|
||||||
config.optimization.runtimeChunk = false
|
config.optimization.runtimeChunk = false
|
||||||
return config
|
return config
|
||||||
}, */
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withPayload(nextConfig)
|
export default withPayload(nextConfig)
|
||||||
|
@ -37,7 +37,7 @@ export default buildConfig({
|
|||||||
collections: [Users, Posts, Authors, Media, Pages],
|
collections: [Users, Posts, Authors, Media, Pages],
|
||||||
admin: {
|
admin: {
|
||||||
autoLogin: {
|
autoLogin: {
|
||||||
email: 'dev@payloadcms.com',
|
email: 'admin@nextload.test',
|
||||||
password: 'test',
|
password: 'test',
|
||||||
prefillOnly: true,
|
prefillOnly: true,
|
||||||
},
|
},
|
||||||
@ -60,14 +60,14 @@ export default buildConfig({
|
|||||||
async onInit(payload) {
|
async onInit(payload) {
|
||||||
const existingUsers = await payload.find({
|
const existingUsers = await payload.find({
|
||||||
collection: 'users',
|
collection: 'users',
|
||||||
limit: 1,
|
limit: 2,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (existingUsers.docs.length === 0) {
|
if (existingUsers.docs.length === 0 || existingUsers.docs.length === 1) {
|
||||||
await payload.create({
|
await payload.create({
|
||||||
collection: 'users',
|
collection: 'users',
|
||||||
data: {
|
data: {
|
||||||
email: 'dev@payloadcms.com',
|
email: 'admin@nextload.test',
|
||||||
password: 'test',
|
password: 'test',
|
||||||
roles: ['admin'],
|
roles: ['admin'],
|
||||||
},
|
},
|
||||||
|
@ -7,8 +7,7 @@ import { notFound } from 'next/navigation'
|
|||||||
|
|
||||||
const PreviewCatchAllPage = async ({ params }: { params: { path: string[] } }) => {
|
const PreviewCatchAllPage = async ({ params }: { params: { path: string[] } }) => {
|
||||||
noStore()
|
noStore()
|
||||||
const [user, page] = await Promise.all([
|
const [page] = await Promise.all([
|
||||||
getCurrentUser(),
|
|
||||||
getDocument({
|
getDocument({
|
||||||
collection: COLLECTION_SLUG_PAGE,
|
collection: COLLECTION_SLUG_PAGE,
|
||||||
path: params.path,
|
path: params.path,
|
||||||
@ -16,7 +15,8 @@ const PreviewCatchAllPage = async ({ params }: { params: { path: string[] } }) =
|
|||||||
cache: false,
|
cache: false,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
if (!user || !page) notFound()
|
if (!page) notFound()
|
||||||
|
|
||||||
return <PreviewBlocks initialData={page} locale="" url={process.env.BASE_URL || ''} />
|
return <PreviewBlocks initialData={page} locale="" url={process.env.BASE_URL || ''} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,7 @@ import PreviewPostPage from '@/components/PreviewPostPage'
|
|||||||
|
|
||||||
const PreviewCatchAllPage = async ({ params }: { params: { path: string[] } }) => {
|
const PreviewCatchAllPage = async ({ params }: { params: { path: string[] } }) => {
|
||||||
noStore()
|
noStore()
|
||||||
const [user, page] = await Promise.all([
|
const [page] = await Promise.all([
|
||||||
getCurrentUser(),
|
|
||||||
getDocument({
|
getDocument({
|
||||||
collection: COLLECTION_SLUG_POST,
|
collection: COLLECTION_SLUG_POST,
|
||||||
path: params.path,
|
path: params.path,
|
||||||
@ -17,7 +16,7 @@ const PreviewCatchAllPage = async ({ params }: { params: { path: string[] } }) =
|
|||||||
cache: false,
|
cache: false,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
if (!user || !page) notFound()
|
if (!page) notFound()
|
||||||
|
|
||||||
return <PreviewPostPage initialData={page} locale="" url={process.env.BASE_URL || ''} />
|
return <PreviewPostPage initialData={page} locale="" url={process.env.BASE_URL || ''} />
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,11 @@ import { Access } from 'payload/types'
|
|||||||
import type { User } from 'types/payload-types'
|
import type { User } from 'types/payload-types'
|
||||||
|
|
||||||
export const isAdmin = ({ req: { user } }: any) => {
|
export const isAdmin = ({ req: { user } }: any) => {
|
||||||
if (user && user.roles?.includes('admin')) {
|
if (!user || !user.roles) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.roles?.includes('admin')) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10,7 +14,11 @@ export const isAdmin = ({ req: { user } }: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isAdminOrCreatedBy = ({ req: { user } }: any) => {
|
export const isAdminOrCreatedBy = ({ req: { user } }: any) => {
|
||||||
if (user && user.role === 'admin') {
|
if (!user || !user.roles) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.roles?.includes('admin')) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,24 +34,27 @@ export const isAdminOrCreatedBy = ({ req: { user } }: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isAdminOrSelf = ({ req: { user } }: any) => {
|
export const isAdminOrSelf = ({ req: { user } }: any) => {
|
||||||
if (user) {
|
if (!user || !user.roles) {
|
||||||
if (user.roles?.includes('admin')) {
|
return false
|
||||||
return true
|
}
|
||||||
}
|
|
||||||
|
if (user.roles?.includes('admin')) {
|
||||||
// Non-admin: can only access themselves
|
return true
|
||||||
return {
|
}
|
||||||
id: {
|
|
||||||
equals: user.id,
|
// Non-admin: can only access themselves
|
||||||
},
|
return {
|
||||||
}
|
id: {
|
||||||
|
equals: user.id,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isAdminOrPublished = ({ req: { user } }: any) => {
|
export const isAdminOrPublished = ({ req: { user } }: any) => {
|
||||||
if (user && user?.role === 'admin') {
|
if (user && user.roles) {
|
||||||
return true
|
if (user.roles?.includes('admin')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -2,7 +2,11 @@ import { Access, FieldAccess } from 'payload/types'
|
|||||||
import type { User } from 'types/payload-types'
|
import type { User } from 'types/payload-types'
|
||||||
|
|
||||||
export const isEditor = ({ req: { user } }: any) => {
|
export const isEditor = ({ req: { user } }: any) => {
|
||||||
if (user && user?.roles?.some((role: string) => ['editor', 'admin'].includes(role))) {
|
if (!user || !user.roles) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user?.roles?.some((role: string) => ['editor', 'admin'].includes(role))) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ import { Access, FieldAccess } from 'payload/types'
|
|||||||
import type { User } from 'types/payload-types'
|
import type { User } from 'types/payload-types'
|
||||||
|
|
||||||
export const isUser = ({ req: { user } }: any) => {
|
export const isUser = ({ req: { user } }: any) => {
|
||||||
if (user && user?.roles?.some((role: string) => ['user', 'editor', 'admin'].includes(role))) {
|
if (!user || !user.roles) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user?.roles?.some((role: string) => ['user', 'editor', 'admin'].includes(role))) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { getPayloadHMR } from '@payloadcms/next/utilities'
|
|
||||||
import configPromise from '@payload-config'
|
|
||||||
|
|
||||||
export const GET = async () => {
|
|
||||||
const payload = await getPayloadHMR({
|
|
||||||
config: configPromise,
|
|
||||||
})
|
|
||||||
|
|
||||||
const data = await payload.find({
|
|
||||||
collection: 'users',
|
|
||||||
})
|
|
||||||
|
|
||||||
return Response.json(data)
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user