gohorsejobs/backend/internal/models/user.go
Tiago Yamamoto 9ee9f6855c feat: implementar múltiplas features
Backend:
- Password reset flow (forgot/reset endpoints, tokens table)
- Profile management (PUT /users/me, skills, experience, education)
- Tickets system (CRUD, messages, stats)
- Activity logs (list, stats)
- Document validator (CNPJ, CPF, EIN support)
- Input sanitizer (XSS prevention)
- Full-text search em vagas (plainto_tsquery)
- Filtros avançados (location, salary, workMode)
- Ordenação (date, salary, relevance)

Frontend:
- Forgot/Reset password pages
- Candidate profile edit page
- Sanitize utilities (sanitize.ts)

Backoffice:
- TicketsModule proxy
- ActivityLogsModule proxy
- Dockerfile otimizado (multi-stage, non-root, healthcheck)

Migrations:
- 013: Profile fields to users
- 014: Password reset tokens
- 015: Tickets table
- 016: Activity logs table
2025-12-27 11:19:47 -03:00

95 lines
3.4 KiB
Go
Executable file

package models
import (
"encoding/json"
"time"
)
// User represents a system user (SuperAdmin, CompanyAdmin, Recruiter, or JobSeeker)
type User struct {
ID int `json:"id" db:"id"`
Identifier string `json:"identifier" db:"identifier"`
PasswordHash string `json:"-" db:"password_hash"` // Never expose password hash in JSON
Role string `json:"role" db:"role"` // superadmin, companyAdmin, recruiter, jobSeeker
// Personal Info
FullName string `json:"fullName" db:"full_name"`
Phone *string `json:"phone,omitempty" db:"phone"`
LineID *string `json:"lineId,omitempty" db:"line_id"`
WhatsApp *string `json:"whatsapp,omitempty" db:"whatsapp"`
Instagram *string `json:"instagram,omitempty" db:"instagram"`
// Settings
Language string `json:"language" db:"language"` // pt, en, es, ja
Active bool `json:"active" db:"active"`
// Metadata
CreatedAt time.Time `json:"createdAt" db:"created_at"`
UpdatedAt time.Time `json:"updatedAt" db:"updated_at"`
LastLoginAt *time.Time `json:"lastLoginAt,omitempty" db:"last_login_at"`
// Profile Profile
Bio *string `json:"bio,omitempty" db:"bio"`
ProfilePictureURL *string `json:"profilePictureUrl,omitempty" db:"profile_picture_url"`
Skills []byte `json:"skills,omitempty" db:"skills"` // JSONB
Experience []byte `json:"experience,omitempty" db:"experience"` // JSONB
Education []byte `json:"education,omitempty" db:"education"` // JSONB
}
// UserResponse is the public representation of a user (without sensitive data)
type UserResponse struct {
ID int `json:"id"`
Identifier string `json:"identifier"`
Role string `json:"role"`
FullName string `json:"fullName"`
Phone *string `json:"phone,omitempty"`
LineID *string `json:"lineId,omitempty"`
WhatsApp *string `json:"whatsapp,omitempty"`
Instagram *string `json:"instagram,omitempty"`
Language string `json:"language"`
Active bool `json:"active"`
CreatedAt time.Time `json:"createdAt"`
LastLoginAt *time.Time `json:"lastLoginAt,omitempty"`
Bio *string `json:"bio,omitempty"`
ProfilePictureURL *string `json:"profilePictureUrl,omitempty"`
Skills []string `json:"skills,omitempty"`
Experience []any `json:"experience,omitempty"`
Education []any `json:"education,omitempty"`
}
// ToResponse converts User to UserResponse
func (u *User) ToResponse() UserResponse {
// Helper to unmarshal JSONB
var skills []string
if len(u.Skills) > 0 {
_ = json.Unmarshal(u.Skills, &skills)
}
var experience []any
if len(u.Experience) > 0 {
_ = json.Unmarshal(u.Experience, &experience)
}
var education []any
if len(u.Education) > 0 {
_ = json.Unmarshal(u.Education, &education)
}
return UserResponse{
ID: u.ID,
Identifier: u.Identifier,
Role: u.Role,
FullName: u.FullName,
Phone: u.Phone,
LineID: u.LineID,
WhatsApp: u.WhatsApp,
Instagram: u.Instagram,
Language: u.Language,
Active: u.Active,
CreatedAt: u.CreatedAt,
LastLoginAt: u.LastLoginAt,
Bio: u.Bio,
ProfilePictureURL: u.ProfilePictureURL,
Skills: skills,
Experience: experience,
Education: education,
}
}