deafmissoula-website/server/src/seed.ts
friday-bot a164c1f956 Auth, drag-and-drop, image previews, rate limiting
- Login by email; board members are dashboard users (full access)
- Forced password change on first login; forgot/reset password via email
- Auto-send welcome email with set-password link when board member created
- 5 attempts / 5 min rate limit on login endpoint
- Board + Minutes tabs: drag-and-drop card reordering, persisted to DB
- PATCH /api/board/reorder and /api/minutes/reorder endpoints
- New minutes auto-insert at top (order 0)
- ImagePicker: inline preview thumbnail before upload (board, gallery, sponsors)
- Fix Minutes public sort: proper date parsing instead of broken string compare
- Remove server/dist/ from git tracking (.gitignore)
2026-05-27 16:49:10 -06:00

89 lines
8.3 KiB
TypeScript

import 'dotenv/config';
import * as argon2 from 'argon2';
import { connectDB } from './db';
import { User } from './models/User';
import { BoardMember } from './models/BoardMember';
import { Event } from './models/Event';
import { GalleryItem } from './models/GalleryItem';
import { Sponsor } from './models/Sponsor';
import { Minute } from './models/Minute';
async function seed() {
await connectDB();
// Admin user
const existing = await User.findOne({ username: 'admin' });
if (!existing) {
const password = await argon2.hash(process.env.ADMIN_PASSWORD ?? 'changeme123!');
await User.create({ username: 'admin', password, name: 'MCDi Admin', email: 'admin@deafmissoula.org', role: 'admin' });
console.log('Created admin user');
}
// Board members
const boardCount = await BoardMember.countDocuments();
if (boardCount === 0) {
await BoardMember.insertMany([
{ name: 'Rita Brandborg', position: 'President', email: 'rita.brandborg@deafmissoula.org', image: '/headshots/rita.jpg', bio: "Meet Rita Brandborg, the proud mom of two tiny tornados (Levi and Josie) who keep her on her toes! When she's not wrangling her mini-me's or teaching Sign 102 at the University of Montana, you can find Rita snapping photos with her trusty camera or reeling in the big ones fly fishing. This Deaf momma is all about spreading joy, love, and a little bit of chaos wherever she goes! With a heart full of laughter and a mind full of stories, Rita is living life to the fullest - and loving every minute of it!", order: 0 },
{ name: 'Skyla Wilson', position: 'Vice President', email: 'skyla.wilson@deafmissoula.org', image: '/headshots/skyla.jpg', bio: "Meet Skyla Wilson, the river soul with a heart tuned to justice. She's a fierce advocate for the Deaf community, always ready to stand up, speak out (in her own way), and make space for voices that often go unheard. When she's not pushing for accessibility and equity, you'll find her floating peacefully down a river, soaking in the calm before diving back into the work. Skyla blends quiet power with unstoppable purpose—equal parts grace, grit, and a deep love for her community.", order: 1 },
{ name: 'Tessa Williams', position: 'Secretary', email: 'tessa.williams@deafmissoula.org', image: '/headshots/tessa.jpg', bio: "Meet Tessa Williams, the sparkplug of the University of Montana Social Worker's program. By day, she's a social work student with a heart of gold; by night, she's a sass-spewing machine who can take down anyone with her quick wit and sharp humor. When she's not advocating for Deaf rights or making her friends laugh, Tessa can be found sipping on a matcha latte with honey (her happy place). Don't mess with this tiny firecracker - she's got love for all, except maybe for those who can't keep up with her sass.", order: 2 },
{ name: 'Aubz M', position: 'Treasurer', email: 'aubz.m@deafmissoula.org', image: '/headshots/aubz.jpg', bio: "Aubz M is a shining star at the local veterinary hospital, where they're paving their way to become a certified vet tech. This animal whisperer's heart beats for creatures great and small, but it also swells with love for self-care and coziness. When they're not snuggling Kanga (their adorable pup), Aubz can be found soaking up wellness vibes or cracking jokes that'll leave you giggling. With a quick wit and thoughtful spirit, this Deaf rockstar is spreading kindness and compassion wherever they go!", order: 3 },
]);
console.log('Seeded board members');
}
// Events
const eventCount = await Event.countDocuments();
if (eventCount === 0) {
await Event.insertMany([
{ date: '2026-03-14', title: 'MCDi Board Meeting', description: 'Board Meeting at Funk It Coffee and Thrift', startTime: '10:00', endTime: '11:00', pointOfContact: 'Tessa Williams', email: 'tessa.williams@deafmissoula.org', address: '314 N 1st St. West, Missoula MT 59802' },
{ date: '2026-06-13', title: 'MCDi Board Meeting', description: 'Board Meeting', startTime: '09:00', endTime: '10:00', pointOfContact: 'Tessa Williams', email: 'tessa.williams@deafmissoula.org', address: 'Hybrid' },
{ date: '2026-09-12', title: 'MCDi Board Meeting', description: 'Board Meeting', startTime: '09:00', endTime: '10:00', pointOfContact: 'Tessa Williams', email: 'tessa.williams@deafmissoula.org', address: 'TBD' },
{ date: '2026-09-12', title: 'MCDi Annual Membership Meeting', description: 'Annual Membership Meeting', startTime: '10:00', endTime: '11:00', pointOfContact: 'Tessa Williams', email: 'tessa.williams@deafmissoula.org', address: 'TBD' },
]);
console.log('Seeded events');
}
// Gallery
const galleryCount = await GalleryItem.countDocuments();
if (galleryCount === 0) {
const items = Array.from({ length: 18 }, (_, i) => ({
imageUrl: `/photos/${String(i + 1).padStart(4, '0')}.jpg`,
alt: 'MCDi community event photo',
order: i,
}));
await GalleryItem.insertMany(items);
console.log('Seeded gallery');
}
// Sponsors
const sponsorCount = await Sponsor.countDocuments();
if (sponsorCount === 0) {
await Sponsor.insertMany([
{ name: 'Drum Coffee', logoPath: '/sponsors/drum-coffee-missoula.png', description: 'Drum Coffee partnered with MCDi to provide ASL lessons on coffee-related signology, enhancing their ability to serve Deaf community members. This initiative promotes inclusivity and improves communication in their bustling cafe environment.', websiteUrl: 'https://drumcoffeeroasting.com/', facebookUrl: 'https://m.facebook.com/drumcoffeemt', instagramUrl: 'https://www.instagram.com/drumcoffee/', order: 0 },
{ name: 'Imagine Nation Brewing', logoPath: '/sponsors/imagine-nation-brewing.png', description: 'Imagine Nation Brewing hosted a vibrant fundraising event, donating proceeds to MCDi. Their generous support not only raised funds but also raised awareness about the Deaf community, making a significant impact on our mission.', websiteUrl: 'https://imaginenationbrewing.com/', facebookUrl: 'https://m.facebook.com/ImagineNationBrewing', instagramUrl: 'https://www.instagram.com/imaginenationbrewingco', order: 1 },
{ name: 'GILD Brewing', logoPath: '/sponsors/gild-brewing.png', description: 'GILD Brewing organized a community-focused fundraiser for MCDi, combining craft beer tasting with Deaf culture education. Their event not only raised funds but also fostered a deeper understanding of Deaf culture, making a significant impact on our mission.', websiteUrl: 'https://www.gildbrewing.com/', facebookUrl: 'https://m.facebook.com/gildbrewing/', instagramUrl: 'https://www.instagram.com/gildbrewing/', order: 2 },
{ name: 'SBS Solar', logoPath: '/sponsors/sbs-solar.png', description: "SBS Solar supports MCDi's mission to serve the Deaf community in Missoula. Their commitment to renewable energy and community engagement aligns with our values of accessibility and sustainability.", websiteUrl: 'https://www.sbslink.com/', facebookUrl: 'https://www.facebook.com/sbssolar', instagramUrl: 'https://www.instagram.com/sbssolarmt/', order: 3 },
]);
console.log('Seeded sponsors');
}
// Minutes
const minuteCount = await Minute.countDocuments();
if (minuteCount === 0) {
await Minute.insertMany([
{ date: '04/12/2025', meetingType: 'Membership Meeting', location: 'The Break Coffee', fileUrl: '/minutes/minutes-04122025.pdf', order: 0 },
{ date: '03/08/2025', meetingType: 'Board Meeting', location: 'The Break Espresso', fileUrl: '/minutes/minutes-03082025.pdf', order: 1 },
{ date: '02/08/2025', meetingType: 'Board Meeting', location: 'Book Exchange - Liquid Planet', fileUrl: '/minutes/minutes-02082025.pdf', order: 2 },
{ date: '01/11/2025', meetingType: 'Membership Meeting', location: 'Black Coffee Roasting Company', fileUrl: '/minutes/minutes-01112025.pdf', order: 3 },
{ date: '10/17/2024', meetingType: 'Board Meeting', location: 'UC Market (University)', fileUrl: '/minutes/minutes-10172024.pdf', order: 4 },
{ date: '09/14/2024', meetingType: 'Membership Meeting', location: 'Dog Wash Cafe', fileUrl: '/minutes/minutes-09142024.pdf', order: 5 },
{ date: '08/06/2024', meetingType: 'Membership Meeting', location: 'The Break Espresso', fileUrl: '/minutes/minutes-08062024.pdf', order: 6 },
]);
console.log('Seeded minutes');
}
console.log('Seed complete');
process.exit(0);
}
seed().catch((err) => { console.error(err); process.exit(1); });