Documentation
¶
Overview ¶
Package hirevec implements core server and client.
Package hirevec implements core server and client.
Package hirevec implements core server and client.
Package hirevec implements core server and client.
Index ¶
- Constants
- Variables
- func ConnectPostgreSQL(url string) (*sql.DB, error)
- func ConnectSQLite() (*sql.DB, error)
- func CurrentTimestamp(offset ...time.Duration) string
- func DecodeRequestBody[T any](r *http.Request) (T, error)
- func EscapeSQLiteFTS(query string) string
- func ExecMigration(db *sql.DB, path string) error
- func GenerateUserName() (string, error)
- func Getenv(key string, defaultValue string) string
- func GetenvAndParse[T any](key string, parser func(string) (T, error), defaultValue T) T
- func HashPassword(password string) (string, error)
- func InitLogger(level slog.Level)
- func InitPostgreSQL(url string) (*sql.DB, error)
- func InitSQLite() (*sql.DB, error)
- func IsValidPassword(passwordHash string, password string) bool
- func JSON(w http.ResponseWriter, responseBody Envelope, status int)
- func LoadOrCreateAsymmetricKey(val string) (paseto.V4AsymmetricSecretKey, error)
- func LoadOrCreateSymmetricKey(val string) (paseto.V4SymmetricKey, error)
- func Loadenv(path string) error
- func MiddlewareChain(handler http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc
- func NormalizeAndValidateCandidateAbout(about string) (string, error)
- func NormalizeAndValidatePositionCompanyName(company string) (string, error)
- func NormalizeAndValidatePositionDescription(description string) (string, error)
- func NormalizeAndValidatePositionTitle(title string) (string, error)
- func NormalizeAndValidateUserFullName(name string) (string, error)
- func NormalizeAndValidateUserName(userName string) (string, error)
- func ParseInt(value string) (int, error)
- func ParseLogLevel(value string) (slog.Level, error)
- func RunAPI(ctx context.Context, c APIConfig, s Store, v Vault) error
- func RunApp(c AppConfig) error
- func SqlIn(column string, n int) string
- func UpsertEnvKey(filename string, key string, value string) error
- func ValidateUserPassword(password string) error
- type AIConfig
- type API
- func (a *API) CreateAccessToken(w http.ResponseWriter, userID ULID, provider Provider, roles map[Role]ULID)
- func (a *API) HandlerCreateCandidate() http.HandlerFunc
- func (a *API) HandlerCreatePosition() http.HandlerFunc
- func (a *API) HandlerCreateReaction() http.HandlerFunc
- func (a *API) HandlerCreateRecruiter() http.HandlerFunc
- func (a *API) HandlerCreateUser() http.HandlerFunc
- func (a *API) HandlerDeleteCandidate() http.HandlerFunc
- func (a *API) HandlerDeletePosition() http.HandlerFunc
- func (a *API) HandlerDeleteRecruiter() http.HandlerFunc
- func (a *API) HandlerDeleteUser() http.HandlerFunc
- func (a *API) HandlerGetCandidate() http.HandlerFunc
- func (a *API) HandlerGetMatches() http.HandlerFunc
- func (a *API) HandlerGetPosition() http.HandlerFunc
- func (a *API) HandlerGetPositions() http.HandlerFunc
- func (a *API) HandlerGetReactions() http.HandlerFunc
- func (a *API) HandlerGetRecommendations() http.HandlerFunc
- func (a *API) HandlerGetRecruiter() http.HandlerFunc
- func (a *API) HandlerGetUser() http.HandlerFunc
- func (a *API) HandlerHealth(w http.ResponseWriter, r *http.Request)
- func (a *API) HandlerLoginViaEmail() http.HandlerFunc
- func (a *API) HandlerLoginViaProvider() http.HandlerFunc
- func (a *API) HandlerPatchCandidate() http.HandlerFunc
- func (a *API) HandlerPatchPosition() http.HandlerFunc
- func (a *API) HandlerPatchUser() http.HandlerFunc
- func (a *API) HandlerRefresh() http.HandlerFunc
- func (a *API) HandlerSSOCallback() http.HandlerFunc
- func (a *API) MiddlewareAuth(roles map[Role]bool) Middleware
- func (a *API) MiddlewareLogging(next http.HandlerFunc) http.HandlerFunc
- func (a *API) MiddlewareMaxBytesLimit(next http.HandlerFunc) http.HandlerFunc
- func (a *API) MiddlewarePanicRecovery(next http.HandlerFunc) http.HandlerFunc
- func (a *API) PrivateRoute(c RouteConfig)
- func (a *API) PublicRoute(c RouteConfig)
- func (a *API) RegisterRoutes()
- func (a *API) RunEmbeddingsJob(c AIConfig) error
- func (a *API) RunRecommendationsJob(c AIConfig) error
- func (a *API) WaitAndShutdown(ctx context.Context, errCh chan error, gracePeriod time.Duration) error
- type APIConfig
- type AccessToken
- type AccessTokenClaims
- type AppConfig
- type AppleClaims
- type Candidate
- type ContextKey
- type DatabaseProvider
- type EmbeddingEntity
- type EmbeddingStatus
- type EmbeddingsRequest
- type EmbeddingsResponse
- type Envelope
- type Error
- type ErrorSource
- type GoogleClaims
- type IDToken
- type Links
- type Match
- type Meta
- type Method
- type Middleware
- type OIDCConfig
- type Page
- type Position
- type Provider
- type Reaction
- type ReactionType
- type ReactorType
- type Recommendation
- type RecommendationForCandidate
- type RecommendationForRecruiter
- type Recruiter
- type RefreshToken
- type RefreshTokenClaims
- type RequestBodyCreateCandidate
- type RequestBodyCreatePosition
- type RequestBodyCreateUser
- type RequestBodyLoginViaEmail
- type RequestBodyPatchCandidate
- type RequestBodyPatchPosition
- type RequestBodyPatchUser
- type RequestBodyRefresh
- type RequestCreateReaction
- type ResponseDataHealth
- type ResponseWriter
- type Role
- type Route
- type RouteConfig
- type Scope
- type StateTokenClaims
- type Store
- func (s Store) ClearAll(ctx context.Context) error
- func (s Store) CreateCandidate(userID ULID, about string) (ULID, error)
- func (s Store) CreatePosition(recruiterID ULID, title string, description string, company string, ...) (ULID, error)
- func (s Store) CreateReaction(recommendationID ULID, reactorType ReactorType, reactorID ULID, ...) error
- func (s Store) CreateRecommendation(positionID ULID, candidateID ULID) (ULID, error)
- func (s Store) CreateRecruiter(userID ULID) (ULID, error)
- func (s Store) CreateRefreshToken(userID ULID) (jti ULID, err error)
- func (s Store) CreateUser(provider Provider, providerUserID string, email string, fullName string, ...) (ULID, error)
- func (s Store) DeleteCandidate(candidateID ULID) error
- func (s Store) DeletePosition(positionID ULID) error
- func (s Store) DeleteRecruiter(recruiterID ULID) error
- func (s Store) DeleteUser(userID ULID) error
- func (s Store) FetchPendingEmbeddingsMetadata(limit uint16) ([]ULID, []string, error)
- func (s Store) GetCandidate(candidateID ULID) (Candidate, error)
- func (s Store) GetCandidates(limit uint16, recommendationSpan time.Duration) ([]ULID, error)
- func (s Store) GetMatchesByCandidateID(candidateID ULID, page Page) (matches []Match, nextCursor ULID, err error)
- func (s Store) GetPosition(positionID ULID) (Position, error)
- func (s Store) GetPositions(recruiterID ULID, page Page) (positions []Position, nextCursor ULID, err error)
- func (s Store) GetPositionsForCandidateViaEmbeddings(candidateID ULID, topPositions uint16) ([]ULID, error)
- func (s Store) GetPositionsForCandidateViaFTS(candidateID ULID, topPositions uint16) ([]ULID, error)
- func (s Store) GetReactionsByCandidateID(candidateID ULID, page Page) (reactions []Reaction, nextCursor ULID, err error)
- func (s Store) GetRecommendation(recommendationID ULID) (Recommendation, error)
- func (s Store) GetRecommendationsForCandidate(candidateID ULID, page Page, excludeReacted bool) (recommendations []RecommendationForCandidate, nextCursor ULID, err error)
- func (s Store) GetRecommendationsForRecruiter(recruiterID ULID, page Page, excludeReacted bool) (recommendations []RecommendationForRecruiter, nextCursor ULID, err error)
- func (s Store) GetRecruiter(recruiterID ULID) (Recruiter, error)
- func (s Store) GetUser(userID ULID) (User, error)
- func (s Store) GetUserAndRoles(userID ULID) (User, map[Role]ULID, error)
- func (s Store) GetUserAndRolesByEmail(email string, provider Provider) (User, map[Role]ULID, error)
- func (s Store) GetUserIDAndRolesByProvider(provider Provider, providerUserID string) (ULID, map[Role]ULID, error)
- func (s Store) GetUserRoles(userID ULID, provider Provider) (map[Role]ULID, error)
- func (s Store) IsRevokedRefreshToken(jti ULID) (bool, error)
- func (s Store) MarkEmbeddingsStatus(entityIDs []ULID, status EmbeddingStatus) error
- func (s Store) MarkEmbeddingsStatusTx(tx *sql.Tx, entityIDs []ULID, status EmbeddingStatus) error
- func (s Store) RecruiterExists(recruiterID ULID) (bool, error)
- func (s Store) UpdateCandidate(candidateID ULID, newAbout string) error
- func (s Store) UpdateCandidateAndReturn(candidateID ULID, newAbout string) (Candidate, error)
- func (s Store) UpdatePosition(positionID ULID, newTitle string, newDescription string, newCompany string, ...) error
- func (s Store) UpdateUser(userID ULID, newFullName string, newUserName string) error
- func (s Store) UpdateUserAndReturn(userID ULID, newFullName string, newUserName string) (User, error)
- func (s Store) UpsertEmbeddingsTx(tx *sql.Tx, embeddingIDs []ULID, embeddings []EmbeddingEntity) error
- func (s Store) UserExistsByEmail(email string, provider Provider) (bool, error)
- type StoreConfig
- type TokenPair
- type ULID
- func NewCandidateULID() (ULID, error)
- func NewJTIULID() (ULID, error)
- func NewPositionULID() (ULID, error)
- func NewRecommendationULID() (ULID, error)
- func NewRecruiterULID() (ULID, error)
- func NewULID(prefix string) (ULID, error)
- func NewUserULID() (ULID, error)
- func Rerank(c AIConfig, candidateID ULID, positions []ULID) ([]ULID, error)
- type User
- type Vault
- func (v Vault) CreateAccessToken(userID ULID, provider Provider, roles map[Role]ULID) (AccessToken, error)
- func (v Vault) CreateAuthCodeURL(state string, verifier string, provider Provider) (string, error)
- func (v Vault) CreateRefreshToken(userID ULID, provider Provider, jti ULID) (RefreshToken, error)
- func (v Vault) CreateStateToken(provider Provider) (string, error)
- func (v Vault) CreateTokenPair(userID ULID, provider Provider, jti ULID, roles map[Role]ULID) (TokenPair, error)
- func (v Vault) ExchangeAppleCodeForIDToken(ctx context.Context, code string, verifierCookie *http.Cookie) (string, error)
- func (v Vault) ExchangeGoogleCodeForIDToken(ctx context.Context, code string, verifierCookie *http.Cookie) (string, error)
- func (v Vault) ParseAccessToken(tokenString string) (AccessTokenClaims, error)
- func (v Vault) ParseRefreshToken(tokenString string) (RefreshTokenClaims, error)
- func (v Vault) ParseStateToken(raw string) (StateTokenClaims, error)
- func (v Vault) VerifyAndParseAppleIDToken(ctx context.Context, rawIDToken string, userJSON string) (IDToken, error)
- func (v Vault) VerifyAndParseGoogleIDToken(ctx context.Context, rawIDToken string) (IDToken, error)
- type VaultConfig
Constants ¶
const ( DefaultCandidatesBatchSize = 32 DefaultRecommendationsDailyLimit = 32 DefaultTopPositions = 128 )
const ( DefaultRequestReadTimeout = 1000 * time.Millisecond DefaultRequestWriteTimeout = 1000 * time.Millisecond DefaultGracePeriod = 5000 * time.Millisecond )
const ( DefaultEmbeddingsJobFrequency = 1 * time.Hour DefaultRecommendationsJobFrequency = 24 * time.Hour )
const ( DefaultPageSize = 32 MaxPageSize = 128 )
const ( ErrorCodeBearerTokenRequired = "bearer_token_required" ErrorCodeInvalidAccessToken = "invalid_access_token" )
const ( ErrorCodeInvalidRequestBody = "invalid_request_body" ErrorCodeInvalidGrantType = "invalid_grant_type" ErrorCodeRefreshTokenRequired = "refresh_token_required" ErrorCodeInvalidRefreshToken = "invalid_refresh_token" )
const ( ErrorCodePasswordRequired = "password_required" ErrorCodeInvalidCredentials = "invalid_credentials" )
const ( ErrorCodeMissingState = "missing_state" ErrorCodeInvalidState = "invalid_state" ErrorCodeInvalidCSRF = "invalid_csrf" ErrorCodeMissingVerifier = "missing_verifier" ErrorCodeAuthorizationProvider = "authorization_provider_error" ErrorCodeMissingCode = "missing_code" ErrorCodeIDTokenRequired = "id_token_required" ErrorCodeInvalidIDToken = "invalid_id_token" ErrorCodeFailedParseClaims = "failed_parse_claims" ErrorCodeUnverifiedEmail = "unverified_email" )
const ( DefaultUserFullNameMinLength = 2 DefaultUserFullNameMaxLength = 512 )
const ( ErrorCodeRecommendationIDRequired = "recommendation_id_required" ErrorCodeRecommendationNotFound = "recommendation_not_found" ErrorCodeReactionExists = "reaction_exists" ErrorCodeInvalidReactionType = "invalid_reaction_type" )
const ( DefaultUserPasswordMinLength = 8 DefaultUserPasswordMaxLength = 128 )
const ( ErrorCodeEmailRequired = "email_required" ErrorCodeInvalidUserEmailFormat = "invalid_user_email_format" ErrorCodeInvalidUserPasswordFormat = "invalid_user_password_format" ErrorCodeInvalidUserFullNameFormat = "invalid_user_full_name_format" ErrorCodeUserAlreadyExists = "user_exists" )
const ( ErrorCodeCandidateAlreadyExists = "candiate_already_exists" ErrorCodeInvalidCandidateAboutFormat = "invalid_candidate_about_format" )
const ( ErrorCodeInternalServerError = "internal_server_error" ErrorCodeUserNotFound = "user_not_found" ErrorCodeForbidden = "forbidden" )
const ( DefaultUserNameMinLength = 4 DefaultUesrNameMaxLength = 32 )
const ( ErrorMessageUserNameWrongSize = "user_name must be between 4 and 32 characters" ErrorMessageUserNameForbiddenChars = "user_name can only contain underscores, latin characters and numbers" )
const ( ErrorCodeResourceTypeMismatch = "resource_type_mismatch" ErrorCodeResourceIDMismatch = "resource_id_mismatch" ErrorCodeInvalidUserUserNameFormat = "invalid_user_user_name_format" )
const ( ErrorCodeMissingRequiredRole = "missing_required_role" ErrorCodeCandidateNotFound = "candidate_not_found" )
const ( DefaultPositionTitleMinLength = 4 DefaultPositionTitleMaxLength = 64 )
const ( DefaultPositionCompanyNameMinLength = 2 DefaultPositionCompanyNameMaxLength = 512 )
const ( ErrorCodeInvalidPositionTitleFormat = "invalid_position_title_format" ErrorCodeInvalidPositionDescriptionFormat = "invalid_position_description_format" ErrorCodeInvalidPositionCompanyFormat = "invalid_position_company_format" ErrorCodePositionExists = "position_exists" )
const ( ErrorCodePositionIDRequired = "position_id_required" ErrorCodePositionNotFound = "position_not_found" )
const ( EmbeddingStatusPending = "pending" EmbeddingStatusDone = "done" EmbeddingStatusFailed = "failed" )
const ( DefaultRefreshTokenExpiration = 90 * 24 * time.Hour // 90 days DefaultAccessTokenExpiration = 30 * time.Minute // 30 minutes DefaultStateTokenExpiration = 10 * time.Minute // 10 minutes DefaultVerifierExpiration = 10 * time.Minute // 10 minutes )
const ( TokenAudience = "hirevec.com" TokenIssuer = "hirevec.com" StateTokenAudience = "oauth-state" )
const (
DefaultCandidateAboutMaxLength = 1024
)
const DefaultEmbeddingsBatchSize = 64
const (
DefaultLogLevel = slog.LevelWarn
)
const DefaultMaxRefreshTokensCount = 5
const (
DefaultPositionDescriptionMaxLength = 2048
)
const DefaultProvider = ProviderGoogle
const Enc = "0123456789abcdefghjkmnpqrstvwxyz"
const ErrorCodeInvalidProvider = "invalid_provider"
const ErrorCodeRecruiterExists = "recruiter_exists"
const ErrorCodeRecruiterNotFound = "recruiter_not_found"
const ErrorCodeUnsupportedMediaType = "unsupported_media_type"
const ULIDPrefixCandidate = "can_"
const ULIDPrefixJTI = "jti_"
const ULIDPrefixPosition = "pos_"
const ULIDPrefixRecommendation = "rcm_"
const ULIDPrefixRecruiter = "rcr_"
const ULIDPrefixUser = "usr_"
Variables ¶
var ( RegexHTMLTag = regexp.MustCompile(`(?s)<[^>]*>`) RegexJSTag = regexp.MustCompile(`(?is)<script.*?>.*?</script>`) RegexSQL = regexp.MustCompile(`(?i)\b(select|insert|update|delete|drop|truncate|alter)\b`) )
var ( ErrTextForbiddenChars = errors.New("text contains forbidden characters") ErrTextTooShort = errors.New("text too short") ErrTextTooLong = errors.New("text too long") )
var ( ErrorMessageUserFullNameWrongSize = fmt.Sprintf("full_name must be between %v and %v characters", DefaultUserFullNameMinLength, DefaultUserFullNameMaxLength) ErrorMessageUserFullNameForbiddenChars = "" /* 143-byte string literal not displayed */ )
var ( // UserNameAdjectives is an array for creating random user names, used in conjunction with nouns UserNameAdjectives = [...]string{ "fast", "lazy", "clever", "curious", "brave", "mighty", "silent", "noisy", "happy", "grumpy", } // UserNameNouns is an array for creating random user names, used in conjunction with adjectives UserNameNouns = [...]string{ "lion", "tiger", "panda", "fox", "eagle", "shark", "wolf", "dragon", "otter", "koala", } )
var ( RegexPasswordHasLower = regexp.MustCompile(`[a-z]`) RegexPasswordHasUpper = regexp.MustCompile(`[A-Z]`) RegexPasswordHasDigit = regexp.MustCompile(`\d`) RegexPasswordHasSpecial = regexp.MustCompile(`[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>/?]`) )
var ( ErrPasswordHasNoUpper = errors.New("password has no upper letter") ErrPasswordHasNoDigit = errors.New("password has no digit") ErrPasswordHasNoSpecial = errors.New("password has no special character") ErrPasswordHasNoLower = errors.New("password has no lower letter") )
var ( PathInitMigration = path.Join("migrations/init.sql") PathEmbeddingsMigration = path.Join("migrations/embeddings.sql") PathPostgreSQLFTSMigration = path.Join("migrations/postgresql-fts.sql") PathSQLiteFTSMigration = path.Join("migrations/sqlite-fts.sql") PathDevIngestMigration = path.Join("migrations/dev-ingest.sql") )
var ( ErrUserNoRole = errors.New("user has no role") ErrUserNotFound = errors.New("user not found") )
var ( ErrUserAlreadyExists = errors.New("user already exists") ErrFailedGenerateUserULID = errors.New("failed to generate ULID for user") )
var ( ErrRecommendationAlreadyExists = errors.New("recommendation already exists") ErrFailedGenerateRecommendationULID = errors.New("failed to generate ULID for recommendation") )
var ( ErrRecruiterAlreadyExists = errors.New("recruiter already exists") ErrFailedGenerateRecruiterULID = errors.New("failed to generate ULID for recruiter") )
var ( ErrPositionAlreadyExists = errors.New("position already exists") ErrFailedGeneratePositionULID = errors.New("failed to generate ULID for position") )
var ( ErrCandidateAlreadyExists = errors.New("candidate already exists") ErrFailedGenerateCandidateULID = errors.New("failed to generate ULID for candidate") )
var ( ErrGoogleOIDCConfigNotInitialized = errors.New("Google OIDC configuration is not initialized") ErrAppleOIDCConfigNotInitialized = errors.New("Apple OIDC configuration is not initialized") )
var ( ErrFailedParseClaims = errors.New("failed to parse claims") ErrInvalidIDToken = errors.New("invalid id_token") )
var DefaultSQLiteConn = "file:.db?_pragma=foreign_keys(1)&_pragma=busy_timeout(5000)"
var EmbeddedStatic embed.FS
var ErrCandidateNotFound = errors.New("candidate not found")
var ErrEmailNotVerified = errors.New("email not verified")
var ErrEmbeddingsCountConflict = errors.New("mismatch between count of embedding IDs and embeddings")
var ErrEmptyCandidateProfile = errors.New("candidate profile is empty")
var ErrExtraDataDecoded = errors.New("extra data decoded")
var ErrFailedGenerateJTIULID = errors.New("failed to generate ULID for refresh token (JTI)")
var ErrFailedShutdownServer = errors.New("failed to shutdown server")
var ErrIDTokenRequired = errors.New("id_token is required")
var ErrInvalidProvider = errors.New("invalid provider")
var ErrMissingDatabaseURL = errors.New("database URL is not set")
var ErrPositionNotFound = errors.New("position not found")
var ErrPositionTitleHasURL = errors.New("position title must not contain URLs")
var ErrReactionAlreadyExists = errors.New("reaction already exists")
var ErrRecommendationNotFound = errors.New("recommendation not found")
var ErrRecruiterNotFound = errors.New("recruiter not found")
var ErrUnknownLogLevel = errors.New("unknown log level")
var ErrUnsupportedDatabaseProvider = errors.New("unsupported database provider")
var RegexFullName = regexp.MustCompile(`^[\pL][\pL\s'’-]{2,512}\z`)
var RegexHasTags = regexp.MustCompile(`<[^>]*>`)
var RegexTags = regexp.MustCompile(`<[^>]*>`)
var RegexUrl = regexp.MustCompile(`https?://|www\.`)
var RegexUserName = regexp.MustCompile(`^[a-zA-Z0-9_]+$`)
Functions ¶
func ConnectSQLite ¶
func CurrentTimestamp ¶
func EscapeSQLiteFTS ¶
EscapeSQLiteFTS prevents SQLite SQLITE_ERROR panics if a user types FTS operators (like double quotes, OR, AND, NOT, or asterisks) into their profile bio.
func GenerateUserName ¶
func GetenvAndParse ¶
GetenvAndParse parses extracted value of an environment variable and returns a default in case of an error.
func HashPassword ¶
func InitLogger ¶
func InitSQLite ¶
func IsValidPassword ¶
func LoadOrCreateAsymmetricKey ¶
func LoadOrCreateAsymmetricKey(val string) (paseto.V4AsymmetricSecretKey, error)
func LoadOrCreateSymmetricKey ¶
func LoadOrCreateSymmetricKey(val string) (paseto.V4SymmetricKey, error)
func MiddlewareChain ¶
func MiddlewareChain(handler http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc
func NormalizeAndValidateUserFullName ¶
TODO: Return an array of errors instead of one by one.
func ValidateUserPassword ¶
Types ¶
type API ¶
func (*API) CreateAccessToken ¶
func (*API) HandlerCreateCandidate ¶
func (a *API) HandlerCreateCandidate() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerCreatePosition ¶
func (a *API) HandlerCreatePosition() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerCreateReaction ¶
func (a *API) HandlerCreateReaction() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerCreateRecruiter ¶
func (a *API) HandlerCreateRecruiter() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerCreateUser ¶
func (a *API) HandlerCreateUser() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerDeleteCandidate ¶
func (a *API) HandlerDeleteCandidate() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerDeletePosition ¶
func (a *API) HandlerDeletePosition() http.HandlerFunc
func (*API) HandlerDeleteRecruiter ¶
func (a *API) HandlerDeleteRecruiter() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerDeleteUser ¶
func (a *API) HandlerDeleteUser() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerGetCandidate ¶
func (a *API) HandlerGetCandidate() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerGetMatches ¶
func (a *API) HandlerGetMatches() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerGetPosition ¶
func (a *API) HandlerGetPosition() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerGetPositions ¶
func (a *API) HandlerGetPositions() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerGetReactions ¶
func (a *API) HandlerGetReactions() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerGetRecommendations ¶
func (a *API) HandlerGetRecommendations() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerGetRecruiter ¶
func (a *API) HandlerGetRecruiter() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerGetUser ¶
func (a *API) HandlerGetUser() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerHealth ¶
func (a *API) HandlerHealth(w http.ResponseWriter, r *http.Request)
func (*API) HandlerLoginViaEmail ¶
func (a *API) HandlerLoginViaEmail() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerLoginViaProvider ¶
func (a *API) HandlerLoginViaProvider() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerPatchCandidate ¶
func (a *API) HandlerPatchCandidate() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerPatchPosition ¶
func (a *API) HandlerPatchPosition() http.HandlerFunc
func (*API) HandlerPatchUser ¶
func (a *API) HandlerPatchUser() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerRefresh ¶
func (a *API) HandlerRefresh() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) HandlerSSOCallback ¶
func (a *API) HandlerSSOCallback() http.HandlerFunc
TODO: Write integration tests for this handler https://github.com/akvachan/hirevec-core/issues/34
func (*API) MiddlewareAuth ¶
func (a *API) MiddlewareAuth(roles map[Role]bool) Middleware
func (*API) MiddlewareLogging ¶
func (a *API) MiddlewareLogging(next http.HandlerFunc) http.HandlerFunc
func (*API) MiddlewareMaxBytesLimit ¶
func (a *API) MiddlewareMaxBytesLimit(next http.HandlerFunc) http.HandlerFunc
func (*API) MiddlewarePanicRecovery ¶
func (a *API) MiddlewarePanicRecovery(next http.HandlerFunc) http.HandlerFunc
func (*API) PrivateRoute ¶
func (a *API) PrivateRoute(c RouteConfig)
func (*API) PublicRoute ¶
func (a *API) PublicRoute(c RouteConfig)
func (*API) RegisterRoutes ¶
func (a *API) RegisterRoutes()
func (*API) RunEmbeddingsJob ¶
func (*API) RunRecommendationsJob ¶
type APIConfig ¶
type APIConfig struct {
ServerBaseURL string
RequestReadTimeout time.Duration
RequestWriteTimeout time.Duration
GracePeriod time.Duration
UseGoogleSSO bool
UseAppleSSO bool
TEIBaseURL string
TEIAPIKey string
EmbeddingsModel string
RerankerModel string
UseEmbeddings bool
UseReranker bool
EmbeddingsJobFrequency time.Duration
RecommendationsJobFrequency time.Duration
}
type AccessToken ¶
type AccessTokenClaims ¶
type AppConfig ¶
type AppConfig struct {
ServerBaseURL string
LogLevel slog.Level
RequestReadTimeout time.Duration
RequestWriteTimeout time.Duration
GracePeriod time.Duration
EmbeddingsJobFrequency time.Duration
RecommendationsJobFrequency time.Duration
SymmetricKey string
AsymmetricKey string
AppleClientID string
AppleClientSecret string
GoogleClientID string
GoogleClientSecret string
PostgreSQLDatabaseURL string
TEIAPIKey string
TEIBaseURL string
}
type AppleClaims ¶
type AppleClaims struct {
Sub string `json:"sub"`
Email string `json:"email"`
EmailVerified json.RawMessage `json:"email_verified"`
IsPrivateEmail string `json:"is_private_email"`
}
type DatabaseProvider ¶
type DatabaseProvider string
const ( DatabaseProviderPostgreSQL DatabaseProvider = "PostgreSQL" DatabaseProviderSQLite DatabaseProvider = "SQLite" )
type EmbeddingEntity ¶
type EmbeddingEntity struct {
Embedding []float32 `json:"embedding"`
}
func CreateEmbeddings ¶
func CreateEmbeddings(aiConfig AIConfig, input []string) ([]EmbeddingEntity, error)
type EmbeddingStatus ¶
type EmbeddingStatus string
type EmbeddingsRequest ¶
type EmbeddingsResponse ¶
type EmbeddingsResponse struct {
Data []EmbeddingEntity `json:"data"`
}
type Envelope ¶
type Envelope struct {
// Data contains any main data to be consumed.
Data any `json:"data,omitempty"`
// Errors contains one or more errors when the request fails.
Errors []Error `json:"errors,omitempty"`
// Links contains top-level navigation or pagination URLs.
Links Links `json:"links,omitempty"`
// Meta contains additional information that is not links or errors or data.
Meta Meta `json:"meta,omitempty"`
}
Envelope is a wrapper that contains zero or more fields.
type Error ¶
type Error struct {
// Code is an application-specific error identifier used for programmatic handling.
Code string `json:"code,omitempty"`
// Message provides a detailed explanation of the error.
Message string `json:"detail,omitempty"`
// Source identifies the specific field or parameter that caused the error.
Source ErrorSource `json:"source,omitempty"`
}
Error represents a single error object returned when a request fails.
type ErrorSource ¶
type ErrorSource struct {
// Pointer is a JSON Pointer to the offending value in the request body.
Body string `json:"body,omitempty"`
// Parameter is the query string parameter that caused the error.
Parameter string `json:"parameter,omitempty"`
// Header is a string indicating the name of a single request header which caused the error.
Header string `json:"header,omitempty"`
// Cookie is a string indicating the name of a cookie which caused the error.
Cookie string `json:"cookie,omitempty"`
}
ErrorSource identifies where an error originated in the request.
type GoogleClaims ¶
type Links ¶
type Links struct {
// Next is a link to the next page in a paginated response.
Next string `json:"next,omitempty"`
// Previous is a link to the previous page in a paginated response.
Previous string `json:"previous,omitempty"`
}
Links contains URLs to other related pages.
type Meta ¶
type Meta struct {
// Page contains metadata about current page
Page Page `json:"page,omitempty"`
}
Meta contains that contains data that does not belong to Data, Errors, or Links.
type Method ¶
type Method string
const ( MethodPost Method = http.MethodPost MethodGet Method = http.MethodGet MethodPatch Method = http.MethodPatch MethodDelete Method = http.MethodDelete )
type Middleware ¶
type Middleware func(http.HandlerFunc) http.HandlerFunc
type OIDCConfig ¶
type OIDCConfig struct {
OAuth2Config *oauth2.Config
Verifier *oidc.IDTokenVerifier
}
type Page ¶
type Page struct {
Cursor string `json:"cursor,omitempty"`
Limit int `json:"limit"`
Count int `json:"count"`
HasNext bool `json:"has_next"`
}
func GetPageFromQuery ¶
type Reaction ¶
type Reaction struct {
RecommendationID ULID `json:"recommendation_id"`
ReactorType ReactorType `json:"-"`
ReactorID ULID `json:"-"`
ReactionType ReactionType `json:"reaction_type"`
ReactedAt time.Time `json:"reacted_at"`
}
type ReactionType ¶
type ReactionType string
const ( ReactionTypePositive ReactionType = "positive" ReactionTypeNegative ReactionType = "negative" ReactionTypeNeutral ReactionType = "neutral" )
func (ReactionType) IsValid ¶
func (r ReactionType) IsValid() bool
type ReactorType ¶
type ReactorType string
const ( ReactorTypeCandidate ReactorType = "candidate" ReactorTypeRecruiter ReactorType = "recruiter" )
func (ReactorType) IsValid ¶
func (r ReactorType) IsValid() bool
type Recommendation ¶
type RefreshToken ¶
type RefreshTokenClaims ¶
type RequestBodyCreateCandidate ¶
type RequestBodyCreateCandidate struct {
About string `json:"about"`
}
type RequestBodyCreateUser ¶
type RequestBodyPatchCandidate ¶
type RequestBodyPatchCandidate struct {
About *string `json:"about"`
}
type RequestBodyPatchUser ¶
type RequestBodyRefresh ¶
type RequestCreateReaction ¶
type RequestCreateReaction struct {
RecommendationID ULID `json:"recommendation_id"`
ReactionType ReactionType `json:"reaction_type"`
}
type ResponseDataHealth ¶
type ResponseDataHealth struct {
Status string `json:"status"`
}
type ResponseWriter ¶
type ResponseWriter struct {
http.ResponseWriter
// contains filtered or unexported fields
}
func (*ResponseWriter) WriteHeader ¶
func (rw *ResponseWriter) WriteHeader(code int)
type Route ¶
type Route string
const ( // Misc RouteHealth Route = "/health" // Authentication and authorization RouteCallback Route = "/callback" RouteLoginViaEmail Route = "/login" RouteLoginViaProvider Route = "/login/{provider}" RouteRefresh Route = "/refresh" // Resources and collections RouteCandidate Route = "/candidate" RouteCandidates Route = "/candidates" RouteMatches Route = "/matches" RoutePosition Route = "/positions/{id}" RoutePositions Route = "/positions" RouteReactions Route = "/reactions" RouteRecommendations Route = "/recommendations" RouteRecruiter Route = "/recruiter" RouteRecruiters Route = "/recruiters" RouteUser Route = "/user" RouteUsers Route = "/users" )
type RouteConfig ¶
type RouteConfig struct {
Method Method
Handler http.HandlerFunc
Middlewares []Middleware
Route Route
Roles []Role
}
type StateTokenClaims ¶
type StateTokenClaims struct {
CSRF string `json:"csrf"`
}
type Store ¶
type Store struct {
DatabaseProvider DatabaseProvider
DB *sql.DB
}
func NewStore ¶
func NewStore(c StoreConfig) (Store, error)
func (Store) CreateCandidate ¶
func (Store) CreatePosition ¶
func (Store) CreateReaction ¶
func (s Store) CreateReaction(recommendationID ULID, reactorType ReactorType, reactorID ULID, reactionType ReactionType) error
func (Store) CreateRecommendation ¶
func (Store) CreateRefreshToken ¶
func (Store) CreateUser ¶
func (Store) DeleteCandidate ¶
func (Store) DeletePosition ¶
func (Store) DeleteRecruiter ¶
func (Store) DeleteUser ¶
func (Store) FetchPendingEmbeddingsMetadata ¶
func (Store) GetCandidates ¶
func (Store) GetMatchesByCandidateID ¶
func (Store) GetPositions ¶
func (Store) GetPositionsForCandidateViaEmbeddings ¶
func (Store) GetPositionsForCandidateViaFTS ¶
func (Store) GetReactionsByCandidateID ¶
func (Store) GetRecommendation ¶
func (s Store) GetRecommendation(recommendationID ULID) (Recommendation, error)
func (Store) GetRecommendationsForCandidate ¶
func (Store) GetRecommendationsForRecruiter ¶
func (Store) GetUserAndRoles ¶
func (Store) GetUserAndRolesByEmail ¶
func (Store) GetUserIDAndRolesByProvider ¶
func (Store) GetUserRoles ¶
func (Store) MarkEmbeddingsStatus ¶
func (s Store) MarkEmbeddingsStatus(entityIDs []ULID, status EmbeddingStatus) error
func (Store) MarkEmbeddingsStatusTx ¶
func (Store) UpdateCandidate ¶
func (Store) UpdateCandidateAndReturn ¶
func (Store) UpdatePosition ¶
func (Store) UpdateUser ¶
func (Store) UpdateUserAndReturn ¶
func (Store) UpsertEmbeddingsTx ¶
type StoreConfig ¶
type StoreConfig struct {
DatabaseProvider DatabaseProvider
PostgreSQLDatabaseURL string
}
type ULID ¶
type ULID string
func NewCandidateULID ¶
func NewJTIULID ¶
func NewPositionULID ¶
func NewRecommendationULID ¶
func NewRecruiterULID ¶
func NewUserULID ¶
type Vault ¶
type Vault struct {
AccessTokenParser paseto.Parser
RefreshTokenParser paseto.Parser
StateTokenParser paseto.Parser
V4AsymmetricPublicKey paseto.V4AsymmetricPublicKey
V4AsymmetricSecretKey paseto.V4AsymmetricSecretKey
V4SymmetricKey paseto.V4SymmetricKey
UseGoogleSSO bool
UseAppleSSO bool
GoogleOIDCConfig *OIDCConfig
AppleOIDCConfig *OIDCConfig
RefreshTokenExpiration time.Duration
AccessTokenExpiration time.Duration
StateTokenExpiration time.Duration
VerifierExpiration time.Duration
}
func (Vault) CreateAccessToken ¶
func (Vault) CreateAuthCodeURL ¶
func (Vault) CreateRefreshToken ¶
func (Vault) CreateTokenPair ¶
func (Vault) ExchangeAppleCodeForIDToken ¶
func (Vault) ExchangeGoogleCodeForIDToken ¶
func (Vault) ParseAccessToken ¶
func (v Vault) ParseAccessToken(tokenString string) (AccessTokenClaims, error)
func (Vault) ParseRefreshToken ¶
func (v Vault) ParseRefreshToken(tokenString string) (RefreshTokenClaims, error)
func (Vault) ParseStateToken ¶
func (v Vault) ParseStateToken(raw string) (StateTokenClaims, error)