Implement remaining handlers and fix admin login

- Fix admin login bcrypt hash in database migrations
- Add static data handler (GET /api/static_data/, POST /api/static_data/refresh/)
- Add user handler (list users, get user, list profiles in shared residences)
- Add generate tasks report endpoint for residences
- Remove all placeholder handlers from router
- Add seeding documentation to README

New files:
- internal/handlers/static_data_handler.go
- internal/handlers/user_handler.go
- internal/services/user_service.go
- internal/dto/responses/user.go

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-26 23:11:49 -06:00
parent fff5d8c206
commit 9ec1bddd99
11 changed files with 604 additions and 22 deletions

View File

@@ -308,3 +308,17 @@ func (r *ResidenceRepository) FindResidenceTypeByID(id uint) (*models.ResidenceT
}
return &residenceType, nil
}
// GetTasksForReport returns all tasks for a residence with related data for report generation
func (r *ResidenceRepository) GetTasksForReport(residenceID uint) ([]models.Task, error) {
var tasks []models.Task
err := r.db.
Preload("Category").
Preload("Priority").
Preload("Status").
Preload("Completions").
Where("residence_id = ?", residenceID).
Order("due_date ASC NULLS LAST, created_at DESC").
Find(&tasks).Error
return tasks, err
}

View File

@@ -371,3 +371,118 @@ func (r *UserRepository) ListUsers(limit, offset int) ([]models.User, int64, err
return users, total, nil
}
// FindUsersInSharedResidences finds users that share at least one residence with the given user
func (r *UserRepository) FindUsersInSharedResidences(userID uint) ([]models.User, error) {
var users []models.User
// Find all users that share a residence with the given user
// This includes:
// 1. Owners of residences where current user is a member
// 2. Members of residences owned by current user
// 3. Members of residences where current user is also a member
err := r.db.Raw(`
SELECT DISTINCT u.* FROM user_customuser u
WHERE u.id != ? AND u.is_active = true AND (
-- Users who own residences where current user is a shared user
u.id IN (
SELECT r.owner_id FROM residence_residence r
INNER JOIN residence_residence_users ru ON r.id = ru.residence_id
WHERE ru.user_id = ? AND r.is_active = true
)
OR
-- Users who are shared users of residences owned by current user
u.id IN (
SELECT ru.user_id FROM residence_residence_users ru
INNER JOIN residence_residence r ON ru.residence_id = r.id
WHERE r.owner_id = ? AND r.is_active = true
)
OR
-- Users who share a residence with current user (both are shared users)
u.id IN (
SELECT ru2.user_id FROM residence_residence_users ru1
INNER JOIN residence_residence_users ru2 ON ru1.residence_id = ru2.residence_id
WHERE ru1.user_id = ? AND ru2.user_id != ?
)
)
`, userID, userID, userID, userID, userID).Scan(&users).Error
return users, err
}
// FindUserIfSharedResidence finds a user if they share a residence with the requesting user
func (r *UserRepository) FindUserIfSharedResidence(targetUserID, requestingUserID uint) (*models.User, error) {
var user models.User
err := r.db.Raw(`
SELECT u.* FROM user_customuser u
WHERE u.id = ? AND u.is_active = true AND (
u.id = ? OR
-- Target owns a residence where requester is a member
u.id IN (
SELECT r.owner_id FROM residence_residence r
INNER JOIN residence_residence_users ru ON r.id = ru.residence_id
WHERE ru.user_id = ? AND r.is_active = true
)
OR
-- Target is a member of a residence owned by requester
u.id IN (
SELECT ru.user_id FROM residence_residence_users ru
INNER JOIN residence_residence r ON ru.residence_id = r.id
WHERE r.owner_id = ? AND r.is_active = true
)
OR
-- Target shares a residence with requester (both are shared users)
u.id IN (
SELECT ru2.user_id FROM residence_residence_users ru1
INNER JOIN residence_residence_users ru2 ON ru1.residence_id = ru2.residence_id
WHERE ru1.user_id = ?
)
)
LIMIT 1
`, targetUserID, requestingUserID, requestingUserID, requestingUserID, requestingUserID).Scan(&user).Error
if err != nil {
return nil, err
}
if user.ID == 0 {
return nil, nil
}
return &user, nil
}
// FindProfilesInSharedResidences finds user profiles for users in shared residences
func (r *UserRepository) FindProfilesInSharedResidences(userID uint) ([]models.UserProfile, error) {
var profiles []models.UserProfile
err := r.db.Raw(`
SELECT p.* FROM user_userprofile p
INNER JOIN user_customuser u ON p.user_id = u.id
WHERE u.is_active = true AND (
u.id = ? OR
-- Users who own residences where current user is a shared user
u.id IN (
SELECT r.owner_id FROM residence_residence r
INNER JOIN residence_residence_users ru ON r.id = ru.residence_id
WHERE ru.user_id = ? AND r.is_active = true
)
OR
-- Users who are shared users of residences owned by current user
u.id IN (
SELECT ru.user_id FROM residence_residence_users ru
INNER JOIN residence_residence r ON ru.residence_id = r.id
WHERE r.owner_id = ? AND r.is_active = true
)
OR
-- Users who share a residence with current user (both are shared users)
u.id IN (
SELECT ru2.user_id FROM residence_residence_users ru1
INNER JOIN residence_residence_users ru2 ON ru1.residence_id = ru2.residence_id
WHERE ru1.user_id = ?
)
)
`, userID, userID, userID, userID).Scan(&profiles).Error
return profiles, err
}