尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗מימוש של שלב א׳ (MVP) לפי מסמך האפיון (גרסה 1.0): הרשמה ואזור אישי, אישור משתמשים ורישיונות, יומן זמינות, בקשות הזמנה ואישור מנהל, מניעת הזמנות כפולות, מיילים אוטומטיים, ניהול נהלים, ניהול הרכב והרשאות. הממשק בעברית, מימין לשמאל, ומותאם לטלפון ולמחשב.
דרישות: Node.js 22.13 ומעלה (המערכת משתמשת ב־SQLite המובנה ב־Node, בלי שרת מסד נתונים נפרד), או Docker.
start.cmd./start.shהסקריפט מתקין תלויות, יוצר נתוני דמו, מפעיל את השרת ופותח את https://localhost:3000. בפעם הראשונה הדפדפן יזהיר על התעודה, כי היא תעודה עצמית ל־localhost: בוחרים "מתקדם" ואז "המשך ל־localhost". כניסה: [email protected] / Password1.
start.cmd או npm run dev). בהפעלה מוצגת כתובת הרשת, למשל:
Network: https://192.168.1.23:3000 (other devices on the same Wi-Fi)
allow-wifi.cmd. הקובץ פותח את פורט 3000 ב־Firewall לרשתות פרטיות בלבד ומציג את הכתובות. רשת ה־Wi-Fi צריכה להיות מוגדרת כ־"Private": הגדרות ← רשת ואינטרנט ← Wi-Fi ← הרשת שלך ← רשת פרטית.winget install --id Cloudflare.cloudflared # פעם אחת (macOS: brew install cloudflared)
npm run tunnel # בחלון נוסף, כשהאפליקציה רצה
מוצגת כתובת https://<אקראי>.trycloudflare.com שנגישה מכל מקום, כל עוד שני החלונות פתוחים. אין צורך בחשבון ואין צורך לפתוח פורטים בראוטר.
Password1, שמופיעה ב־README וידועה לכולם. לפני הפרסום צריך להחליף סיסמאות (npm run create-admin -- --email [email protected] --password …), או להתחיל ממסד נתונים חדש בלי נתוני דמו.BASE_URL=<הכתובת> ב־.env ומפעילים מחדש.ngrok http https://localhost:3000 --url=<השם-שלכם>.ngrok-free.app. בשני המקרים מגדירים את BASE_URL לכתובת הקבועה.dev, ראו את המדריך docs/dev-environment.md. לאחסון בחינם (Oracle Cloud Always Free) ראו docs/free-hosting.md. לפריסה ב־Vercel ראו docs/vercel.md. שם מחברים מסד נתונים של Turso (חינם), כדי שהנתונים יישמרו גם אחרי העלאת גרסה חדשה.כשמוגדרים GOOGLE_CLIENT_ID ו־GOOGLE_CLIENT_SECRET, מופיע כפתור "התחברות עם Google" בדפי ההתחברות וההרשמה.
הגדרה (פעם אחת):
https://localhost:3000/auth/google/callback (פיתוח על המחשב)https://<הכתובת-בשרת>/auth/google/callback (למשל https://dev.129-146-10-20.sslip.io/auth/google/callback).env ומפעילים מחדש:
GOOGLE_CLIENT_ID=1234567890-abc.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-...
בדיקת ההגדרה: ב־הגדרות (/admin/settings) יש לוח "התחברות עם Google" שמראה מה מוגדר ומה חסר, את הכתובות המדויקות שצריך להזין ב־Google Cloud Console ואת השגיאה האחרונה.
| מה רואים | הסיבה והפתרון |
|---|---|
| אין כפתור Google | GOOGLE_CLIENT_ID או GOOGLE_CLIENT_SECRET חסרים ב־.env (בלי # בתחילת השורה), או שהשרת לא הופעל מחדש אחרי העריכה |
| במקום כפתור יש הודעה "זמינה בכתובת…" | האתר נפתח בכתובת אחרת מ־BASE_URL (למשל 127.0.0.1 או IP של ה־Wi-Fi). פותחים את הכתובת שבהודעה |
דף שגיאה של Google: redirect_uri_mismatch | ב־Google Cloud Console, תחת Authorized redirect URIs, צריך להופיע בדיוק https://localhost:3000/auth/google/callback (או הכתובת שבלוח ההגדרות) |
| דף שגיאה של Google: "Access blocked" / "has not completed the Google verification process" | מסך ההסכמה במצב Testing: מוסיפים את החשבון תחת Test users, או לוחצים Publish app |
| "הגדרות Google שגויות" | ה־Client ID או ה־Client secret שגויים או הועתקו חלקית |
| "לא ניתן להתחבר לשרתי Google" | למחשב שעליו רץ השרת אין גישה לאינטרנט, או שחומת אש חוסמת אותו |
ההתחברות עם Google עובדת רק בכתובת שב־BASE_URL, כי Google מחזיר את המשתמש בדיוק לכתובת שנרשמה. Google לא מאפשר כתובות IP של הרשת הביתית (למשל 192.168.x.x), אז ממכשירים ב־Wi-Fi מתחברים עם סיסמה או קוד חד־פעמי.
מנהל יכול לפתוח חשבון בלי שהמשתמש יירשם בעצמו: משתמשים ← הוספת משתמש. ממלאים שם, ת"ז, טלפון ודואר אלקטרוני, ואפשר גם תפקיד (משתמש רגיל או מנהל), תאריך תוקף וצילום של רישיון הנהיגה.
ב־רכב ← מסמכי הרכב המנהל מעלה את רישיון הרכב, פוליסות הביטוח (חובה, מקיף / צד ג׳) ומסמכים נוספים, כתמונה או PDF.
English setup guide and reservation notification behavior: Email setup.
בלי SMTP, המיילים לא נשלחים אלא נשמרים ב־data/outbox. כדי שהמשתמשים והמנהלים יקבלו אותם בפועל, כולל אישורי ההזמנה, מגדירים SMTP. לדוגמה עם Gmail:
.env ומפעילים מחדש:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_SECURE=true
[email protected]
SMTP_PASS=abcd efgh ijkl mnop
[email protected]
בדיקה: ב־הגדרות (/admin/settings) יש לוח "שליחת מיילים" שמראה את ההגדרה, את השגיאה האחרונה וכפתור שליחת מייל בדיקה. גם בהפעלת השרת מודפס בחלון אם החיבור לשרת הדואר הצליח ([mail] SMTP OK) או נכשל, ומה הסיבה.
| מה קורה | הסיבה והפתרון |
|---|---|
| קוד ההתחברות לא מגיע, ובדף מופיע "מצב פיתוח" | לא הוגדר SMTP, ולכן המייל לא נשלח בפועל. הקוד מודפס בחלון השרת (>>> Login code for …). כדי לקבל אותו במייל, מגדירים SMTP כמו למעלה |
| "שליחת המייל נכשלה" | הגדרת ה־SMTP שגויה. הסיבה מופיעה בלוח "שליחת מיילים" ובחלון השרת |
Username and Password not accepted / 535 | ב־Gmail צריך App password, לא הסיסמה הרגילה, ואימות דו־שלבי בחשבון חייב להיות מופעל. רווחים בסיסמה לא משנים |
ETIMEDOUT / Greeting never received | פורט שגוי או חסום. ב־Gmail משתמשים ב־465 (SMTP_SECURE נקבע אוטומטית) |
| המייל נשלח אבל לא נמצא | לבדוק בספאם ובלשונית "קידומי מכירות". מבקשים קוד חדש, והקוד הקודם ממשיך לעבוד עד שיפוג (10 דקות) |
מה נשלח כשהזמנה מאושרת: המשתמש מקבל "ההזמנה אושרה" עם פרטי הרכב, המועדים וההנחיות. כל המנהלים הפעילים מקבלים "אישור הזמנה" עם פרטי המזמין ומי אישר. לשני המיילים מצורף זימון ליומן (.ics) שנפתח ב־Google Calendar, Outlook ו־iPhone.
data/certs. בקשת http:// לאותו פורט מועברת ל־https://. כדי להימנע מאזהרת הדפדפן אפשר ליצור תעודה מהימנה עם mkcert (mkcert -install && mkcert localhost 127.0.0.1) ולהגדיר HTTPS_CERT_FILE ו־HTTPS_KEY_FILE בקובץ .env.docker-compose.prod.yml מריץ את Caddy לפני האפליקציה. Caddy מנפיק ומחדש תעודת Let's Encrypt לדומיין שב־DOMAIN ומעביר כל HTTP ל־HTTPS. האפליקציה עצמה מפנה ל־HTTPS כל בקשה שלא הגיעה דרך HTTPS (חוץ מ־/healthz), שולחת HSTS ומסמנת את עוגיית הסשן כ־Secure.HTTPS=true/false עוקף את ברירת המחדל: HTTPS ישיר בפיתוח, מאחורי proxy בייצור.docker compose up --build # האפליקציה: https://localhost:3000
# תיבת דואר לבדיקות (Mailpit): http://localhost:8025
docker compose exec app npm run seed # משתמשי ונתוני דמו
docker compose exec app npm test # הרצת הבדיקות בתוך הקונטיינר
docker compose down -v # עצירה ומחיקת מסד הנתונים של הפיתוח
הקוד ממופה לתוך הקונטיינר, והשרת נטען מחדש בכל שמירה. כל המיילים שהמערכת שולחת נתפסים ב־Mailpit ומוצגים בתיבת דואר בדפדפן.
npm install
cp .env.development.example .env
npm run seed # נתוני דמו
npm run dev # https://localhost:3000, טעינה מחדש בכל שמירה
בלי הגדרת SMTP, המיילים לא נשלחים אלא נשמרים כקבצי .eml בתיקייה data/outbox.
משתמשי דמו (סיסמה Password1): [email protected] (מנהלת), [email protected], [email protected] (פעילים), [email protected] (ממתין לאישור), [email protected] (רישיון פג).
| פקודה | תיאור |
|---|---|
npm run dev | שרת פיתוח עם טעינה מחדש |
npm run seed | נתוני דמו (רק על מסד ריק, -- --force להוספה בכל מקרה, חסום ב־production) |
npm run lint | ESLint |
npm test | כל הבדיקות |
npm run test:unit | בדיקות יחידה: כללי הזמנה, זמנים ושעון קיץ, אימות, מיילים, משימות רקע |
npm run test:e2e | בדיקות קצה לקצה מול שרת אמיתי: תהליכי משתמש ומנהל, אבטחה והרשאות |
npm run test:coverage | בדיקות עם דוח כיסוי (נכשל מתחת ל־80% שורות) |
SQLD_BIN=/path/to/sqld npm run test:libsql | כל הבדיקות מול שרת libSQL (מה ש־Turso מריץ) במקום קובץ מקומי |
npm run create-admin -- --email … --password … | יצירת מנהל או קידום משתמש קיים למנהל |
| ענף | תפקיד | מה קורה ב־push |
|---|---|---|
dev | פיתוח שוטף. כל שינוי נכנס לכאן קודם | Lint, בדיקות, בניית Docker, פרסום ghcr.io/yehonatan21/car-rental:dev ופריסה לסביבת development |
main | גרסת ייצור. מתעדכן רק ב־Pull Request מ־dev | Lint, בדיקות, בניית Docker, פרסום ghcr.io/yehonatan21/car-rental:latest ופריסה לסביבת production |
ה־workflow נמצא ב־.github/workflows/ci-cd.yml:
Dockerfile, Dockerfile.dev) ובדיקת smoke ל־image של הייצור: עלייה, /healthz, דף התחברות, וריצה כמשתמש שאינו root. ב־push ה־image נדחף ל־GitHub Container Registry./healthz בכתובת שנפרסה.ב־Pull Request רצים רק שלבים 1 עד 3, בלי פרסום ובלי פריסה.
ב־Settings → Environments יוצרים שתי סביבות, development ו־production, ובכל אחת מגדירים:
DEPLOY_SSH_HOST, DEPLOY_SSH_KEY ו־DEPLOY_SSH_KNOWN_HOSTS. ה־pipeline מתחבר בשרת ב־SSH, מושך את ה־image החדש ומפעיל מחדש. ההקמה המלאה, כולל סקריפט התקנה לשרת, מתוארת ב־docs/dev-environment.md.DEPLOY_HOOK_URL עם כתובת ה־deploy hook (Render, Railway, Coolify וכדומה).APP_URL: הכתובת הציבורית של הסביבה, לבדיקת התקינות אחרי הפריסה.production מומלץ להוסיף Required reviewers, כדי שכל פריסה לייצור תדרוש אישור ידני.כל עוד אף אחת מהאפשרויות לא הוגדרה, ה־image מתפרסם אבל שלב הפריסה מדלג בהודעה ולא נכשל.
מומלץ גם להגדיר Branch protection ל־main (ב־Settings → Branches): לחייב Pull Request ולחייב מעבר של בדיקות ה־CI (Lint ו־Tests).
docker build -t car-rental . # image ייצור (Dockerfile)
cp .env.example .env # DOMAIN, BASE_URL=https://<DOMAIN>, SMTP_* וכו׳
docker compose -f docker-compose.prod.yml up -d # Caddy (HTTPS בפורטים 80/443) + האפליקציה
docker compose -f docker-compose.prod.yml exec app node scripts/create-admin.js --email … --password …
ה־image של הייצור כולל רק תלויות ריצה, רץ כמשתמש node (לא root) עם מערכת קבצים לקריאה בלבד, שומר את הנתונים ב־volume /data, וכולל healthcheck.
אפשר להגדיר אותם בקובץ .env (ראו .env.example), שנטען אוטומטית ב־npm start.
| משתנה | תיאור |
|---|---|
PORT | פורט השרת (ברירת מחדל 3000) |
BASE_URL | הכתובת הציבורית, משמשת לקישורים במיילים, למשל https://car.example.org |
HTTPS | true כדי שהשרת יגיש TLS בעצמו (ברירת מחדל בפיתוח), false מאחורי proxy (ברירת מחדל בייצור) |
HTTPS_CERT_FILE, HTTPS_KEY_FILE | תעודה ומפתח ל־HTTPS ישיר. בלעדיהם נוצרת תעודה עצמית ל־localhost |
DOMAIN | הדומיין לייצור, ש־Caddy מנפיק עבורו תעודה |
FORCE_HTTPS=false | ביטול ההפניה ל־HTTPS בייצור (לא מומלץ) |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | התחברות עם Google (ראו למעלה) |
TURSO_DATABASE_URL, TURSO_AUTH_TOKEN | מסד נתונים מתארח (Turso/libSQL) במקום קובץ מקומי. נדרש ב־Vercel כדי שהנתונים יישמרו |
ADMIN_EMAIL, ADMIN_PASSWORD | יצירת מנהל ראשון בהפעלה (אם החשבון לא קיים) |
CRON_SECRET | מפתח להפעלת המשימות המתוזמנות דרך /internal/cron (Vercel Cron) |
NODE_ENV=production | מפעיל עוגיות Secure ו־HSTS (חובה מאחורי HTTPS) |
DATA_DIR | תיקיית הנתונים: מסד הנתונים, צילומי הרישיונות ו־outbox (ברירת מחדל ./data) |
SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASS | שרת דואר יוצא |
MAIL_FROM | כתובת השולח (ברירת מחדל: SMTP_USER, אם זו כתובת מייל) |
MAIL_FROM_NAME | שם השולח שמוצג בתיבת הדואר במקום הכתובת, למשל גמח רכב בני אדם (ברירת מחדל: APP_NAME) |
APP_NAME | שם המערכת שמוצג בממשק ובמיילים |
APP_TIMEZONE | אזור הזמן של המערכת (ברירת מחדל Asia/Jerusalem, גם כשהשרת עצמו מוגדר ל־UTC, כמו ב־Vercel) |
docker-compose.prod.yml כולל את Caddy עם תעודות אוטומטיות, או בפלטפורמה שמספקת HTTPS. השרת מוגדר עם trust proxy.DATA_DIR. יש לגבות את התיקייה באופן תקופתי (למשל sqlite3 app.db ".backup backup.db" יחד עם תיקיית licenses).data/licenses אינה נגישה ישירות מהרשת. הקבצים מוגשים רק דרך נתיב שבודק הרשאת מנהל, וכל צפייה נרשמת ביומן הפעולות.src/
server.js אפליקציית Express, אבטחה (CSP, CSRF), העלאת קבצים
config.js הגדרות ומשתני סביבה (אזור זמן: Asia/Jerusalem)
db.js סכמת SQLite, הגדרות מערכת, נהלים
bookings.js כללי ההזמנה: חפיפות, זמן התארגנות, תוקף רישיון, מעברי סטטוס
auth.js סיסמאות (scrypt), סשנים, קוד חד־פעמי במייל, קישורי איפוס סיסמה
mail.js כל תבניות המייל
jobs.js משימות רקע: סגירת הזמנות שהסתיימו, תזכורות, תוקף רישיונות
routes/ public (הרשמה/התחברות), user (אזור אישי, יומן, הזמנות), admin (ממשק מנהל)
views/ תבניות HTML (עם escaping אוטומטי) ויומן יום/שבוע/חודש
public/ CSS ו־JS (שיפורים בלבד: הכל עובד גם בלי JavaScript)
scripts/ create-admin, seed (נתוני דמו), tunnel, server-setup.sh (הקמת שרת)
docs/ dev-environment.md: סביבת פיתוח זמינה באינטרנט · free-hosting.md: אחסון בחינם
test/
helpers.js מסד נתונים זמני לכל קובץ בדיקה, לקוח HTTP עם עוגיות ו־CSRF, קריאת outbox
unit/ בדיקות יחידה
e2e/ בדיקות קצה לקצה
.github/ CI/CD, סקריפטי פריסה, Dependabot
Dockerfile image ייצור · Dockerfile.dev: image פיתוח
docker-compose.yml סביבת פיתוח (אפליקציה + Mailpit) · docker-compose.prod.yml: ייצור
| סעיף | מימוש |
|---|---|
| 2.1 הרשמה | כל השדות, בדיקת ספרת ביקורת לת״ז, העלאת רישיון (תמונה/PDF), תוקף, אישור נהלים ופרטיות. סיסמה או קוד חד־פעמי במייל. אחרי שגיאה בטופס צילום הרישיון והסיסמה נשמרים (בצד השרת), ואין צורך להזין אותם שוב. "שכחתי סיסמה": קישור איפוס במייל, חד־פעמי ותקף לשעה |
| 2.2 אזור אישי | צפייה בפרטים, עדכון טלפון, העלאת רישיון חדש (ממתין לאישור מנהל, הישן ממשיך לשמש עד אז), סטטוס, הזמנות, ביטול, נהלים |
| 2.3 סטטוסי משתמש | ממתין, פעיל, ממתין לעדכון רישיון, חסום (ובנוסף "נדחה" להרשמה שנדחתה) |
| 3.1 יומן | תצוגת יום/שבוע/חודש; משתמשים רואים "תפוס" בלי פרטי המזמין; המנהל רואה הכל כולל בקשות ממתינות. לחיצה על משבצת פנויה פותחת בקשה |
| 3.2 הזמנה | איסוף, החזרה, מטרה, הערות, אישור נהלים; בדיקת זמינות חיה; ההודעה הנדרשת לאחר השליחה |
| 3.3 מניעת כפילויות | בקשות ממתינות לא חוסמות; בדיקה חוזרת בטרנזקציה בזמן האישור; המנהל רואה בקשות מתחרות ובוחר; זמן התארגנות להגדרה |
| 4 נהלים | עמוד נהלים, עריכה עם גרסאות, תיעוד הסכמה (תאריך, שעה, גרסה, IP), דרישת אישור מחדש בשינוי מהותי |
| 5.1 לוח בקרה | משתמשים ובקשות ממתינים, הזמנות קרובות, רישיונות שפגו או עומדים לפוג, התראות רכב |
| 5.2 ניהול משתמשים | רשימה וחיפוש, כרטיס משתמש, צפייה ברישיון, אישור/דחייה/חסימה, בקשת רישיון חדש, היסטוריה, מינוי מנהלים נוספים, שליחת קישור לאיפוס סיסמה. מנהל יכול לאשר גם את רישיון הנהיגה של עצמו (נרשם ביומן), אבל לא לשנות את הסטטוס או התפקיד של עצמו |
| 5.3 ניהול הזמנות | אישור/דחייה עם הערה, בדיקת התנגשויות, הזמנה ידנית, ביטול, חסימת מועדים, היסטוריית שינויים |
| 5.4 ניהול רכב | מספר רישוי, יצרן ודגם, סטטוס, ביטוח, רישיון רכב, טיפול, הערות, הנחיות לנהג (נכללות במייל האישור) |
| 6 מיילים | כל האירועים בטבלה. מייל אישור סופי נשלח רק אחרי אישור מנהל, גם למשתמש וגם למנהלים, עם זימון ליומן |
| 7 סטטוסי הזמנה | ממתינה, מאושרת, נדחתה, בוטלה, הסתיימה (אוטומטית כשמועד ההחזרה עבר). כל שינוי נשמר עם מבצע הפעולה |
| 8.1 תוקף רישיון | תזכורת למשתמש, העברה אוטומטית ל"ממתין לעדכון רישיון" והתראה למנהל, חסימת הזמנה שחורגת מתוקף הרישיון |
| 8.3, 8.4, 8.5 | חסימות תחזוקה; חיפוש וסינון לפי שם, תאריך, סטטוס ורכב; תזכורות איסוף והחזרה; התראה על בקשות שממתינות זמן רב |
| 9 אבטחה | הפרדת הרשאות, אחסון רישיונות מוגן, יומן פעולות מנהל, CSRF, CSP, הגבלת ניסיונות התחברות |
vehicle_id בכל הזמנה, סינון לפי רכב). חסר רק ממשק לבחירת רכב.דיווח מצב הרכב באיסוף ובהחזרה (קילומטראז׳, דלק, תמונות), דוחות שימוש, ממשק לניהול מספר רכבים, SMS/WhatsApp, ניהול טיפולים מתקדם.
שימו לב: הנהלים ומדיניות הפרטיות הם טיוטות. יש לעדכן אותם בהתאם להסדר הביטוחי ולייעוץ משפטי: את הנהלים דרך "נהלים" בממשק המנהל, ואת מדיניות הפרטיות בקובץ
src/routes/public.js.