hirevec

package module
v0.0.0-...-c894a94 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 5, 2026 License: MIT Imports: 23 Imported by: 0

README

Hirevec Core

About Hirevec

Hirevec is application that uses a recommendation engine to match candidates with positions and recruiters with candidates. This repository contains the core server implementation.

Philosophy

  • The server strives to be simple and lightweight, we intentionally avoid heavy fullstack frameworks.
  • The server follows HATEOAS philosophy, meaning that we provide next available actions (_links) in the response body where it is appropriate:
{
    "_links": {
      "reaction": {
        "href": "/v1/me/recommendations/rcm_01kmahehzgtq01pq9vy17579ve/reaction"
      },
      "self": {
        "href": "/v1/me/recommendations/rcm_01kmahehzgtq01pq9vy17579ve"
      }
    },
    "about": "Test candidate with full-stack experience",
    "candidate_id": "can_01kmahehzfmh1s64qg7d4szfrk",
    "full_name": "Test User",
    "recommendation_id": "rcm_01kmahehzgtq01pq9vy17579ve"
}
  • The server does not use any external build systems, package managers or shell scripts, thus trying to be as cross-platform as possible.
  • The system is designed to operate without additional infrastructure such as Redis or vector databases.
  • The server follows best practices and implements RFCs wherever it can. We do not make up our own concepts or conventions.

Quick Start

Requirements
  1. Copy .example.env and rename it to .env:
cp .example.env .env
  1. Set environment variables in .env:
    • Choose your own POSTGRES_USER and POSTGRES_PASSWORD.
    • Generate your own SYMMETRIC_KEY and ASYMMETRIC_KEY.
  2. Set up server dependencies:
go run cmd/setup/main.go --dev
  1. Run the Go server:
go run cmd/server/main.go
  1. Open http://localhost:8080/health.

Cleanup

In case, for whatever reason, you want to completely remove the database and everything created by the setup script, run cleanup script:

go run cmd/cleanup/main.go

CLI API Client

  1. Generate access token (token gives access to a test user with some data bound to it already):
go run cmd/token/main.go
  1. Set ACCESS_TOKEN either in shell environment variables or .env.
  2. Call the script with a path:
go run cmd/api/main.go "/v1/me/recommendations"

or

go run cmd/api/main.go "/v1/me/recommendations/{id}/reaction" POST '{"reaction_type":"positive"}'

Documentation

Overview

Package hirevec implements internal server features

Index

Constants

View Source
const (
	DefaultReadTimeout   = 2000 * time.Millisecond
	DefaultWriteTimeout  = 2000 * time.Millisecond
	DefaultGracePeriod   = 5000 * time.Millisecond
	DefaultPageSizeLimit = 50
	PageSizeMaxLimit     = 100
)
View Source
const (
	RouteHealth            = "/health"
	RouteOAuthToken        = "/oauth/token"
	RouteOAuthAuthorize    = "/oauth/authorize"
	RouteOAuthCallback     = "/oauth/callback"
	RouteMeRecommendations = "/v1/me/recommendations"
	RouteMeReactions       = "/v1/me/reactions"
	RouteMeMatches         = "/v1/me/matches"
	RouteMeReaction        = "/v1/me/recommendations/{id}/reaction"
)
View Source
const (
	DefaultRefreshTokenExpiration = 30 * 24 * time.Hour
	DefaultAccessTokenExpiration  = 30 * time.Minute
	DefaultStateTokenExpiration   = 10 * time.Minute
	DefaultVerifierExpiration     = 10 * time.Minute
	DefaultProvider               = ProviderGoogle
)
View Source
const (
	TokenAudience      = "api.hirevec.com"
	TokenIssuer        = "api.hirevec.com"
	StateTokenAudience = "oauth-state"
)
View Source
const DefaultLogLevel = slog.LevelError

Variables

View Source
var (
	ErrAboutForbiddenChars          = errors.New("about contains forbidden characters")
	ErrAboutTooLong                 = errors.New("about too long")
	ErrAboutTooShort                = errors.New("about too short")
	ErrEmailNotVerified             = errors.New("email not verified")
	ErrExtraDataDecoded             = errors.New("extra data decoded")
	ErrFailedBindAddress            = errors.New("failed to bind address")
	ErrFailedDecode                 = errors.New("failed to decode")
	ErrFailedGenerateUsernameSuffix = errors.New("failed to generate random username suffix")
	ErrFailedShutdownServer         = errors.New("failed to shutdown server")
	ErrNameForbiddenChars           = errors.New("name contains forbidden characters")
	ErrNameTooLong                  = errors.New("name too long")
	ErrNameTooShort                 = errors.New("name too short")
	ErrFailedCloseRequestBody       = errors.New("failed to close request body")
)
View Source
var (
	ErrFailedConnectDB       = errors.New("failed to connect to database")
	ErrFailedPingDB          = errors.New("failed to ping database")
	ErrUserNoRole            = errors.New("user has no role")
	ErrUserNotFound          = errors.New("user not found")
	ErrRecommendationExists  = errors.New("recommendation already exists")
	ErrCandidateNotFound     = errors.New("candidate not found")
	ErrRecruiterNotFound     = errors.New("recruiter not found")
	ErrReactionAlreadyExists = errors.New("reaction already exists")
)
View Source
var (
	ErrFailedSetScope                 = errors.New("failed to set scope")
	ErrFailedCreateAccessToken        = errors.New("failed to create access token")
	ErrFailedCreateAppleOIDCProvider  = errors.New("failed to create Apple OIDC provider")
	ErrFailedCreateGoogleOIDCProvider = errors.New("failed to create Google OIDC provider")
	ErrFailedCreateRefreshToken       = errors.New("failed to create refresh token")
	ErrFailedExchangeToken            = errors.New("failed to exchange tokens")
	ErrFailedLoadAsymmetricKey        = errors.New("failed to load asymmetric key")
	ErrFailedLoadSymmetricKey         = errors.New("failed to load symmetric key")
	ErrFailedParseClaims              = errors.New("failed to parse claims")
	ErrFailedParseJTI                 = errors.New("failed to parse jti")
	ErrFailedParseProvider            = errors.New("failed to parse provider")
	ErrFailedParseScope               = errors.New("failed to parse scope")
	ErrFailedParseTokenType           = errors.New("failed to parse token type")
	ErrFailedParseCSRF                = errors.New("failed to parse CSRF")
	ErrFailedSetProvider              = errors.New("failed to set provider")
	ErrFailedSetTokenType             = errors.New("failed to set token type")
	ErrIDTokenRequired                = errors.New("id_token required")
	ErrInvalidAccessToken             = errors.New("invalid access token")
	ErrInvalidIDToken                 = errors.New("invalid id_token")
	ErrInvalidProvider                = errors.New("invalid provider")
	ErrInvalidRefreshToken            = errors.New("invalid refresh token")
	ErrInvalidRole                    = errors.New("invalid role")
	ErrInvalidSubject                 = errors.New("invalid subject")
	ErrInvalidTokenType               = errors.New("invalid token type")
	ErrInvalidScopeValue              = errors.New("invalid scope value provided")
	ErrInvalidStateToken              = errors.New("invalid state token")
)

Functions

func AuthAccessToken

func AuthAccessToken(w http.ResponseWriter, accessToken AccessToken)

func AuthError

func AuthError(w http.ResponseWriter, code AuthErrorCode, description string)

func AuthTokenPair

func AuthTokenPair(w http.ResponseWriter, tokenPair TokenPair)

func BaseMiddleware

func BaseMiddleware(handler http.HandlerFunc) http.Handler

func Chain

func Chain(handler http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc

Chain wraps handler into a sequence of middlewares, each middleware is applied in the same order it is provided.

func CreateMeReaction

func CreateMeReaction(s StoreInterface) http.HandlerFunc

Records a candidate's reaction to a position recommendation.

func CreateOnboardingToken

func CreateOnboardingToken(v VaultInterface, w http.ResponseWriter, userID ULID, provider Provider)

func CreateTokenPair

func CreateTokenPair(s StoreInterface, v VaultInterface, w http.ResponseWriter, userID ULID, provider Provider, roles map[Role]ULID)

func DecodeRequestBody

func DecodeRequestBody[T any](r *http.Request) (*T, error)

func DeleteCookies

func DeleteCookies(w http.ResponseWriter, names []string)

func Error

func Error(w http.ResponseWriter, status int, message string)

func Fail

func Fail(w http.ResponseWriter, status int, data FailData)

func FinishAuthFlow

func FinishAuthFlow(s StoreInterface, v VaultInterface, w http.ResponseWriter, user User)

func GenerateUsername

func GenerateUsername() (string, error)

GenerateUsername creates username with a cryptographically random suffix

func GetMeMatches

func GetMeMatches(s StoreInterface) http.HandlerFunc

Returns all mutual matches for the authenticated candidate.

func GetMeReactions

func GetMeReactions(s StoreInterface) http.HandlerFunc

Returns all reactions made by the authenticated candidate.

func GetMeRecommendations

func GetMeRecommendations(s StoreInterface) http.HandlerFunc

Returns position recommendations for the authenticated candidate.

func Health

func Health(w http.ResponseWriter, r *http.Request)

func InitLogger

func InitLogger(config LoggerConfig)

func Logger

func Logger(next http.HandlerFunc) http.HandlerFunc

func MaxBytesLimiter

func MaxBytesLimiter(next http.HandlerFunc) http.HandlerFunc

func OAuthAuthorize

func OAuthAuthorize(v VaultInterface) http.HandlerFunc

func PanicHandler

func PanicHandler(next http.HandlerFunc) http.HandlerFunc

func ParseDurationWithDefault

func ParseDurationWithDefault(value string, defaultValue time.Duration) time.Duration

func ParseLogLevelWithDefault

func ParseLogLevelWithDefault(value string, defaultValue slog.Level) slog.Level

func ParseUint16WithDefault

func ParseUint16WithDefault(value string, defaultValue uint16) uint16

func ProtectedRoute

func ProtectedRoute(cfg RouteConfig, v VaultInterface)

func PublicRoute

func PublicRoute(cfg RouteConfig)

func Route

func Route(method Method, route string) string

func RunApp

func RunApp(c AppConfig) error

func SetAuthHeaders

func SetAuthHeaders(w http.ResponseWriter)

func SetDefaultHeaders

func SetDefaultHeaders(w http.ResponseWriter)

func SetUnauthorizedHeaders

func SetUnauthorizedHeaders(w http.ResponseWriter)

func Success

func Success(w http.ResponseWriter, status int, res Resource)

func Unauthorized

func Unauthorized(w http.ResponseWriter, code AuthErrorCode, description string)

func ValidateAbout

func ValidateAbout(about string) (string, error)

func ValidateName

func ValidateName(name string) (string, error)

func WaitAndShutdown

func WaitAndShutdown(ctx context.Context, server *http.Server, errCh chan error, gracePeriod time.Duration) error

func WriteJSON

func WriteJSON(w http.ResponseWriter, status int, data any)

WriteJSON implements a helper for writing HTTP status and encoding data.

Types

type AccessToken

type AccessToken struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   uint32 `json:"expires_in"`
	Scope       string `json:"scope"`
	UserID      ULID   `json:"user_id"`
	CandidateID ULID   `json:"candidate_id,omitempty"`
	RecruiterID ULID   `json:"recruiter_id,omitempty"`
}

type AccessTokenClaims

type AccessTokenClaims struct {
	UserID   ULID
	Provider Provider
	Roles    map[Role]ULID
}

func GetClaims

func GetClaims(r *http.Request) (*AccessTokenClaims, bool)

type AppConfig

type AppConfig struct {
	Protocol            string
	Host                string
	Port                string
	RequestReadTimeout  string
	RequestWriteTimeout string
	GracePeriod         string
	PostgresHost        string
	PostgresPort        string
	PostgresDB          string
	PostgresUser        string
	PostgresPassword    string
	LogLevel            string
	SymmetricKey        string
	AsymmetricKey       string
	GoogleClientID      string
	GoogleClientSecret  string
	AppleClientID       string
	AppleClientSecret   string
}

type AuthErrorCode

type AuthErrorCode string

AuthErrorCode defienes OAuth2 error codes, see [RFC6749](https://www.rfc-editor.org/rfc/rfc6749.txt).

const (
	/*
		The request is missing a required parameter, includes an
		unsupported parameter value (other than grant type),
		repeats a parameter, includes multiple credentials,
		utilizes more than one mechanism for authenticating the
		client, or is otherwise malformed.
	*/
	AuthInvalidRequest AuthErrorCode = "invalid_request"

	/*
		The provided authorization grant (e.g., authorization
		code, resource owner credentials) or refresh token is
		invalid, expired, revoked, does not match the redirection
		URI used in the authorization request, or was issued to
		another client.
	*/
	AuthInvalidGrant AuthErrorCode = "invalid_grant"

	/*
		Client authentication failed (e.g., unknown client, no
		client authentication included, or unsupported
		authentication method).  The authorization server MAY
		return an HTTP 401 (Unauthorized) status code to indicate
		which HTTP authentication schemes are supported.  If the
		client attempted to authenticate via the "Authorization"
		request header field, the authorization server MUST
		respond with an HTTP 401 (Unauthorized) status code and
		include the "WWW-Authenticate" response header field
		matching the authentication scheme used by the client.
	*/
	AuthInvalidClient AuthErrorCode = "invalid_client"

	/*
		The authenticated client is not authorized to use this
		authorization grant type.
	*/
	AuthUnauthorizedClient AuthErrorCode = "unauthorized_client"

	/*
		The authorization grant type is not supported by the
		authorization server.
	*/
	AuthUnsupportedGrantType AuthErrorCode = "unsupported_grant_type"
)

type AuthErrorResponse

type AuthErrorResponse struct {
	Error            AuthErrorCode `json:"error"`
	ErrorDescription string        `json:"error_description,omitempty"`
	ErrorURI         string        `json:"error_uri,omitempty"`
}

AuthErrorResponse defines OAuth2 error response.

type Candidate

type Candidate struct {
	ID     ULID   `json:"id"`
	UserID ULID   `json:"user_id,omitempty"`
	About  string `json:"about"`
}

Candidate represents a candidate profile

type CandidateRecommendation

type CandidateRecommendation struct {
	RecommendationID ULID   `json:"recommendation_id"`
	CandidateID      ULID   `json:"candidate_id"`
	UserName         string `json:"username"`
	FullName         string `json:"full_name,omitempty"`
	About            string `json:"about"`
}

type ContextKey

type ContextKey string
const (
	ContextKeyUserID ContextKey = "user_id"
	ContextKeyClaims ContextKey = "claims"
)

type Embedded

type Embedded map[string]any

type ErrorCode

type ErrorCode uint16

ErrorCode defines JSend error codes.

type ErrorResponse

type ErrorResponse struct {
	Status  ResponseStatus `json:"status"`
	Message string         `json:"message"`
	Code    ErrorCode      `json:"code,omitempty"`
}

type FailData

type FailData map[string]string

FailData defines [JSend](https://github.com/omniti-labs/jsend) request failure data.

type FailResponse

type FailResponse struct {
	Status ResponseStatus `json:"status"`
	Data   FailData       `json:"data,omitempty"`
	Links  Links          `json:"_links,omitempty"`
}

type IssuedTokenType

type IssuedTokenType string
const (
	IssuedTokenTypeRefreshToken IssuedTokenType = "urn:ietf:params:oauth:token-type:refresh_token"
	IssuedTokenTypeAccessToken  IssuedTokenType = "urn:ietf:params:oauth:token-type:access_token"
)
type Link struct {
	Href      string `json:"href"`
	Name      string `json:"name,omitempty"`
	Templated bool   `json:"templated,omitempty"`
}

Link defines a [HAL](https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-11) link object.

type Links map[RelType]Link

type LoggerConfig

type LoggerConfig struct {
	Level slog.Level
}

type Match

type Match struct {
	PositionID  ULID      `json:"position_id"`
	Title       string    `json:"title"`
	Description string    `json:"description"`
	Company     string    `json:"company"`
	MatchedAt   time.Time `json:"matched_at"`
}

type Method

type Method string
const (
	MethodGet  Method = http.MethodGet
	MethodPost Method = http.MethodPost
)

type Middleware

type Middleware func(http.HandlerFunc) http.HandlerFunc

func Authentication

func Authentication(v VaultInterface, allowedRoles []Role) Middleware

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 GetPagination

func GetPagination(r *http.Request) Page

type Position

type Position struct {
	ID          ULID   `json:"id"`
	RecruiterID ULID   `json:"recruiter_id"`
	Title       string `json:"title"`
	Description string `json:"description"`
	Company     string `json:"company"`
}

Position represents a job position

type PositionRecommendation

type PositionRecommendation struct {
	RecommendationID ULID   `json:"recommendation_id"`
	PositionID       ULID   `json:"position_id"`
	Title            string `json:"title"`
	Company          string `json:"company"`
	Description      string `json:"description"`
}

type Props

type Props map[string]any

type Provider

type Provider string
const (
	ProviderApple  Provider = "apple"
	ProviderGoogle Provider = "google"
)

func ToProvider

func ToProvider(str string, def Provider) (Provider, error)

func (Provider) Raw

func (p Provider) Raw() string

type Reaction

type Reaction struct {
	RecommendationID ULID         `json:"recommendation_id"`
	ReactorType      ReactorType  `json:"reactor_type"`
	ReactorID        ULID         `json:"reactor_id"`
	ReactionType     ReactionType `json:"reaction_type"`
	ReactedAt        time.Time    `json:"reacted_at"`
}

Reaction represents either a candidate or recruiter reaction to a recommendation

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 Recommendation struct {
	ID          ULID `json:"id"`
	PositionID  ULID `json:"position_id"`
	CandidateID ULID `json:"candidate_id"`
}

type Recruiter

type Recruiter struct {
	ID     ULID `json:"id"`
	UserID ULID `json:"user_id"`
}

Recruiter represents a recruiter profile

type RefreshToken

type RefreshToken struct {
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    uint32 `json:"expires_in"`
	UserID       ULID   `json:"user_id"`
}

type RefreshTokenClaims

type RefreshTokenClaims struct {
	UserID   ULID
	Provider Provider
	JTI      ULID
}

type RelType

type RelType string

RelType defines link relation type, see [RFC5988](https://www.rfc-editor.org/rfc/rfc5988.txt).

const (
	// All went well, and (usually) some data was returned.
	ResponseStatusSuccess = "success"

	// There was a problem with the data submitted, or some pre-condition of the API call wasn't satisfied.
	ResponseStatusFail = "fail"

	// An error occurred in processing the request, i.e. an exception was thrown.
	ResponseStatusError = "error"

	// Conveys an identifier for the link's context.
	RelTypeSelf RelType = "self"

	// Refers to a parent document in a hierarchy of documents.
	RelTypeUp RelType = "up"

	// Refers to the previous resource in an ordered series of resources.
	RelTypePrevious RelType = "previous"

	// Refers to the next resource in a ordered series of resources.
	RelTypeNext RelType = "next"

	// An IRI that refers to the furthest preceding resource in a series of resources.
	RelTypeFirst RelType = "first"

	// An IRI that refers to the furthest following resource in a series of resources.
	RelTypeLast RelType = "last"

	// Refers to an index.
	RelTypeIndex RelType = "index"

	// Refers to a resource offering help (more information, links to other sources information, etc.).
	RelTypeHelp RelType = "help"

	// Refers to a resource that can be used to edit the link's context.
	RelTypeEdit RelType = "edit"
)

type Resource

type Resource struct {
	Links    Links    `json:"_links,omitempty"`
	Embedded Embedded `json:"_embedded,omitempty"`
	Props    Props    `json:"-"`
}

Resource is a flat HAL Resource Object. _links, _embedded, and all

func (Resource) MarshalJSON

func (res Resource) MarshalJSON() ([]byte, error)

type ResponseStatus

type ResponseStatus string

ResponseStatus defines JSend status codes.

type ResponseWriter

type ResponseWriter struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

func (*ResponseWriter) WriteHeader

func (rw *ResponseWriter) WriteHeader(code int)

type Role

type Role string
const (
	RoleCandidate  Role = "candidate"
	RoleRecruiter  Role = "recruiter"
	RoleOnboarding Role = "onboarding"
)

type RouteConfig

type RouteConfig struct {
	Mux           *http.ServeMux
	Method        Method
	Route         string
	Handler       http.HandlerFunc
	RequiredRoles []Role // required for protected routes
}

type Scope

type Scope []ScopeValue

func RolesToScope

func RolesToScope(roles map[Role]ULID) (*Scope, error)

func (Scope) Raw

func (s Scope) Raw() string

type ScopeValue

type ScopeValue string
const (
	ScopeValueCandidate  ScopeValue = "role:candidate"
	ScopeValueRecruiter  ScopeValue = "role:recruiter"
	ScopeValueOnboarding ScopeValue = "role:onboarding"
)

func ToScopeValue

func ToScopeValue(str string) (ScopeValue, error)

type ServerConfig

type ServerConfig struct {
	Protocol     string
	Host         string
	Port         uint16
	ReadTimeout  time.Duration
	WriteTimeout time.Duration
	GracePeriod  time.Duration
}

type StateTokenClaims

type StateTokenClaims struct {
	Provider Provider `json:"provider"`
	CSRF     string   `json:"csrf"`
}

type StoreConfig

type StoreConfig struct {
	PostgresHost     string
	PostgresPort     uint16
	PostgresDB       string
	PostgresUser     string
	PostgresPassword string
}

type StoreImpl

type StoreImpl struct {
	Postgres *sql.DB
}

func NewStore

func NewStore(c StoreConfig) (*StoreImpl, error)

func (StoreImpl) CreateCandidate

func (s StoreImpl) CreateCandidate(c Candidate) error

CreateCandidate creates a candidate

func (StoreImpl) CreateReaction

func (s StoreImpl) CreateReaction(r Reaction) error

CreateReaction records a reaction (from a candidate or recruiter) to a recommendation.

func (StoreImpl) CreateRecommendation

func (s StoreImpl) CreateRecommendation(positionID, candidateID ULID) (ULID, error)

CreateRecommendation inserts a new recommendation for a candidate and a position.

func (StoreImpl) CreateRecruiter

func (s StoreImpl) CreateRecruiter(r Recruiter) error

CreateRecruiter creates a recruiter

func (StoreImpl) CreateRefreshToken

func (s StoreImpl) CreateRefreshToken(userID ULID, expiresAt time.Time) (jti ULID, err error)

CreateRefreshToken creates a new refresh token record.

func (StoreImpl) CreateUser

func (s StoreImpl) CreateUser(u User) (ULID, error)

CreateUser generates a unique username and inserts a new user record.

func (StoreImpl) GetCandidate

func (s StoreImpl) GetCandidate(id ULID) (*Candidate, error)

func (StoreImpl) GetCandidateByUserID

func (s StoreImpl) GetCandidateByUserID(userID ULID) (*Candidate, error)

GetCandidateByUserID fetches a candidate by their associated user ID.

func (StoreImpl) GetCandidateRecommendations

func (s StoreImpl) GetCandidateRecommendations(recruiterID ULID, page Page, excludeReacted bool) ([]CandidateRecommendation, ULID, error)

func (StoreImpl) GetMatchesByCandidateID

func (s StoreImpl) GetMatchesByCandidateID(candidateID ULID, page Page) (matches []Match, nextCursor ULID, err error)

GetMatchesByCandidateID returns paginated matches for a candidate.

func (StoreImpl) GetPosition

func (s StoreImpl) GetPosition(id ULID) (*Position, error)

func (StoreImpl) GetPositionRecommendations

func (s StoreImpl) GetPositionRecommendations(candidateID ULID, page Page, excludeReacted bool) (positionRecommendations []PositionRecommendation, nextCursor ULID, err error)

GetPositionRecommendations returns paginated position recommendations for a candidate.

func (StoreImpl) GetReactionsByCandidateID

func (s StoreImpl) GetReactionsByCandidateID(candidateID ULID, page Page) (reactions []Reaction, nextCursor ULID, err error)

GetReactionsByCandidateID returns paginated reactions made by a candidate.

func (StoreImpl) GetRecommendation

func (s StoreImpl) GetRecommendation(id ULID) (*Recommendation, error)

func (StoreImpl) GetRecruiterByUserID

func (s StoreImpl) GetRecruiterByUserID(userID ULID) (*Recruiter, error)

GetRecruiterByUserID fetches a recruiter by their associated user ID.

func (StoreImpl) GetUserByProvider

func (s StoreImpl) GetUserByProvider(provider Provider, providerUserID string) (ULID, map[Role]ULID, error)

GetUserByProvider retrieves an existing user and his role based on their provider details.

func (StoreImpl) GetUserRoles

func (s StoreImpl) GetUserRoles(userID ULID, provider Provider) (map[Role]ULID, error)

GetUserRoles fetches user roles by user's ID and provider.

func (StoreImpl) IsActiveSession

func (s StoreImpl) IsActiveSession(jti ULID) (bool, error)

IsActiveSession checks if the JTI exists and is not expired.

type StoreInterface

type StoreInterface interface {
	CreateCandidate(Candidate) error
	CreateReaction(Reaction) error
	CreateRecommendation(positionID, candidateID ULID) (ULID, error)
	CreateRecruiter(Recruiter) error
	CreateRefreshToken(userID ULID, expiresAt time.Time) (jti ULID, err error)
	CreateUser(User) (userID ULID, err error)
	GetReactionsByCandidateID(ULID, Page) (reactions []Reaction, nextCursor ULID, err error)
	GetMatchesByCandidateID(ULID, Page) (matches []Match, nextCursos ULID, err error)
	GetPosition(ULID) (*Position, error)
	GetUserByProvider(Provider, string) (ULID, map[Role]ULID, error)
	GetRecommendation(ULID) (*Recommendation, error)
	GetUserRoles(ULID, Provider) (map[Role]ULID, error)
	GetPositionRecommendations(candidateID ULID, page Page, excludeReacted bool) (positionRecommendations []PositionRecommendation, nextCursor ULID, err error)
	GetCandidateRecommendations(candidateID ULID, page Page, excludeReacted bool) (candidateRecommenations []CandidateRecommendation, nextCursor ULID, err error)
	IsActiveSession(jti ULID) (bool, error)
}

type TokenPair

type TokenPair struct {
	AccessToken  string `json:"access_token"`
	TokenType    string `json:"token_type"`
	ExpiresIn    uint32 `json:"expires_in"`
	RefreshToken string `json:"refresh_token"`
	Scope        string `json:"scope"`
	UserID       ULID   `json:"user_id"`
}

type ULID

type ULID string

func GetUserID

func GetUserID(r *http.Request) (ULID, bool)

type User

type User struct {
	ID             ULID     `json:"id,omitempty"`
	Provider       Provider `json:"provider,omitempty"`
	ProviderUserID string   `json:"provider_user_id,omitempty"`
	Email          string   `json:"email,omitempty"`
	FullName       string   `json:"full_name,omitempty"`
	UserName       string   `json:"user_name"`
}

User represents a system user

type VaultConfig

type VaultConfig struct {
	Host                   string
	Port                   string
	SymmetricKeyHex        string
	AsymmetricKeyHex       string
	GoogleClientID         string
	GoogleClientSecret     string
	AppleClientID          string
	AppleClientSecret      string
	RefreshTokenExpiration time.Duration
	AccessTokenExpiration  time.Duration
}

type VaultImpl

type VaultImpl struct {
	AccessTokenParser      paseto.Parser
	RefreshTokenParser     paseto.Parser
	StateTokenParser       paseto.Parser
	V4AsymmetricPublicKey  paseto.V4AsymmetricPublicKey
	V4AsymmetricSecretKey  paseto.V4AsymmetricSecretKey
	V4SymmetricKey         paseto.V4SymmetricKey
	GoogleOIDCConfig       OIDCConfig
	AppleOIDCConfig        OIDCConfig
	RefreshTokenExpiration time.Duration
	AccessTokenExpiration  time.Duration
}

func NewVault

func NewVault(ctx context.Context, cfg VaultConfig) (*VaultImpl, error)

func (VaultImpl) CreateAccessToken

func (v VaultImpl) CreateAccessToken(userID ULID, provider Provider, roles map[Role]ULID) (*AccessToken, error)

func (VaultImpl) CreateAuthCodeURL

func (v VaultImpl) CreateAuthCodeURL(state string, verifier string, provider Provider) (string, error)

func (VaultImpl) CreateRefreshToken

func (v VaultImpl) CreateRefreshToken(userID ULID, provider Provider, jti ULID) (*RefreshToken, error)

func (VaultImpl) CreateStateToken

func (v VaultImpl) CreateStateToken(provider Provider) (string, error)

func (VaultImpl) CreateTokenPair

func (v VaultImpl) CreateTokenPair(userID ULID, provider Provider, jti ULID, roles map[Role]ULID) (*TokenPair, error)

func (VaultImpl) ExchangeAppleCodeForIDToken

func (v VaultImpl) ExchangeAppleCodeForIDToken(ctx context.Context, code string, verifierCookie *http.Cookie) (string, error)

func (VaultImpl) ExchangeGoogleCodeForIDToken

func (v VaultImpl) ExchangeGoogleCodeForIDToken(ctx context.Context, code string, verifierCookie *http.Cookie) (string, error)

func (VaultImpl) ParseAccessToken

func (v VaultImpl) ParseAccessToken(tokenString string) (*AccessTokenClaims, error)

func (VaultImpl) ParseRefreshToken

func (v VaultImpl) ParseRefreshToken(tokenString string) (*RefreshTokenClaims, error)

func (VaultImpl) ParseStateToken

func (v VaultImpl) ParseStateToken(raw string) (*StateTokenClaims, error)

func (VaultImpl) VerifyAndParseAppleIDToken

func (v VaultImpl) VerifyAndParseAppleIDToken(ctx context.Context, rawIDToken string, userJSON string) (*User, error)

func (VaultImpl) VerifyAndParseGoogleIDToken

func (v VaultImpl) VerifyAndParseGoogleIDToken(ctx context.Context, rawIDToken string) (*User, error)

type VaultInterface

type VaultInterface interface {
	CreateAccessToken(userID ULID, provider Provider, roles map[Role]ULID) (*AccessToken, error)
	CreateAuthCodeURL(state string, verifier string, provider Provider) (string, error)
	CreateRefreshToken(userID ULID, provider Provider, jti ULID) (*RefreshToken, error)
	CreateTokenPair(userID ULID, provider Provider, jti ULID, roles map[Role]ULID) (*TokenPair, error)
	CreateStateToken(provider Provider) (string, error)
	ExchangeAppleCodeForIDToken(ctx context.Context, code string, verifier *http.Cookie) (string, error)
	ExchangeGoogleCodeForIDToken(ctx context.Context, code string, verifier *http.Cookie) (string, error)
	ParseAccessToken(token string) (*AccessTokenClaims, error)
	ParseRefreshToken(token string) (*RefreshTokenClaims, error)
	ParseStateToken(token string) (*StateTokenClaims, error)
	VerifyAndParseAppleIDToken(ctx context.Context, rawIDToken string, userJSON string) (*User, error)
	VerifyAndParseGoogleIDToken(ctx context.Context, rawIDToken string) (*User, error)
}

Directories

Path Synopsis
cmd
api command
cleanup command
common
Package common implements common helper functions for the scripts
Package common implements common helper functions for the scripts
server command
setup command
token command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL