232 lines
21 KiB
Python
232 lines
21 KiB
Python
<<<<<<< HEAD
|
|
import sys
|
|
import os
|
|
from datetime import datetime, timedelta
|
|
|
|
# Add the app directory to the path
|
|
sys.path.insert(0, '/app')
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
from app.db.base import Base
|
|
from app.models.user import User
|
|
from app.models.chore import Chore
|
|
from app.core.security import get_password_hash
|
|
|
|
# Database setup
|
|
DATABASE_URL = "sqlite:///./family_hub.db"
|
|
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
|
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
|
|
def init_db():
|
|
"""Initialize database with schema and demo data"""
|
|
print("Creating all tables...")
|
|
Base.metadata.create_all(bind=engine)
|
|
|
|
db = SessionLocal()
|
|
|
|
try:
|
|
# Check if users already exist
|
|
existing_users = db.query(User).count()
|
|
if existing_users > 0:
|
|
print(f"Database already has {existing_users} users. Skipping initialization.")
|
|
return
|
|
|
|
print("Creating family members...")
|
|
# Create family members
|
|
users_data = [
|
|
{"username": "lou", "email": "lou@family.local", "full_name": "Lou", "is_admin": False},
|
|
{"username": "jess", "email": "jess@family.local", "full_name": "Jess", "is_admin": True},
|
|
{"username": "william", "email": "william@family.local", "full_name": "William", "is_admin": False},
|
|
{"username": "xander", "email": "xander@family.local", "full_name": "Xander", "is_admin": False},
|
|
{"username": "bella", "email": "bella@family.local", "full_name": "Bella", "is_admin": False},
|
|
]
|
|
|
|
users = {}
|
|
for user_data in users_data:
|
|
user = User(
|
|
username=user_data["username"],
|
|
email=user_data["email"],
|
|
full_name=user_data["full_name"],
|
|
hashed_password=get_password_hash("password123"),
|
|
is_admin=user_data["is_admin"],
|
|
is_active=True,
|
|
discord_id=None,
|
|
profile_picture=None
|
|
)
|
|
db.add(user)
|
|
users[user_data["username"]] = user
|
|
print(f" + Created user: {user_data['full_name']} ({user_data['username']})")
|
|
|
|
db.commit()
|
|
|
|
# Refresh to get IDs
|
|
for user in users.values():
|
|
db.refresh(user)
|
|
|
|
print("\nCreating demo chores...")
|
|
# Create demo chores with various statuses and assignments
|
|
today = datetime.now()
|
|
|
|
demo_chores = [
|
|
# Daily chores
|
|
{
|
|
"title": "Feed the Dog",
|
|
"description": "Give Rex his breakfast and dinner",
|
|
"room": "Kitchen",
|
|
"frequency": "daily",
|
|
"assignment_type": "any_one",
|
|
"status": "completed",
|
|
"assigned_user_id": users["william"].id,
|
|
"due_date": today.replace(hour=23, minute=59, second=59),
|
|
"completed_at": today.replace(hour=8, minute=30)
|
|
},
|
|
{
|
|
"title": "Take Out Trash",
|
|
"description": "Empty all bins and take to curb",
|
|
"room": "Kitchen",
|
|
"frequency": "daily",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["xander"].id,
|
|
"due_date": today.replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
{
|
|
"title": "Wash Dishes",
|
|
"description": "Load and run the dishwasher",
|
|
"room": "Kitchen",
|
|
"frequency": "daily",
|
|
"assignment_type": "any_one",
|
|
"status": "in_progress",
|
|
"assigned_user_id": users["bella"].id,
|
|
"due_date": today.replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
# Weekly chores
|
|
{
|
|
"title": "Vacuum Living Room",
|
|
"description": "Vacuum carpets and under furniture",
|
|
"room": "Living Room",
|
|
"frequency": "weekly",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["lou"].id,
|
|
"due_date": (today + timedelta(days=3)).replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
{
|
|
"title": "Clean Bathrooms",
|
|
"description": "Scrub toilets, sinks, and showers",
|
|
"room": "Bathroom",
|
|
"frequency": "weekly",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["jess"].id,
|
|
"due_date": (today + timedelta(days=2)).replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
{
|
|
"title": "Mow Lawn",
|
|
"description": "Mow front and back yards",
|
|
"room": "Yard",
|
|
"frequency": "weekly",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["william"].id,
|
|
"due_date": (today + timedelta(days=5)).replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
# Monthly chores
|
|
{
|
|
"title": "Change Air Filters",
|
|
"description": "Replace HVAC air filters throughout house",
|
|
"room": "Utility Room",
|
|
"frequency": "monthly",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["lou"].id,
|
|
"due_date": (today + timedelta(days=15)).replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
{
|
|
"title": "Deep Clean Fridge",
|
|
"description": "Empty, wipe down shelves, check expiry dates",
|
|
"room": "Kitchen",
|
|
"frequency": "monthly",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["jess"].id,
|
|
"due_date": (today + timedelta(days=20)).replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
# On-trigger chores (no specific schedule)
|
|
{
|
|
"title": "Water Plants",
|
|
"description": "Check soil moisture and water as needed",
|
|
"room": "Living Room",
|
|
"frequency": "on_trigger",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["bella"].id,
|
|
"due_date": today.replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
{
|
|
"title": "Sort Recycling",
|
|
"description": "Separate recyclables into proper bins",
|
|
"room": "Garage",
|
|
"frequency": "on_trigger",
|
|
"assignment_type": "any_one",
|
|
"status": "completed",
|
|
"assigned_user_id": users["xander"].id,
|
|
"due_date": (today - timedelta(days=1)).replace(hour=23, minute=59, second=59),
|
|
"completed_at": (today - timedelta(days=1)).replace(hour=14, minute=20)
|
|
},
|
|
# Some overdue chores
|
|
{
|
|
"title": "Organize Garage",
|
|
"description": "Sort tools and clean workspace",
|
|
"room": "Garage",
|
|
"frequency": "monthly",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["william"].id,
|
|
"due_date": (today - timedelta(days=3)).replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
{
|
|
"title": "Clean Windows",
|
|
"description": "Wash all interior and exterior windows",
|
|
"room": "Whole House",
|
|
"frequency": "monthly",
|
|
"assignment_type": "any_one",
|
|
"status": "pending",
|
|
"assigned_user_id": users["xander"].id,
|
|
"due_date": (today - timedelta(days=1)).replace(hour=23, minute=59, second=59),
|
|
"completed_at": None
|
|
},
|
|
]
|
|
|
|
for chore_data in demo_chores:
|
|
chore = Chore(**chore_data, created_by=users["jess"].id)
|
|
db.add(chore)
|
|
status_marker = "[DONE]" if chore_data["status"] == "completed" else "[WIP]" if chore_data["status"] == "in_progress" else "[TODO]"
|
|
print(f" {status_marker} {chore_data['title']} - {chore_data['frequency']} ({chore_data['room']})")
|
|
|
|
db.commit()
|
|
print(f"\n[SUCCESS] Database initialized with {len(users_data)} users and {len(demo_chores)} demo chores!")
|
|
|
|
except Exception as e:
|
|
print(f"[ERROR] Error initializing database: {e}")
|
|
db.rollback()
|
|
raise
|
|
finally:
|
|
db.close()
|
|
|
|
if __name__ == "__main__":
|
|
init_db()
|
|
=======
|
|
aW1wb3J0IHN5cwppbXBvcnQgb3MKZnJvbSBkYXRldGltZSBpbXBvcnQgZGF0ZXRpbWUsIHRpbWVkZWx0YQoKIyBBZGQgdGhlIGFwcCBkaXJlY3RvcnkgdG8gdGhlIHBhdGgKc3lzLnBhdGguaW5zZXJ0KDAsICcvYXBwJykKCmZyb20gc3FsYWxjaGVteSBpbXBvcnQgY3JlYXRlX2VuZ2luZQpmcm9tIHNxbGFsY2hlbXkub3JtIGltcG9ydCBzZXNzaW9ubWFrZXIKZnJvbSBhcHAuZGIuYmFzZSBpbXBvcnQgQmFzZQpmcm9tIGFwcC5tb2RlbHMudXNlciBpbXBvcnQgVXNlcgpmcm9tIGFwcC5tb2RlbHMuY2hvcmUgaW1wb3J0IENob3JlCmZyb20gYXBwLmNvcmUuc2VjdXJpdHkgaW1wb3J0IGdldF9wYXNzd29yZF9oYXNoCgojIERhdGFiYXNlIHNldHVwCkRBVEFCQVNFX1VSTCA9ICJzcWxpdGU6Ly8vLi9mYW1pbHlfaHViLmRiIgplbmdpbmUgPSBjcmVhdGVfZW5naW5lKERBVEFCQVNFX1VSTCwgY29ubmVjdF9hcmdzPXsiY2hlY2tfc2FtZV90aHJlYWQiOiBGYWxzZX0pClNlc3Npb25Mb2NhbCA9IHNlc3Npb25tYWtlcihhdXRvY29tbWl0PUZhbHNlLCBhdXRvZmx1c2g9RmFsc2UsIGJpbmQ9ZW5naW5lKQoKZGVmIGluaXRfZGIoKToKICAgICIiIkluaXRpYWxpemUgZGF0YWJhc2Ugd2l0aCBzY2hlbWEgYW5kIGRlbW8gZGF0YSIiIgogICAgcHJpbnQoIkNyZWF0aW5nIGFsbCB0YWJsZXMuLi4iKQogICAgQmFzZS5tZXRhZGF0YS5jcmVhdGVfYWxsKGJpbmQ9ZW5naW5lKQogICAgCiAgICBkYiA9IFNlc3Npb25Mb2NhbCgpCiAgICAKICAgIHRyeToKICAgICAgICAjIENoZWNrIGlmIHVzZXJzIGFscmVhZHkgZXhpc3QKICAgICAgICBleGlzdGluZ191c2VycyA9IGRiLnF1ZXJ5KFVzZXIpLmNvdW50KCkKICAgICAgICBpZiBleGlzdGluZ191c2VycyA+IDA6CiAgICAgICAgICAgIHByaW50KGYiRGF0YWJhc2UgYWxyZWFkeSBoYXMge2V4aXN0aW5nX3VzZXJzfSB1c2Vycy4gU2tpcHBpbmcgaW5pdGlhbGl6YXRpb24uIikKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgCiAgICAgICAgcHJpbnQoIkNyZWF0aW5nIGZhbWlseSBtZW1iZXJzLi4uIikKICAgICAgICAjIENyZWF0ZSBmYW1pbHkgbWVtYmVycwogICAgICAgIHVzZXJzX2RhdGEgPSBbCiAgICAgICAgICAgIHsidXNlcm5hbWUiOiAibG91IiwgImVtYWlsIjogImxvdUBmYW1pbHkubG9jYWwiLCAiZnVsbF9uYW1lIjogIkxvdSIsICJpc19hZG1pbiI6IEZhbHNlfSwKICAgICAgICAgICAgeyJ1c2VybmFtZSI6ICJqZXNzIiwgImVtYWlsIjogImplc3NAZmFtaWx5LmxvY2FsIiwgImZ1bGxfbmFtZSI6ICJKZXNzIiwgImlzX2FkbWluIjogVHJ1ZX0sCiAgICAgICAgICAgIHsidXNlcm5hbWUiOiAid2lsbGlhbSIsICJlbWFpbCI6ICJ3aWxsaWFtQGZhbWlseS5sb2NhbCIsICJmdWxsX25hbWUiOiAiV2lsbGlhbSIsICJpc19hZG1pbiI6IEZhbHNlfSwKICAgICAgICAgICAgeyJ1c2VybmFtZSI6ICJ4YW5kZXIiLCAiZW1haWwiOiAieGFuZGVyQGZhbWlseS5sb2NhbCIsICJmdWxsX25hbWUiOiAiWGFuZGVyIiwgImlzX2FkbWluIjogRmFsc2V9LAogICAgICAgICAgICB7InVzZXJuYW1lIjogImJlbGxhIiwgImVtYWlsIjogImJlbGxhQGZhbWlseS5sb2NhbCIsICJmdWxsX25hbWUiOiAiQmVsbGEiLCAiaXNfYWRtaW4iOiBGYWxzZX0sCiAgICAgICAgXQogICAgICAgIAogICAgICAgIHVzZXJzID0ge30KICAgICAgICBmb3IgdXNlcl9kYXRhIGluIHVzZXJzX2RhdGE6CiAgICAgICAgICAgIHVzZXIgPSBVc2VyKAogICAgICAgICAgICAgICAgdXNlcm5hbWU9dXNlcl9kYXRhWyJ1c2VybmFtZSJdLAogICAgICAgICAgICAgICAgZW1haWw9dXNlcl9kYXRhWyJlbWFpbCJdLAogICAgICAgICAgICAgICAgZnVsbF9uYW1lPXVzZXJfZGF0YVsiZnVsbF9uYW1lIl0sCiAgICAgICAgICAgICAgICBoYXNoZWRfcGFzc3dvcmQ9Z2V0X3Bhc3N3b3JkX2hhc2goInBhc3N3b3JkMTIzIiksCiAgICAgICAgICAgICAgICBpc19hZG1pbj11c2VyX2RhdGFbImlzX2FkbWluIl0sCiAgICAgICAgICAgICAgICBpc19hY3RpdmU9VHJ1ZSwKICAgICAgICAgICAgICAgIGRpc2NvcmRfaWQ9Tm9uZSwKICAgICAgICAgICAgICAgIHByb2ZpbGVfcGljdHVyZT1Ob25lCiAgICAgICAgICAgICkKICAgICAgICAgICAgZGIuYWRkKHVzZXIpCiAgICAgICAgICAgIHVzZXJzW3VzZXJfZGF0YVsidXNlcm5hbWUiXV0gPSB1c2VyCiAgICAgICAgICAgIHByaW50KGYiICDinJMgQ3JlYXRlZCB1c2VyOiB7dXNlcl9kYXRhWydmdWxsX25hbWUnXX0gKHt1c2VyX2RhdGFbJ3VzZXJuYW1lJ119KSIpCiAgICAgICAgCiAgICAgICAgZGIuY29tbWl0KCkKICAgICAgICAKICAgICAgICAjIFJlZnJlc2ggdG8gZ2V0IElEcwogICAgICAgIGZvciB1c2VyIGluIHVzZXJzLnZhbHVlcygpOgogICAgICAgICAgICBkYi5yZWZyZXNoKHVzZXIpCiAgICAgICAgCiAgICAgICAgcHJpbnQoIlxuQ3JlYXRpbmcgZGVtbyBjaG9yZXMuLi4iKQogICAgICAgICMgQ3JlYXRlIGRlbW8gY2hvcmVzIHdpdGggdmFyaW91cyBzdGF0dXNlcyBhbmQgYXNzaWdubWVudHMKICAgICAgICB0b2RheSA9IGRhdGV0aW1lLm5vdygpCiAgICAgICAgCiAgICAgICAgZGVtb19jaG9yZXMgPSBbCiAgICAgICAgICAgICMgRGFpbHkgY2hvcmVzCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJ0aXRsZSI6ICJGZWVkIHRoZSBEb2ciLAogICAgICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogIkdpdmUgUmV4IGhpcyBicmVha2Zhc3QgYW5kIGRpbm5lciIsCiAgICAgICAgICAgICAgICAicm9vbSI6ICJLaXRjaGVuIiwKICAgICAgICAgICAgICAgICJmcmVxdWVuY3kiOiAiREFJTFkiLAogICAgICAgICAgICAgICAgInN0YXR1cyI6ICJDT01QTEVURUQiLAogICAgICAgICAgICAgICAgImFzc2lnbmVkX3VzZXJfaWQiOiB1c2Vyc1sid2lsbGlhbSJdLmlkLAogICAgICAgICAgICAgICAgImR1ZV9kYXRlIjogdG9kYXkucmVwbGFjZShob3VyPTIzLCBtaW51dGU9NTksIHNlY29uZD01OSksCiAgICAgICAgICAgICAgICAiY29tcGxldGVkX2F0IjogdG9kYXkucmVwbGFjZShob3VyPTgsIG1pbnV0ZT0zMCkKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgInRpdGxlIjogIlRha2UgT3V0IFRyYXNoIiwKICAgICAgICAgICAgICAgICJkZXNjcmlwdGlvbiI6ICJFbXB0eSBhbGwgYmlucyBhbmQgdGFrZSB0byBjdXJiIiwKICAgICAgICAgICAgICAgICJyb29tIjogIktpdGNoZW4iLAogICAgICAgICAgICAgICAgImZyZXF1ZW5jeSI6ICJEQUlMWSIsCiAgICAgICAgICAgICAgICAic3RhdHVzIjogIlBFTkRJTkciLAogICAgICAgICAgICAgICAgImFzc2lnbmVkX3VzZXJfaWQiOiB1c2Vyc1sieGFuZGVyIl0uaWQsCiAgICAgICAgICAgICAgICAiZHVlX2RhdGUiOiB0b2RheS5yZXBsYWNlKGhvdXI9MjMsIG1pbnV0ZT01OSwgc2Vjb25kPTU5KSwKICAgICAgICAgICAgICAgICJjb21wbGV0ZWRfYXQiOiBOb25lCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJ0aXRsZSI6ICJXYXNoIERpc2hlcyIsCiAgICAgICAgICAgICAgICAiZGVzY3JpcHRpb24iOiAiTG9hZCBhbmQgcnVuIHRoZSBkaXNod2FzaGVyIiwKICAgICAgICAgICAgICAgICJyb29tIjogIktpdGNoZW4iLAogICAgICAgICAgICAgICAgImZyZXF1ZW5jeSI6ICJEQUlMWSIsCiAgICAgICAgICAgICAgICAic3RhdHVzIjogIklOX1BST0dSRVNTIiwKICAgICAgICAgICAgICAgICJhc3NpZ25lZF91c2VyX2lkIjogdXNlcnNbImJlbGxhIl0uaWQsCiAgICAgICAgICAgICAgICAiZHVlX2RhdGUiOiB0b2RheS5yZXBsYWNlKGhvdXI9MjMsIG1pbnV0ZT01OSwgc2Vjb25kPTU5KSwKICAgICAgICAgICAgICAgICJjb21wbGV0ZWRfYXQiOiBOb25lCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICMgV2Vla2x5IGNob3JlcwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAidGl0bGUiOiAiVmFjdXVtIExpdmluZyBSb29tIiwKICAgICAgICAgICAgICAgICJkZXNjcmlwdGlvbiI6ICJWYWN1dW0gY2FycGV0cyBhbmQgdW5kZXIgZnVybml0dXJlIiwKICAgICAgICAgICAgICAgICJyb29tIjogIkxpdmluZyBSb29tIiwKICAgICAgICAgICAgICAgICJmcmVxdWVuY3kiOiAiV0VFS0xZIiwKICAgICAgICAgICAgICAgICJzdGF0dXMiOiAiUEVORElORyIsCiAgICAgICAgICAgICAgICAiYXNzaWduZWRfdXNlcl9pZCI6IHVzZXJzWyJsb3UiXS5pZCwKICAgICAgICAgICAgICAgICJkdWVfZGF0ZSI6ICh0b2RheSArIHRpbWVkZWx0YShkYXlzPTMpKS5yZXBsYWNlKGhvdXI9MjMsIG1pbnV0ZT01OSwgc2Vjb25kPTU5KSwKICAgICAgICAgICAgICAgICJjb21wbGV0ZWRfYXQiOiBOb25lCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJ0aXRsZSI6ICJDbGVhbiBCYXRocm9vbXMiLAogICAgICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogIlNjcnViIHRvaWxldHMsIHNpbmtzLCBhbmQgc2hvd2VycyIsCiAgICAgICAgICAgICAgICAicm9vbSI6ICJCYXRocm9vbSIsCiAgICAgICAgICAgICAgICAiZnJlcXVlbmN5IjogIldFRUtMWSIsCiAgICAgICAgICAgICAgICAic3RhdHVzIjogIlBFTkRJTkciLAogICAgICAgICAgICAgICAgImFzc2lnbmVkX3VzZXJfaWQiOiB1c2Vyc1siamVzcyJdLmlkLAogICAgICAgICAgICAgICAgImR1ZV9kYXRlIjogKHRvZGF5ICsgdGltZWRlbHRhKGRheXM9MikpLnJlcGxhY2UoaG91cj0yMywgbWludXRlPTU5LCBzZWNvbmQ9NTkpLAogICAgICAgICAgICAgICAgImNvbXBsZXRlZF9hdCI6IE5vbmUKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgInRpdGxlIjogIk1vdyBMYXduIiwKICAgICAgICAgICAgICAgICJkZXNjcmlwdGlvbiI6ICJNb3cgZnJvbnQgYW5kIGJhY2sgeWFyZHMiLAogICAgICAgICAgICAgICAgInJvb20iOiAiWWFyZCIsCiAgICAgICAgICAgICAgICAiZnJlcXVlbmN5IjogIldFRUtMWSIsCiAgICAgICAgICAgICAgICAic3RhdHVzIjogIlBFTkRJTkciLAogICAgICAgICAgICAgICAgImFzc2lnbmVkX3VzZXJfaWQiOiB1c2Vyc1sid2lsbGlhbSJdLmlkLAogICAgICAgICAgICAgICAgImR1ZV9kYXRlIjogKHRvZGF5ICsgdGltZWRlbHRhKGRheXM9NSkpLnJlcGxhY2UoaG91cj0yMywgbWludXRlPTU5LCBzZWNvbmQ9NTkpLAogICAgICAgICAgICAgICAgImNvbXBsZXRlZF9hdCI6IE5vbmUKICAgICAgICAgICAgfSwKICAgICAgICAgICAgIyBNb250aGx5IGNob3JlcwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAidGl0bGUiOiAiQ2hhbmdlIEFpciBGaWx0ZXJzIiwKICAgICAgICAgICAgICAgICJkZXNjcmlwdGlvbiI6ICJSZXBsYWNlIEhWQUMgYWlyIGZpbHRlcnMgdGhyb3VnaG91dCBob3VzZSIsCiAgICAgICAgICAgICAgICAicm9vbSI6ICJVdGlsaXR5IFJvb20iLAogICAgICAgICAgICAgICAgImZyZXF1ZW5jeSI6ICJNT05USExZIiwKICAgICAgICAgICAgICAgICJzdGF0dXMiOiAiUEVORElORyIsCiAgICAgICAgICAgICAgICAiYXNzaWduZWRfdXNlcl9pZCI6IHVzZXJzWyJsb3UiXS5pZCwKICAgICAgICAgICAgICAgICJkdWVfZGF0ZSI6ICh0b2RheSArIHRpbWVkZWx0YShkYXlzPTE1KSkucmVwbGFjZShob3VyPTIzLCBtaW51dGU9NTksIHNlY29uZD01OSksCiAgICAgICAgICAgICAgICAiY29tcGxldGVkX2F0IjogTm9uZQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAidGl0bGUiOiAiRGVlcCBDbGVhbiBGcmlkZ2UiLAogICAgICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogIkVtcHR5LCB3aXBlIGRvd24gc2hlbHZlcywgY2hlY2sgZXhwaXJ5IGRhdGVzIiwKICAgICAgICAgICAgICAgICJyb29tIjogIktpdGNoZW4iLAogICAgICAgICAgICAgICAgImZyZXF1ZW5jeSI6ICJNT05USExZIiwKICAgICAgICAgICAgICAgICJzdGF0dXMiOiAiUEVORElORyIsCiAgICAgICAgICAgICAgICAiYXNzaWduZWRfdXNlcl9pZCI6IHVzZXJzWyJqZXNzIl0uaWQsCiAgICAgICAgICAgICAgICAiZHVlX2RhdGUiOiAodG9kYXkgKyB0aW1lZGVsdGEoZGF5cz0yMCkpLnJlcGxhY2UoaG91cj0yMywgbWludXRlPTU5LCBzZWNvbmQ9NTkpLAogICAgICAgICAgICAgICAgImNvbXBsZXRlZF9hdCI6IE5vbmUKICAgICAgICAgICAgfSwKICAgICAgICAgICAgIyBPbi10cmlnZ2VyIGNob3JlcyAobm8gc3BlY2lmaWMgc2NoZWR1bGUpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJ0aXRsZSI6ICJXYXRlciBQbGFudHMiLAogICAgICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogIkNoZWNrIHNvaWwgbW9pc3R1cmUgYW5kIHdhdGVyIGFzIG5lZWRlZCIsCiAgICAgICAgICAgICAgICAicm9vbSI6ICJMaXZpbmcgUm9vbSIsCiAgICAgICAgICAgICAgICAiZnJlcXVlbmN5IjogIk9OX1RSSUdHRVIiLAogICAgICAgICAgICAgICAgInN0YXR1cyI6ICJQRU5ESU5HIiwKICAgICAgICAgICAgICAgICJhc3NpZ25lZF91c2VyX2lkIjogdXNlcnNbImJlbGxhIl0uaWQsCiAgICAgICAgICAgICAgICAiZHVlX2RhdGUiOiB0b2RheS5yZXBsYWNlKGhvdXI9MjMsIG1pbnV0ZT01OSwgc2Vjb25kPTU5KSwKICAgICAgICAgICAgICAgICJjb21wbGV0ZWRfYXQiOiBOb25lCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJ0aXRsZSI6ICJTb3J0IFJlY3ljbGluZyIsCiAgICAgICAgICAgICAgICAiZGVzY3JpcHRpb24iOiAiU2VwYXJhdGUgcmVjeWNsYWJsZXMgaW50byBwcm9wZXIgYmlucyIsCiAgICAgICAgICAgICAgICAicm9vbSI6ICJHYXJhZ2UiLAogICAgICAgICAgICAgICAgImZyZXF1ZW5jeSI6ICJPTl9UUklHR0VSIiwKICAgICAgICAgICAgICAgICJzdGF0dXMiOiAiQ09NUExFVEVEIiwKICAgICAgICAgICAgICAgICJhc3NpZ25lZF91c2VyX2lkIjogdXNlcnNbInhhbmRlciJdLmlkLAogICAgICAgICAgICAgICAgImR1ZV9kYXRlIjogKHRvZGF5IC0gdGltZWRlbHRhKGRheXM9MSkpLnJlcGxhY2UoaG91cj0yMywgbWludXRlPTU5LCBzZWNvbmQ9NTkpLAogICAgICAgICAgICAgICAgImNvbXBsZXRlZF9hdCI6ICh0b2RheSAtIHRpbWVkZWx0YShkYXlzPTEpKS5yZXBsYWNlKGhvdXI9MTQsIG1pbnV0ZT0yMCkKICAgICAgICAgICAgfSwKICAgICAgICAgICAgIyBTb21lIG92ZXJkdWUgY2hvcmVzCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJ0aXRsZSI6ICJPcmdhbml6ZSBHYXJhZ2UiLAogICAgICAgICAgICAgICAgImRlc2NyaXB0aW9uIjogIlNvcnQgdG9vbHMgYW5kIGNsZWFuIHdvcmtzcGFjZSIsCiAgICAgICAgICAgICAgICAicm9vbSI6ICJHYXJhZ2UiLAogICAgICAgICAgICAgICAgImZyZXF1ZW5jeSI6ICJNT05USExZIiwKICAgICAgICAgICAgICAgICJzdGF0dXMiOiAiUEVORElORyIsCiAgICAgICAgICAgICAgICAiYXNzaWduZWRfdXNlcl9pZCI6IHVzZXJzWyJ3aWxsaWFtIl0uaWQsCiAgICAgICAgICAgICAgICAiZHVlX2RhdGUiOiAodG9kYXkgLSB0aW1lZGVsdGEoZGF5cz0zKSkucmVwbGFjZShob3VyPTIzLCBtaW51dGU9NTksIHNlY29uZD01OSksCiAgICAgICAgICAgICAgICAiY29tcGxldGVkX2F0IjogTm9uZQogICAgICAgICAgICB9LAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAidGl0bGUiOiAiQ2xlYW4gV2luZG93cyIsCiAgICAgICAgICAgICAgICAiZGVzY3JpcHRpb24iOiAiV2FzaCBhbGwgaW50ZXJpb3IgYW5kIGV4dGVyaW9yIHdpbmRvd3MiLAogICAgICAgICAgICAgICAgInJvb20iOiAiV2hvbGUgSG91c2UiLAogICAgICAgICAgICAgICAgImZyZXF1ZW5jeSI6ICJNT05USExZIiwKICAgICAgICAgICAgICAgICJzdGF0dXMiOiAiUEVORElORyIsCiAgICAgICAgICAgICAgICAiYXNzaWduZWRfdXNlcl9pZCI6IHVzZXJzWyJ4YW5kZXIiXS5pZCwKICAgICAgICAgICAgICAgICJkdWVfZGF0ZSI6ICh0b2RheSAtIHRpbWVkZWx0YShkYXlzPTEpKS5yZXBsYWNlKGhvdXI9MjMsIG1pbnV0ZT01OSwgc2Vjb25kPTU5KSwKICAgICAgICAgICAgICAgICJjb21wbGV0ZWRfYXQiOiBOb25lCiAgICAgICAgICAgIH0sCiAgICAgICAgXQogICAgICAgIAogICAgICAgIGZvciBjaG9yZV9kYXRhIGluIGRlbW9fY2hvcmVzOgogICAgICAgICAgICBjaG9yZSA9IENob3JlKCoqY2hvcmVfZGF0YSwgY3JlYXRlZF9ieT11c2Vyc1siamVzcyJdLmlkKQogICAgICAgICAgICBkYi5hZGQoY2hvcmUpCiAgICAgICAgICAgIHN0YXR1c19lbW9qaSA9ICLinJMiIGlmIGNob3JlX2RhdGFbInN0YXR1cyJdID09ICJDT01QTEVURUQiIGVsc2UgIuKPsyIgaWYgY2hvcmVfZGF0YVsic3RhdHVzIl0gPT0gIklOX1BST0dSRVNTIiBlbHNlICLil4siCiAgICAgICAgICAgIHByaW50KGYiICB7c3RhdHVzX2Vtb2ppfSB7Y2hvcmVfZGF0YVsndGl0bGUnXX0gLSB7Y2hvcmVfZGF0YVsnZnJlcXVlbmN5J119ICh7Y2hvcmVfZGF0YVsncm9vbSddfSkiKQogICAgICAgIAogICAgICAgIGRiLmNvbW1pdCgpCiAgICAgICAgcHJpbnQoZiJcbuKchSBEYXRhYmFzZSBpbml0aWFsaXplZCBzdWNjZXNzZnVsbHkgd2l0aCB7bGVuKHVzZXJzX2RhdGEpfSB1c2VycyBhbmQge2xlbihkZW1vX2Nob3Jlcyl9IGRlbW8gY2hvcmVzISIpCiAgICAgICAgCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgcHJpbnQoZiLinYwgRXJyb3IgaW5pdGlhbGl6aW5nIGRhdGFiYXNlOiB7ZX0iKQogICAgICAgIGRiLnJvbGxiYWNrKCkKICAgICAgICByYWlzZQogICAgZmluYWxseToKICAgICAgICBkYi5jbG9zZSgpCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgaW5pdF9kYigpCg==
|
|
>>>>>>> 65c71b3d67d462fe9ecc01a1c2aa17e54b626fe2
|