Refactor authentication handler
Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
@@ -16,12 +16,15 @@ package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
@@ -34,8 +37,24 @@ type (
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
ErrUserNotFound struct {
|
||||
Identifier string
|
||||
}
|
||||
|
||||
ErrUserAlreadyExists struct {
|
||||
message string
|
||||
}
|
||||
)
|
||||
|
||||
func (e ErrUserNotFound) Error() string {
|
||||
return fmt.Sprintf("user not found: %q", e.Identifier)
|
||||
}
|
||||
|
||||
func (e ErrUserAlreadyExists) Error() string {
|
||||
return e.message
|
||||
}
|
||||
|
||||
func (u User) CursorKey() page.CursorKey {
|
||||
return page.NewCursorKey(u.ID, u.CreatedAt)
|
||||
}
|
||||
@@ -69,6 +88,10 @@ LIMIT 1;
|
||||
|
||||
user, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[User])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return &ErrUserNotFound{Identifier: email}
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot collect user: %w", err)
|
||||
}
|
||||
|
||||
@@ -106,6 +129,10 @@ LIMIT 1;
|
||||
|
||||
user, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[User])
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return &ErrUserNotFound{Identifier: userID.String()}
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot collect user: %w", err)
|
||||
}
|
||||
|
||||
@@ -141,5 +168,19 @@ VALUES (
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
return err
|
||||
|
||||
if err != nil {
|
||||
var pgErr *pgconn.PgError
|
||||
if errors.As(err, &pgErr) {
|
||||
if pgErr.Code == "23505" && strings.Contains(pgErr.ConstraintName, "email_address") {
|
||||
return &ErrUserAlreadyExists{
|
||||
message: fmt.Sprintf("user with email %s already exists", u.EmailAddress),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -27,32 +27,34 @@ import (
|
||||
|
||||
type (
|
||||
Profile struct {
|
||||
minIterations uint
|
||||
saltLength uint
|
||||
keyLength uint
|
||||
pepper []byte
|
||||
iterations uint32
|
||||
saltLength uint
|
||||
keyLength uint
|
||||
pepper []byte
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
versionByte = 0x01 // Version identifier
|
||||
algorithmByte = 0x01 // Algorithm identifier (0x01 for PBKDF2-SHA256)
|
||||
|
||||
minIterations = 600000
|
||||
)
|
||||
|
||||
func NewProfile(pepper []byte) (*Profile, error) {
|
||||
func NewProfile(pepper []byte, iterations uint32) (*Profile, error) {
|
||||
if len(pepper) < 32 {
|
||||
return nil, fmt.Errorf("pepper must be at least 32 bytes")
|
||||
}
|
||||
|
||||
// NIST SP 800-63B recommendations:
|
||||
// - At least 32 bits of salt (we use 256 bits/32 bytes for extra security)
|
||||
// - At least 1000 iterations (we use higher based on processing capabilities)
|
||||
// - Resulting key length should be at least 160 bits (we use 256 bits)
|
||||
if iterations < minIterations {
|
||||
return nil, fmt.Errorf("iterations below minimum security threshold")
|
||||
}
|
||||
|
||||
return &Profile{
|
||||
minIterations: 600000, // Minimum iterations (adjusted based on hardware speed)
|
||||
saltLength: 32, // Salt length in bytes (256 bits)
|
||||
keyLength: 32, // Output key length in bytes (256 bits)
|
||||
pepper: pepper, // Pepper length in bytes (256 bits)
|
||||
iterations: iterations,
|
||||
saltLength: 32,
|
||||
keyLength: 32,
|
||||
pepper: pepper,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -62,14 +64,14 @@ func (hp Profile) applyPepper(input []byte) []byte {
|
||||
return mac.Sum(nil)
|
||||
}
|
||||
|
||||
func (hp Profile) HashPassword(password []byte, iterations uint32) ([]byte, error) {
|
||||
func (hp Profile) HashPassword(password []byte) ([]byte, error) {
|
||||
salt := make([]byte, hp.saltLength)
|
||||
if _, err := rand.Read(salt); err != nil {
|
||||
return nil, fmt.Errorf("error generating salt: %v", err)
|
||||
}
|
||||
|
||||
pepperedPassword := hp.applyPepper([]byte(password))
|
||||
hash := pbkdf2.Key(pepperedPassword, salt, int(iterations), int(hp.keyLength), sha256.New)
|
||||
hash := pbkdf2.Key(pepperedPassword, salt, int(hp.iterations), int(hp.keyLength), sha256.New)
|
||||
|
||||
// Binary format:
|
||||
// [1B version][1B algorithm][4B iterations][1B salt length][salt bytes][hash bytes]
|
||||
@@ -81,7 +83,7 @@ func (hp Profile) HashPassword(password []byte, iterations uint32) ([]byte, erro
|
||||
|
||||
// Iterations (4 bytes, big endian)
|
||||
iterBytes := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(iterBytes, iterations)
|
||||
binary.BigEndian.PutUint32(iterBytes, hp.iterations)
|
||||
binaryHash = append(binaryHash, iterBytes...)
|
||||
|
||||
// Salt length and salt
|
||||
@@ -110,13 +112,13 @@ func (hp Profile) ComparePasswordAndHash(password, passwordHash []byte) (bool, e
|
||||
// Extract iterations
|
||||
iterations := binary.BigEndian.Uint32(passwordHash[2:6])
|
||||
|
||||
if iterations < uint32(hp.minIterations) {
|
||||
if iterations < minIterations {
|
||||
return false, fmt.Errorf("iterations below minimum security threshold")
|
||||
}
|
||||
|
||||
// Extract salt length and validate
|
||||
saltLen := int(passwordHash[6])
|
||||
if saltLen < 32 { // NIST minimum requirement
|
||||
if saltLen < 32 {
|
||||
return false, fmt.Errorf("salt length below security minimum")
|
||||
}
|
||||
|
||||
|
||||
@@ -21,53 +21,57 @@ import (
|
||||
|
||||
type (
|
||||
authConfig struct {
|
||||
// Pepper is a secret key used for password hashing
|
||||
// It should be at least 32 bytes long
|
||||
Pepper string `json:"pepper"`
|
||||
SessionDuration int `json:"session-duration"`
|
||||
CookieName string `json:"cookie-name"`
|
||||
CookieSecure bool `json:"cookie-secure"`
|
||||
CookieHTTPOnly bool `json:"cookie-http-only"`
|
||||
CookieDomain string `json:"cookie-domain"`
|
||||
CookiePath string `json:"cookie-path"`
|
||||
CookieSecret string `json:"cookie-secret"`
|
||||
Cookie cookieConfig `json:"cookie"`
|
||||
Password passwordConfig `json:"password"`
|
||||
}
|
||||
|
||||
cookieConfig struct {
|
||||
Domain string `json:"domain"`
|
||||
Secret string `json:"secret"`
|
||||
Duration int `json:"duration"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
passwordConfig struct {
|
||||
Iterations uint32 `json:"iterations"`
|
||||
Pepper string `json:"pepper"`
|
||||
}
|
||||
)
|
||||
|
||||
func (c authConfig) GetPepperBytes() ([]byte, error) {
|
||||
if c.Pepper == "" {
|
||||
if c.Password.Pepper == "" {
|
||||
return nil, fmt.Errorf("pepper cannot be empty")
|
||||
}
|
||||
|
||||
if decoded, err := base64.StdEncoding.DecodeString(c.Pepper); err == nil {
|
||||
if decoded, err := base64.StdEncoding.DecodeString(c.Password.Pepper); err == nil {
|
||||
if len(decoded) < 32 {
|
||||
return nil, fmt.Errorf("decoded pepper must be at least 32 bytes long")
|
||||
}
|
||||
return decoded, nil
|
||||
}
|
||||
|
||||
if len(c.Pepper) < 32 {
|
||||
if len(c.Password.Pepper) < 32 {
|
||||
return nil, fmt.Errorf("pepper must be at least 32 bytes long")
|
||||
}
|
||||
|
||||
return []byte(c.Pepper), nil
|
||||
return []byte(c.Password.Pepper), nil
|
||||
}
|
||||
|
||||
func (c authConfig) GetCookieSecretBytes() ([]byte, error) {
|
||||
if c.CookieSecret == "" {
|
||||
if c.Cookie.Secret == "" {
|
||||
return nil, fmt.Errorf("cookie secret cannot be empty")
|
||||
}
|
||||
|
||||
if decoded, err := base64.StdEncoding.DecodeString(c.CookieSecret); err == nil {
|
||||
if decoded, err := base64.StdEncoding.DecodeString(c.Cookie.Secret); err == nil {
|
||||
if len(decoded) < 32 {
|
||||
return nil, fmt.Errorf("decoded cookie secret must be at least 32 bytes long")
|
||||
}
|
||||
return decoded, nil
|
||||
}
|
||||
|
||||
if len(c.CookieSecret) < 32 {
|
||||
if len(c.Cookie.Secret) < 32 {
|
||||
return nil, fmt.Errorf("cookie secret must be at least 32 bytes long")
|
||||
}
|
||||
|
||||
return []byte(c.CookieSecret), nil
|
||||
return []byte(c.Cookie.Secret), nil
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/getprobo/probo/pkg/awsconfig"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/crypto/passwdhash"
|
||||
"github.com/getprobo/probo/pkg/probo"
|
||||
"github.com/getprobo/probo/pkg/server"
|
||||
console_v1 "github.com/getprobo/probo/pkg/server/api/console/v1"
|
||||
@@ -75,14 +76,16 @@ func New() *Implm {
|
||||
PoolSize: 100,
|
||||
},
|
||||
Auth: authConfig{
|
||||
Pepper: "this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes",
|
||||
SessionDuration: 24,
|
||||
CookieName: "SSID",
|
||||
CookieSecure: false,
|
||||
CookieHTTPOnly: true,
|
||||
CookieDomain: "localhost",
|
||||
CookiePath: "/",
|
||||
CookieSecret: "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes",
|
||||
Password: passwordConfig{
|
||||
Pepper: "this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes",
|
||||
Iterations: 1000000,
|
||||
},
|
||||
Cookie: cookieConfig{
|
||||
Name: "SSID",
|
||||
Secret: "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes",
|
||||
Duration: 24,
|
||||
Domain: "localhost",
|
||||
},
|
||||
},
|
||||
AWS: awsConfig{
|
||||
Region: "us-east-1",
|
||||
@@ -153,7 +156,12 @@ func (impl *Implm) Run(
|
||||
return fmt.Errorf("cannot migrate database schema: %w", err)
|
||||
}
|
||||
|
||||
usrmgrService, err := usrmgr.NewService(ctx, pgClient, pepper)
|
||||
hp, err := passwdhash.NewProfile(pepper, uint32(impl.cfg.Auth.Password.Iterations))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create hashing profile: %w", err)
|
||||
}
|
||||
|
||||
usrmgrService, err := usrmgr.NewService(ctx, pgClient, hp)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create usrmgr service: %w", err)
|
||||
}
|
||||
@@ -169,13 +177,10 @@ func (impl *Implm) Run(
|
||||
Probo: proboService,
|
||||
Usrmgr: usrmgrService,
|
||||
Auth: console_v1.AuthConfig{
|
||||
CookieName: impl.cfg.Auth.CookieName,
|
||||
CookieSecure: impl.cfg.Auth.CookieSecure,
|
||||
CookieHTTPOnly: impl.cfg.Auth.CookieHTTPOnly,
|
||||
CookieDomain: impl.cfg.Auth.CookieDomain,
|
||||
CookiePath: impl.cfg.Auth.CookiePath,
|
||||
SessionDuration: time.Duration(impl.cfg.Auth.SessionDuration) * time.Hour,
|
||||
CookieSecret: impl.cfg.Auth.CookieSecret,
|
||||
CookieName: impl.cfg.Auth.Cookie.Name,
|
||||
CookieDomain: impl.cfg.Auth.Cookie.Domain,
|
||||
SessionDuration: time.Duration(impl.cfg.Auth.Cookie.Duration) * time.Hour,
|
||||
CookieSecret: impl.cfg.Auth.Cookie.Secret,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
164
pkg/securecookie/securecookie.go
Normal file
164
pkg/securecookie/securecookie.go
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package securecookie
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidCookie = errors.New("invalid cookie")
|
||||
ErrCookieNotFound = errors.New("cookie not found")
|
||||
ErrInvalidSignature = errors.New("invalid signature")
|
||||
)
|
||||
|
||||
// Config holds the configuration for secure cookies
|
||||
type Config struct {
|
||||
// Name is the name of the cookie
|
||||
Name string
|
||||
|
||||
// Secret is the secret key used for signing cookies
|
||||
Secret string
|
||||
|
||||
// Domain is the cookie domain
|
||||
Domain string
|
||||
|
||||
// Path is the cookie path
|
||||
Path string
|
||||
|
||||
// MaxAge is the maximum age of the cookie in seconds
|
||||
MaxAge int
|
||||
|
||||
// Secure indicates if the cookie should only be sent over HTTPS
|
||||
Secure bool
|
||||
|
||||
// HTTPOnly indicates if the cookie should be inaccessible to JavaScript
|
||||
HTTPOnly bool
|
||||
|
||||
// SameSite defines the SameSite attribute of the cookie
|
||||
SameSite http.SameSite
|
||||
}
|
||||
|
||||
// DefaultConfig returns a default secure cookie configuration
|
||||
func DefaultConfig(name, secret string) Config {
|
||||
return Config{
|
||||
Name: name,
|
||||
Secret: secret,
|
||||
Path: "/",
|
||||
MaxAge: 86400 * 30, // 30 days
|
||||
Secure: true,
|
||||
HTTPOnly: true,
|
||||
SameSite: http.SameSiteStrictMode,
|
||||
}
|
||||
}
|
||||
|
||||
// Set creates and sets a secure cookie with the given value
|
||||
func Set(w http.ResponseWriter, config Config, value string) error {
|
||||
signedValue, err := Sign(value, config.Secret)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to sign cookie value: %w", err)
|
||||
}
|
||||
|
||||
cookie := &http.Cookie{
|
||||
Name: config.Name,
|
||||
Value: signedValue,
|
||||
Path: config.Path,
|
||||
Domain: config.Domain,
|
||||
MaxAge: config.MaxAge,
|
||||
Secure: config.Secure,
|
||||
HttpOnly: config.HTTPOnly,
|
||||
SameSite: config.SameSite,
|
||||
}
|
||||
|
||||
http.SetCookie(w, cookie)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get retrieves and verifies a secure cookie
|
||||
func Get(r *http.Request, config Config) (string, error) {
|
||||
cookie, err := r.Cookie(config.Name)
|
||||
if err != nil {
|
||||
return "", ErrCookieNotFound
|
||||
}
|
||||
|
||||
value, err := Verify(cookie.Value, config.Secret)
|
||||
if err != nil {
|
||||
return "", ErrInvalidCookie
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// Clear removes a cookie by setting its expiration in the past
|
||||
func Clear(w http.ResponseWriter, config Config) {
|
||||
cookie := &http.Cookie{
|
||||
Name: config.Name,
|
||||
Value: "",
|
||||
Path: config.Path,
|
||||
Domain: config.Domain,
|
||||
MaxAge: -1,
|
||||
Expires: time.Now().Add(-1 * time.Hour),
|
||||
Secure: config.Secure,
|
||||
HttpOnly: config.HTTPOnly,
|
||||
SameSite: config.SameSite,
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
|
||||
// Sign creates a signed value using HMAC-SHA256
|
||||
func Sign(value, secret string) (string, error) {
|
||||
if secret == "" {
|
||||
return "", fmt.Errorf("secret cannot be empty")
|
||||
}
|
||||
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
h.Write([]byte(value))
|
||||
|
||||
signature := base64.RawURLEncoding.EncodeToString(h.Sum(nil))
|
||||
|
||||
return value + "." + signature, nil
|
||||
}
|
||||
|
||||
// Verify checks if a signed value is valid
|
||||
func Verify(signedValue, secret string) (string, error) {
|
||||
if secret == "" {
|
||||
return "", fmt.Errorf("secret cannot be empty")
|
||||
}
|
||||
|
||||
parts := strings.Split(signedValue, ".")
|
||||
if len(parts) != 2 {
|
||||
return "", fmt.Errorf("invalid signed value format")
|
||||
}
|
||||
|
||||
value := parts[0]
|
||||
|
||||
expectedSignedValue, err := Sign(value, secret)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to sign value: %w", err)
|
||||
}
|
||||
|
||||
if signedValue != expectedSignedValue {
|
||||
return "", ErrInvalidSignature
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
@@ -1,215 +1,21 @@
|
||||
package console_v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/usrmgr"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type (
|
||||
// RegisterRequest represents the request body for user registration
|
||||
RegisterRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
FullName string `json:"fullName"`
|
||||
}
|
||||
|
||||
// LoginRequest represents the request body for user login
|
||||
LoginRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// AuthResponse represents the response for successful authentication
|
||||
AuthResponse struct {
|
||||
User UserResponse `json:"user"`
|
||||
Session SessionResponse `json:"session"`
|
||||
}
|
||||
|
||||
// UserResponse represents user data in the authentication response
|
||||
UserResponse struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
FullName string `json:"fullName"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
// SessionResponse represents session data in the authentication response
|
||||
SessionResponse struct {
|
||||
ID gid.GID `json:"id"`
|
||||
ExpiresAt time.Time `json:"expiresAt"`
|
||||
}
|
||||
)
|
||||
|
||||
// RegisterHandler handles user registration
|
||||
func RegisterHandler(usrmgrSvc *usrmgr.Service, authCfg AuthConfig) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Parse request body
|
||||
var req RegisterRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate request
|
||||
if req.Email == "" || req.Password == "" {
|
||||
http.Error(w, "Email and password are required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Register the user
|
||||
user, err := usrmgrSvc.RegisterUser(
|
||||
r.Context(),
|
||||
usrmgr.RegisterUserParams{
|
||||
Email: req.Email,
|
||||
Password: req.Password,
|
||||
FullName: req.FullName,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to register user: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Log the user in
|
||||
session, err := usrmgrSvc.Login(r.Context(), req.Email, req.Password)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to login after registration: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Set the session cookie
|
||||
setSessionCookie(w, session.ID.String(), authCfg)
|
||||
|
||||
// Return response
|
||||
resp := AuthResponse{
|
||||
User: UserResponse{
|
||||
ID: user.ID,
|
||||
Email: user.EmailAddress,
|
||||
FullName: user.FullName,
|
||||
CreatedAt: user.CreatedAt,
|
||||
UpdatedAt: user.UpdatedAt,
|
||||
},
|
||||
Session: SessionResponse{
|
||||
ID: session.ID,
|
||||
ExpiresAt: session.ExpiredAt,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LoginHandler handles user login
|
||||
func LoginHandler(usrmgrSvc *usrmgr.Service, authCfg AuthConfig) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Parse request body
|
||||
var req LoginRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate request
|
||||
if req.Email == "" || req.Password == "" {
|
||||
http.Error(w, "Email and password are required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Login the user
|
||||
session, err := usrmgrSvc.Login(r.Context(), req.Email, req.Password)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to login: %v", err), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the user
|
||||
user, err := usrmgrSvc.GetUserBySession(r.Context(), session.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to get user: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Set the session cookie
|
||||
setSessionCookie(w, session.ID.String(), authCfg)
|
||||
|
||||
// Return response
|
||||
resp := AuthResponse{
|
||||
User: UserResponse{
|
||||
ID: user.ID,
|
||||
Email: user.EmailAddress,
|
||||
FullName: user.FullName,
|
||||
CreatedAt: user.CreatedAt,
|
||||
UpdatedAt: user.UpdatedAt,
|
||||
},
|
||||
Session: SessionResponse{
|
||||
ID: session.ID,
|
||||
ExpiresAt: session.ExpiredAt,
|
||||
},
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LogoutHandler handles user logout
|
||||
func LogoutHandler(usrmgrSvc *usrmgr.Service, authCfg AuthConfig) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Get session from cookie
|
||||
cookie, err := r.Cookie(authCfg.CookieName)
|
||||
if err != nil || cookie.Value == "" {
|
||||
http.Error(w, "No active session", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Verify the cookie signature
|
||||
originalValue, err := verifyCookieValue(cookie.Value, authCfg.CookieSecret)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid session cookie", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Parse the session ID
|
||||
sessionID, err := gid.ParseGID(originalValue)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid session ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Logout the user
|
||||
err = usrmgrSvc.Logout(r.Context(), sessionID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to logout: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Clear the session cookie
|
||||
clearSessionCookie(w, authCfg)
|
||||
|
||||
// Return success response
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]bool{"success": true})
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterAuthRoutes registers the authentication routes
|
||||
func RegisterAuthRoutes(r chi.Router, usrmgrSvc *usrmgr.Service, authCfg AuthConfig) {
|
||||
r.Post("/auth/register", RegisterHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/login", LoginHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/logout", LogoutHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/register", SignUpHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/login", SignInHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/logout", SignOutHandler(usrmgrSvc, authCfg))
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package console_v1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// setSessionCookie sets a session cookie in the response
|
||||
func setSessionCookie(w http.ResponseWriter, sessionID string, cfg AuthConfig) {
|
||||
// Sign the session ID
|
||||
signedValue := signCookieValue(sessionID, cfg.CookieSecret)
|
||||
|
||||
cookie := &http.Cookie{
|
||||
Name: cfg.CookieName,
|
||||
Value: signedValue,
|
||||
Path: cfg.CookiePath,
|
||||
Domain: cfg.CookieDomain,
|
||||
Secure: cfg.CookieSecure,
|
||||
HttpOnly: cfg.CookieHTTPOnly,
|
||||
MaxAge: int(cfg.SessionDuration.Seconds()),
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
|
||||
// clearSessionCookie clears the session cookie
|
||||
func clearSessionCookie(w http.ResponseWriter, cfg AuthConfig) {
|
||||
cookie := &http.Cookie{
|
||||
Name: cfg.CookieName,
|
||||
Value: "",
|
||||
Path: cfg.CookiePath,
|
||||
Domain: cfg.CookieDomain,
|
||||
Secure: cfg.CookieSecure,
|
||||
HttpOnly: cfg.CookieHTTPOnly,
|
||||
MaxAge: -1,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package console_v1
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func signCookieValue(value string, secret string) string {
|
||||
if secret == "" {
|
||||
panic(fmt.Errorf("cookie secret is not set"))
|
||||
}
|
||||
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
|
||||
h.Write([]byte(value))
|
||||
|
||||
signature := base64.URLEncoding.EncodeToString(h.Sum(nil))
|
||||
|
||||
return fmt.Sprintf("%s.%s", value, signature)
|
||||
}
|
||||
|
||||
func verifyCookieValue(signedValue string, secret string) (string, error) {
|
||||
if secret == "" {
|
||||
panic(fmt.Errorf("cookie secret is not set"))
|
||||
}
|
||||
|
||||
parts := strings.Split(signedValue, ".")
|
||||
if len(parts) != 2 {
|
||||
return "", fmt.Errorf("invalid signed cookie format")
|
||||
}
|
||||
|
||||
value, signature := parts[0], parts[1]
|
||||
|
||||
expectedSignedValue := signCookieValue(value, secret)
|
||||
expectedParts := strings.Split(expectedSignedValue, ".")
|
||||
if len(expectedParts) != 2 {
|
||||
return "", fmt.Errorf("error computing signature")
|
||||
}
|
||||
|
||||
expectedSignature := expectedParts[1]
|
||||
|
||||
if signature != expectedSignature {
|
||||
return "", fmt.Errorf("cookie signature verification failed")
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package console_v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -30,6 +31,7 @@ import (
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/probo"
|
||||
"github.com/getprobo/probo/pkg/securecookie"
|
||||
"github.com/getprobo/probo/pkg/server/api/console/v1/schema"
|
||||
"github.com/getprobo/probo/pkg/usrmgr"
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -39,10 +41,7 @@ import (
|
||||
type (
|
||||
AuthConfig struct {
|
||||
CookieName string
|
||||
CookieSecure bool
|
||||
CookieHTTPOnly bool
|
||||
CookieDomain string
|
||||
CookiePath string
|
||||
SessionDuration time.Duration
|
||||
CookieSecret string
|
||||
}
|
||||
@@ -141,28 +140,29 @@ func graphqlHandler(proboSvc *probo.Service, usrmgrSvc *usrmgr.Service, authCfg
|
||||
}
|
||||
ctx := context.WithValue(r.Context(), httpContextKey, httpCtx)
|
||||
|
||||
// Extract session from cookie
|
||||
cookie, err := r.Cookie(authCfg.CookieName)
|
||||
if err == nil && cookie.Value != "" {
|
||||
// Verify the cookie signature
|
||||
originalValue, err := verifyCookieValue(cookie.Value, authCfg.CookieSecret)
|
||||
if err == nil {
|
||||
// Parse the session ID
|
||||
sessionID, err := gid.ParseGID(originalValue)
|
||||
if err == nil {
|
||||
// Get the session
|
||||
session, err := usrmgrSvc.GetSession(r.Context(), sessionID)
|
||||
if err == nil {
|
||||
// Add session to context
|
||||
ctx = context.WithValue(ctx, sessionContextKey, session)
|
||||
cookieValue, err := securecookie.Get(r, securecookie.DefaultConfig(
|
||||
authCfg.CookieName,
|
||||
authCfg.CookieSecret,
|
||||
))
|
||||
if err != nil {
|
||||
if !errors.Is(err, securecookie.ErrCookieNotFound) {
|
||||
panic(fmt.Errorf("failed to get session: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// Get the user
|
||||
user, err := usrmgrSvc.GetUserBySession(r.Context(), sessionID)
|
||||
if err == nil {
|
||||
// Add user to context
|
||||
ctx = context.WithValue(ctx, userContextKey, user)
|
||||
}
|
||||
}
|
||||
sessionID, err := gid.ParseGID(cookieValue)
|
||||
if err == nil {
|
||||
// Get the session
|
||||
session, err := usrmgrSvc.GetSession(r.Context(), sessionID)
|
||||
if err == nil {
|
||||
// Add session to context
|
||||
ctx = context.WithValue(ctx, sessionContextKey, session)
|
||||
|
||||
// Get the user
|
||||
user, err := usrmgrSvc.GetUserBySession(r.Context(), sessionID)
|
||||
if err == nil {
|
||||
// Add user to context
|
||||
ctx = context.WithValue(ctx, userContextKey, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/99designs/gqlgen/graphql/introspection"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/server/api/console/v1/types"
|
||||
gqlparser "github.com/vektah/gqlparser/v2"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
@@ -1845,20 +1845,14 @@ enum ControlState
|
||||
|
||||
enum TaskState
|
||||
@goModel(model: "github.com/getprobo/probo/pkg/coredata.TaskState") {
|
||||
TODO
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.TaskStateTodo")
|
||||
DONE
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.TaskStateDone")
|
||||
TODO @goEnum(value: "github.com/getprobo/probo/pkg/coredata.TaskStateTodo")
|
||||
DONE @goEnum(value: "github.com/getprobo/probo/pkg/coredata.TaskStateDone")
|
||||
}
|
||||
|
||||
enum EvidenceState
|
||||
@goModel(
|
||||
model: "github.com/getprobo/probo/pkg/coredata.EvidenceState"
|
||||
) {
|
||||
@goModel(model: "github.com/getprobo/probo/pkg/coredata.EvidenceState") {
|
||||
VALID
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.EvidenceStateValid"
|
||||
)
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.EvidenceStateValid")
|
||||
INVALID
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.EvidenceStateInvalid"
|
||||
@@ -1872,9 +1866,7 @@ enum EvidenceState
|
||||
enum PeopleKind
|
||||
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PeopleKind") {
|
||||
EMPLOYEE
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.PeopleKindEmployee"
|
||||
)
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.PeopleKindEmployee")
|
||||
CONTRACTOR
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.PeopleKindContractor"
|
||||
@@ -2181,9 +2173,7 @@ input UpdatePeopleInput {
|
||||
}
|
||||
|
||||
enum ServiceCriticality
|
||||
@goModel(
|
||||
model: "github.com/getprobo/probo/pkg/coredata.ServiceCriticality"
|
||||
) {
|
||||
@goModel(model: "github.com/getprobo/probo/pkg/coredata.ServiceCriticality") {
|
||||
LOW
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.ServiceCriticalityLow"
|
||||
@@ -2201,17 +2191,11 @@ enum ServiceCriticality
|
||||
enum RiskTier
|
||||
@goModel(model: "github.com/getprobo/probo/pkg/coredata.RiskTier") {
|
||||
CRITICAL
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.RiskTierCritical"
|
||||
)
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.RiskTierCritical")
|
||||
SIGNIFICANT
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.RiskTierSignificant"
|
||||
)
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.RiskTierSignificant")
|
||||
GENERAL
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.RiskTierGeneral"
|
||||
)
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.RiskTierGeneral")
|
||||
}
|
||||
|
||||
input UpdateVendorInput {
|
||||
@@ -2352,13 +2336,9 @@ type DeleteEvidencePayload {
|
||||
enum PolicyStatus
|
||||
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyStatus") {
|
||||
DRAFT
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusDraft"
|
||||
)
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusDraft")
|
||||
ACTIVE
|
||||
@goEnum(
|
||||
value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusActive"
|
||||
)
|
||||
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusActive")
|
||||
}
|
||||
|
||||
input CreatePolicyInput {
|
||||
@@ -3871,7 +3851,7 @@ func (ec *executionContext) _Control_state(ctx context.Context, field graphql.Co
|
||||
}
|
||||
res := resTmp.(coredata.ControlState)
|
||||
fc.Result = res
|
||||
return ec.marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState(ctx, field.Selections, res)
|
||||
return ec.marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Control_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -4910,7 +4890,7 @@ func (ec *executionContext) _Evidence_state(ctx context.Context, field graphql.C
|
||||
}
|
||||
res := resTmp.(coredata.EvidenceState)
|
||||
fc.Result = res
|
||||
return ec.marshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐEvidenceState(ctx, field.Selections, res)
|
||||
return ec.marshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceState(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Evidence_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -7521,7 +7501,7 @@ func (ec *executionContext) _People_kind(ctx context.Context, field graphql.Coll
|
||||
}
|
||||
res := resTmp.(coredata.PeopleKind)
|
||||
fc.Result = res
|
||||
return ec.marshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind(ctx, field.Selections, res)
|
||||
return ec.marshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_People_kind(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -7973,7 +7953,7 @@ func (ec *executionContext) _Policy_status(ctx context.Context, field graphql.Co
|
||||
}
|
||||
res := resTmp.(coredata.PolicyStatus)
|
||||
fc.Result = res
|
||||
return ec.marshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus(ctx, field.Selections, res)
|
||||
return ec.marshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Policy_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -8840,7 +8820,7 @@ func (ec *executionContext) _Task_state(ctx context.Context, field graphql.Colle
|
||||
}
|
||||
res := resTmp.(coredata.TaskState)
|
||||
fc.Result = res
|
||||
return ec.marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState(ctx, field.Selections, res)
|
||||
return ec.marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Task_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -10007,7 +9987,7 @@ func (ec *executionContext) _Vendor_serviceCriticality(ctx context.Context, fiel
|
||||
}
|
||||
res := resTmp.(coredata.ServiceCriticality)
|
||||
fc.Result = res
|
||||
return ec.marshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality(ctx, field.Selections, res)
|
||||
return ec.marshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Vendor_serviceCriticality(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -10045,7 +10025,7 @@ func (ec *executionContext) _Vendor_riskTier(ctx context.Context, field graphql.
|
||||
}
|
||||
res := resTmp.(coredata.RiskTier)
|
||||
fc.Result = res
|
||||
return ec.marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier(ctx, field.Selections, res)
|
||||
return ec.marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Vendor_riskTier(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -12335,7 +12315,7 @@ func (ec *executionContext) unmarshalInputCreatePeopleInput(ctx context.Context,
|
||||
it.AdditionalEmailAddresses = data
|
||||
case "kind":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("kind"))
|
||||
data, err := ec.unmarshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind(ctx, v)
|
||||
data, err := ec.unmarshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -12383,7 +12363,7 @@ func (ec *executionContext) unmarshalInputCreatePolicyInput(ctx context.Context,
|
||||
it.Content = data
|
||||
case "status":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
|
||||
data, err := ec.unmarshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus(ctx, v)
|
||||
data, err := ec.unmarshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -12500,14 +12480,14 @@ func (ec *executionContext) unmarshalInputCreateVendorInput(ctx context.Context,
|
||||
it.ServiceTerminationAt = data
|
||||
case "serviceCriticality":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceCriticality"))
|
||||
data, err := ec.unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality(ctx, v)
|
||||
data, err := ec.unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.ServiceCriticality = data
|
||||
case "riskTier":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("riskTier"))
|
||||
data, err := ec.unmarshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier(ctx, v)
|
||||
data, err := ec.unmarshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -12752,7 +12732,7 @@ func (ec *executionContext) unmarshalInputUpdateControlInput(ctx context.Context
|
||||
it.Category = data
|
||||
case "state":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("state"))
|
||||
data, err := ec.unmarshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState(ctx, v)
|
||||
data, err := ec.unmarshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -12862,7 +12842,7 @@ func (ec *executionContext) unmarshalInputUpdatePeopleInput(ctx context.Context,
|
||||
it.AdditionalEmailAddresses = data
|
||||
case "kind":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("kind"))
|
||||
data, err := ec.unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind(ctx, v)
|
||||
data, err := ec.unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -12917,7 +12897,7 @@ func (ec *executionContext) unmarshalInputUpdatePolicyInput(ctx context.Context,
|
||||
it.Content = data
|
||||
case "status":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
|
||||
data, err := ec.unmarshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus(ctx, v)
|
||||
data, err := ec.unmarshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -12986,7 +12966,7 @@ func (ec *executionContext) unmarshalInputUpdateTaskInput(ctx context.Context, o
|
||||
it.Description = data
|
||||
case "state":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("state"))
|
||||
data, err := ec.unmarshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState(ctx, v)
|
||||
data, err := ec.unmarshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -13055,14 +13035,14 @@ func (ec *executionContext) unmarshalInputUpdateVendorInput(ctx context.Context,
|
||||
it.ServiceTerminationAt = data
|
||||
case "serviceCriticality":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("serviceCriticality"))
|
||||
data, err := ec.unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality(ctx, v)
|
||||
data, err := ec.unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.ServiceCriticality = data
|
||||
case "riskTier":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("riskTier"))
|
||||
data, err := ec.unmarshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier(ctx, v)
|
||||
data, err := ec.unmarshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -16415,14 +16395,14 @@ func (ec *executionContext) marshalNControlEdge2ᚖgithubᚗcomᚋgetproboᚋpro
|
||||
return ec._ControlEdge(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState(ctx context.Context, v any) (coredata.ControlState, error) {
|
||||
func (ec *executionContext) unmarshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState(ctx context.Context, v any) (coredata.ControlState, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState[tmp]
|
||||
res := unmarshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState(ctx context.Context, sel ast.SelectionSet, v coredata.ControlState) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState[v])
|
||||
func (ec *executionContext) marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState(ctx context.Context, sel ast.SelectionSet, v coredata.ControlState) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
@@ -16432,13 +16412,13 @@ func (ec *executionContext) marshalNControlState2githubᚗcomᚋgetproboᚋprobo
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState = map[string]coredata.ControlState{
|
||||
unmarshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState = map[string]coredata.ControlState{
|
||||
"NOT_STARTED": coredata.ControlStateNotStarted,
|
||||
"IN_PROGRESS": coredata.ControlStateInProgress,
|
||||
"NOT_APPLICABLE": coredata.ControlStateNotApplicable,
|
||||
"IMPLEMENTED": coredata.ControlStateImplemented,
|
||||
}
|
||||
marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState = map[coredata.ControlState]string{
|
||||
marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState = map[coredata.ControlState]string{
|
||||
coredata.ControlStateNotStarted: "NOT_STARTED",
|
||||
coredata.ControlStateInProgress: "IN_PROGRESS",
|
||||
coredata.ControlStateNotApplicable: "NOT_APPLICABLE",
|
||||
@@ -16795,14 +16775,14 @@ func (ec *executionContext) marshalNEvidenceEdge2ᚖgithubᚗcomᚋgetproboᚋpr
|
||||
return ec._EvidenceEdge(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐEvidenceState(ctx context.Context, v any) (coredata.EvidenceState, error) {
|
||||
func (ec *executionContext) unmarshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceState(ctx context.Context, v any) (coredata.EvidenceState, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐEvidenceState[tmp]
|
||||
res := unmarshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceState[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐEvidenceState(ctx context.Context, sel ast.SelectionSet, v coredata.EvidenceState) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐEvidenceState[v])
|
||||
func (ec *executionContext) marshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceState(ctx context.Context, sel ast.SelectionSet, v coredata.EvidenceState) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceState[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
@@ -16812,12 +16792,12 @@ func (ec *executionContext) marshalNEvidenceState2githubᚗcomᚋgetproboᚋprob
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐEvidenceState = map[string]coredata.EvidenceState{
|
||||
unmarshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceState = map[string]coredata.EvidenceState{
|
||||
"VALID": coredata.EvidenceStateValid,
|
||||
"INVALID": coredata.EvidenceStateInvalid,
|
||||
"EXPIRED": coredata.EvidenceStateExpired,
|
||||
}
|
||||
marshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐEvidenceState = map[coredata.EvidenceState]string{
|
||||
marshalNEvidenceState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐEvidenceState = map[coredata.EvidenceState]string{
|
||||
coredata.EvidenceStateValid: "VALID",
|
||||
coredata.EvidenceStateInvalid: "INVALID",
|
||||
coredata.EvidenceStateExpired: "EXPIRED",
|
||||
@@ -17094,14 +17074,14 @@ func (ec *executionContext) marshalNPeopleEdge2ᚖgithubᚗcomᚋgetproboᚋprob
|
||||
return ec._PeopleEdge(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind(ctx context.Context, v any) (coredata.PeopleKind, error) {
|
||||
func (ec *executionContext) unmarshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind(ctx context.Context, v any) (coredata.PeopleKind, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind[tmp]
|
||||
res := unmarshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind(ctx context.Context, sel ast.SelectionSet, v coredata.PeopleKind) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind[v])
|
||||
func (ec *executionContext) marshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind(ctx context.Context, sel ast.SelectionSet, v coredata.PeopleKind) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
@@ -17111,11 +17091,11 @@ func (ec *executionContext) marshalNPeopleKind2githubᚗcomᚋgetproboᚋprobo
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind = map[string]coredata.PeopleKind{
|
||||
unmarshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind = map[string]coredata.PeopleKind{
|
||||
"EMPLOYEE": coredata.PeopleKindEmployee,
|
||||
"CONTRACTOR": coredata.PeopleKindContractor,
|
||||
}
|
||||
marshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind = map[coredata.PeopleKind]string{
|
||||
marshalNPeopleKind2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind = map[coredata.PeopleKind]string{
|
||||
coredata.PeopleKindEmployee: "EMPLOYEE",
|
||||
coredata.PeopleKindContractor: "CONTRACTOR",
|
||||
}
|
||||
@@ -17193,14 +17173,14 @@ func (ec *executionContext) marshalNPolicyEdge2ᚖgithubᚗcomᚋgetproboᚋprob
|
||||
return ec._PolicyEdge(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus(ctx context.Context, v any) (coredata.PolicyStatus, error) {
|
||||
func (ec *executionContext) unmarshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus(ctx context.Context, v any) (coredata.PolicyStatus, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus[tmp]
|
||||
res := unmarshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus(ctx context.Context, sel ast.SelectionSet, v coredata.PolicyStatus) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus[v])
|
||||
func (ec *executionContext) marshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus(ctx context.Context, sel ast.SelectionSet, v coredata.PolicyStatus) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
@@ -17210,24 +17190,24 @@ func (ec *executionContext) marshalNPolicyStatus2githubᚗcomᚋgetproboᚋprobo
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus = map[string]coredata.PolicyStatus{
|
||||
unmarshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus = map[string]coredata.PolicyStatus{
|
||||
"DRAFT": coredata.PolicyStatusDraft,
|
||||
"ACTIVE": coredata.PolicyStatusActive,
|
||||
}
|
||||
marshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus = map[coredata.PolicyStatus]string{
|
||||
marshalNPolicyStatus2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus = map[coredata.PolicyStatus]string{
|
||||
coredata.PolicyStatusDraft: "DRAFT",
|
||||
coredata.PolicyStatusActive: "ACTIVE",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier(ctx context.Context, v any) (coredata.RiskTier, error) {
|
||||
func (ec *executionContext) unmarshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier(ctx context.Context, v any) (coredata.RiskTier, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier[tmp]
|
||||
res := unmarshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier(ctx context.Context, sel ast.SelectionSet, v coredata.RiskTier) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier[v])
|
||||
func (ec *executionContext) marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier(ctx context.Context, sel ast.SelectionSet, v coredata.RiskTier) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
@@ -17237,26 +17217,26 @@ func (ec *executionContext) marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋp
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier = map[string]coredata.RiskTier{
|
||||
unmarshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier = map[string]coredata.RiskTier{
|
||||
"CRITICAL": coredata.RiskTierCritical,
|
||||
"SIGNIFICANT": coredata.RiskTierSignificant,
|
||||
"GENERAL": coredata.RiskTierGeneral,
|
||||
}
|
||||
marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier = map[coredata.RiskTier]string{
|
||||
marshalNRiskTier2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier = map[coredata.RiskTier]string{
|
||||
coredata.RiskTierCritical: "CRITICAL",
|
||||
coredata.RiskTierSignificant: "SIGNIFICANT",
|
||||
coredata.RiskTierGeneral: "GENERAL",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality(ctx context.Context, v any) (coredata.ServiceCriticality, error) {
|
||||
func (ec *executionContext) unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx context.Context, v any) (coredata.ServiceCriticality, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality[tmp]
|
||||
res := unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality(ctx context.Context, sel ast.SelectionSet, v coredata.ServiceCriticality) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality[v])
|
||||
func (ec *executionContext) marshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx context.Context, sel ast.SelectionSet, v coredata.ServiceCriticality) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
@@ -17266,12 +17246,12 @@ func (ec *executionContext) marshalNServiceCriticality2githubᚗcomᚋgetprobo
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality = map[string]coredata.ServiceCriticality{
|
||||
unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality = map[string]coredata.ServiceCriticality{
|
||||
"LOW": coredata.ServiceCriticalityLow,
|
||||
"MEDIUM": coredata.ServiceCriticalityMedium,
|
||||
"HIGH": coredata.ServiceCriticalityHigh,
|
||||
}
|
||||
marshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality = map[coredata.ServiceCriticality]string{
|
||||
marshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality = map[coredata.ServiceCriticality]string{
|
||||
coredata.ServiceCriticalityLow: "LOW",
|
||||
coredata.ServiceCriticalityMedium: "MEDIUM",
|
||||
coredata.ServiceCriticalityHigh: "HIGH",
|
||||
@@ -17397,14 +17377,14 @@ func (ec *executionContext) marshalNTaskEdge2ᚖgithubᚗcomᚋgetproboᚋprobo
|
||||
return ec._TaskEdge(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState(ctx context.Context, v any) (coredata.TaskState, error) {
|
||||
func (ec *executionContext) unmarshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState(ctx context.Context, v any) (coredata.TaskState, error) {
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState[tmp]
|
||||
res := unmarshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState[tmp]
|
||||
return res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState(ctx context.Context, sel ast.SelectionSet, v coredata.TaskState) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState[v])
|
||||
func (ec *executionContext) marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState(ctx context.Context, sel ast.SelectionSet, v coredata.TaskState) graphql.Marshaler {
|
||||
res := graphql.MarshalString(marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState[v])
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
@@ -17414,11 +17394,11 @@ func (ec *executionContext) marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋ
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState = map[string]coredata.TaskState{
|
||||
unmarshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState = map[string]coredata.TaskState{
|
||||
"TODO": coredata.TaskStateTodo,
|
||||
"DONE": coredata.TaskStateDone,
|
||||
}
|
||||
marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState = map[coredata.TaskState]string{
|
||||
marshalNTaskState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState = map[coredata.TaskState]string{
|
||||
coredata.TaskStateTodo: "TODO",
|
||||
coredata.TaskStateDone: "DONE",
|
||||
}
|
||||
@@ -17913,31 +17893,31 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState(ctx context.Context, v any) (*coredata.ControlState, error) {
|
||||
func (ec *executionContext) unmarshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState(ctx context.Context, v any) (*coredata.ControlState, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState[tmp]
|
||||
res := unmarshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState[tmp]
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState(ctx context.Context, sel ast.SelectionSet, v *coredata.ControlState) graphql.Marshaler {
|
||||
func (ec *executionContext) marshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState(ctx context.Context, sel ast.SelectionSet, v *coredata.ControlState) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := graphql.MarshalString(marshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState[*v])
|
||||
res := graphql.MarshalString(marshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState[*v])
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState = map[string]coredata.ControlState{
|
||||
unmarshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState = map[string]coredata.ControlState{
|
||||
"NOT_STARTED": coredata.ControlStateNotStarted,
|
||||
"IN_PROGRESS": coredata.ControlStateInProgress,
|
||||
"NOT_APPLICABLE": coredata.ControlStateNotApplicable,
|
||||
"IMPLEMENTED": coredata.ControlStateImplemented,
|
||||
}
|
||||
marshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐControlState = map[coredata.ControlState]string{
|
||||
marshalOControlState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐControlState = map[coredata.ControlState]string{
|
||||
coredata.ControlStateNotStarted: "NOT_STARTED",
|
||||
coredata.ControlStateInProgress: "IN_PROGRESS",
|
||||
coredata.ControlStateNotApplicable: "NOT_APPLICABLE",
|
||||
@@ -18009,116 +17989,116 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind(ctx context.Context, v any) (*coredata.PeopleKind, error) {
|
||||
func (ec *executionContext) unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind(ctx context.Context, v any) (*coredata.PeopleKind, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind[tmp]
|
||||
res := unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind[tmp]
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind(ctx context.Context, sel ast.SelectionSet, v *coredata.PeopleKind) graphql.Marshaler {
|
||||
func (ec *executionContext) marshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind(ctx context.Context, sel ast.SelectionSet, v *coredata.PeopleKind) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := graphql.MarshalString(marshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind[*v])
|
||||
res := graphql.MarshalString(marshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind[*v])
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind = map[string]coredata.PeopleKind{
|
||||
unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind = map[string]coredata.PeopleKind{
|
||||
"EMPLOYEE": coredata.PeopleKindEmployee,
|
||||
"CONTRACTOR": coredata.PeopleKindContractor,
|
||||
}
|
||||
marshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPeopleKind = map[coredata.PeopleKind]string{
|
||||
marshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind = map[coredata.PeopleKind]string{
|
||||
coredata.PeopleKindEmployee: "EMPLOYEE",
|
||||
coredata.PeopleKindContractor: "CONTRACTOR",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus(ctx context.Context, v any) (*coredata.PolicyStatus, error) {
|
||||
func (ec *executionContext) unmarshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus(ctx context.Context, v any) (*coredata.PolicyStatus, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus[tmp]
|
||||
res := unmarshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus[tmp]
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus(ctx context.Context, sel ast.SelectionSet, v *coredata.PolicyStatus) graphql.Marshaler {
|
||||
func (ec *executionContext) marshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus(ctx context.Context, sel ast.SelectionSet, v *coredata.PolicyStatus) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := graphql.MarshalString(marshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus[*v])
|
||||
res := graphql.MarshalString(marshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus[*v])
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus = map[string]coredata.PolicyStatus{
|
||||
unmarshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus = map[string]coredata.PolicyStatus{
|
||||
"DRAFT": coredata.PolicyStatusDraft,
|
||||
"ACTIVE": coredata.PolicyStatusActive,
|
||||
}
|
||||
marshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐPolicyStatus = map[coredata.PolicyStatus]string{
|
||||
marshalOPolicyStatus2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPolicyStatus = map[coredata.PolicyStatus]string{
|
||||
coredata.PolicyStatusDraft: "DRAFT",
|
||||
coredata.PolicyStatusActive: "ACTIVE",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier(ctx context.Context, v any) (*coredata.RiskTier, error) {
|
||||
func (ec *executionContext) unmarshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier(ctx context.Context, v any) (*coredata.RiskTier, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier[tmp]
|
||||
res := unmarshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier[tmp]
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier(ctx context.Context, sel ast.SelectionSet, v *coredata.RiskTier) graphql.Marshaler {
|
||||
func (ec *executionContext) marshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier(ctx context.Context, sel ast.SelectionSet, v *coredata.RiskTier) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := graphql.MarshalString(marshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier[*v])
|
||||
res := graphql.MarshalString(marshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier[*v])
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier = map[string]coredata.RiskTier{
|
||||
unmarshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier = map[string]coredata.RiskTier{
|
||||
"CRITICAL": coredata.RiskTierCritical,
|
||||
"SIGNIFICANT": coredata.RiskTierSignificant,
|
||||
"GENERAL": coredata.RiskTierGeneral,
|
||||
}
|
||||
marshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐRiskTier = map[coredata.RiskTier]string{
|
||||
marshalORiskTier2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTier = map[coredata.RiskTier]string{
|
||||
coredata.RiskTierCritical: "CRITICAL",
|
||||
coredata.RiskTierSignificant: "SIGNIFICANT",
|
||||
coredata.RiskTierGeneral: "GENERAL",
|
||||
}
|
||||
)
|
||||
|
||||
func (ec *executionContext) unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality(ctx context.Context, v any) (*coredata.ServiceCriticality, error) {
|
||||
func (ec *executionContext) unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx context.Context, v any) (*coredata.ServiceCriticality, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality[tmp]
|
||||
res := unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality[tmp]
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality(ctx context.Context, sel ast.SelectionSet, v *coredata.ServiceCriticality) graphql.Marshaler {
|
||||
func (ec *executionContext) marshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx context.Context, sel ast.SelectionSet, v *coredata.ServiceCriticality) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := graphql.MarshalString(marshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality[*v])
|
||||
res := graphql.MarshalString(marshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality[*v])
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality = map[string]coredata.ServiceCriticality{
|
||||
unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality = map[string]coredata.ServiceCriticality{
|
||||
"LOW": coredata.ServiceCriticalityLow,
|
||||
"MEDIUM": coredata.ServiceCriticalityMedium,
|
||||
"HIGH": coredata.ServiceCriticalityHigh,
|
||||
}
|
||||
marshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐServiceCriticality = map[coredata.ServiceCriticality]string{
|
||||
marshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality = map[coredata.ServiceCriticality]string{
|
||||
coredata.ServiceCriticalityLow: "LOW",
|
||||
coredata.ServiceCriticalityMedium: "MEDIUM",
|
||||
coredata.ServiceCriticalityHigh: "HIGH",
|
||||
@@ -18179,29 +18159,29 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState(ctx context.Context, v any) (*coredata.TaskState, error) {
|
||||
func (ec *executionContext) unmarshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState(ctx context.Context, v any) (*coredata.TaskState, error) {
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
tmp, err := graphql.UnmarshalString(v)
|
||||
res := unmarshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState[tmp]
|
||||
res := unmarshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState[tmp]
|
||||
return &res, graphql.ErrorOnPath(ctx, err)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState(ctx context.Context, sel ast.SelectionSet, v *coredata.TaskState) graphql.Marshaler {
|
||||
func (ec *executionContext) marshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState(ctx context.Context, sel ast.SelectionSet, v *coredata.TaskState) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := graphql.MarshalString(marshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState[*v])
|
||||
res := graphql.MarshalString(marshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState[*v])
|
||||
return res
|
||||
}
|
||||
|
||||
var (
|
||||
unmarshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState = map[string]coredata.TaskState{
|
||||
unmarshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState = map[string]coredata.TaskState{
|
||||
"TODO": coredata.TaskStateTodo,
|
||||
"DONE": coredata.TaskStateDone,
|
||||
}
|
||||
marshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚐTaskState = map[coredata.TaskState]string{
|
||||
marshalOTaskState2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐTaskState = map[coredata.TaskState]string{
|
||||
coredata.TaskStateTodo: "TODO",
|
||||
coredata.TaskStateDone: "DONE",
|
||||
}
|
||||
|
||||
92
pkg/server/api/console/v1/sign_in_handler.go
Normal file
92
pkg/server/api/console/v1/sign_in_handler.go
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package console_v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/securecookie"
|
||||
"github.com/getprobo/probo/pkg/usrmgr"
|
||||
"go.gearno.de/kit/httpserver"
|
||||
)
|
||||
|
||||
type (
|
||||
SignInRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
SignInResponse struct {
|
||||
User UserResponse `json:"user"`
|
||||
}
|
||||
|
||||
UserResponse struct {
|
||||
ID gid.GID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
FullName string `json:"fullName"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
)
|
||||
|
||||
func SignInHandler(usrmgrSvc *usrmgr.Service, authCfg AuthConfig) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req SignInRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot decode body: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
user, session, err := usrmgrSvc.SignIn(r.Context(), req.Email, req.Password)
|
||||
if err != nil {
|
||||
var ErrInvalidCredentials *usrmgr.ErrInvalidCredentials
|
||||
if errors.As(err, &ErrInvalidCredentials) {
|
||||
httpserver.RenderError(w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("cannot sign in: %w", err))
|
||||
}
|
||||
|
||||
securecookie.Set(
|
||||
w,
|
||||
securecookie.DefaultConfig(
|
||||
authCfg.CookieName,
|
||||
authCfg.CookieSecret,
|
||||
),
|
||||
session.ID.String(),
|
||||
)
|
||||
|
||||
httpserver.RenderJSON(
|
||||
w,
|
||||
http.StatusOK,
|
||||
SignInResponse{
|
||||
User: UserResponse{
|
||||
ID: user.ID,
|
||||
Email: user.EmailAddress,
|
||||
FullName: user.FullName,
|
||||
CreatedAt: user.CreatedAt,
|
||||
UpdatedAt: user.UpdatedAt,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
57
pkg/server/api/console/v1/sign_out_handler.go
Normal file
57
pkg/server/api/console/v1/sign_out_handler.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package console_v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/securecookie"
|
||||
"github.com/getprobo/probo/pkg/usrmgr"
|
||||
"go.gearno.de/kit/httpserver"
|
||||
)
|
||||
|
||||
func SignOutHandler(usrmgrSvc *usrmgr.Service, authCfg AuthConfig) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
sessionID, err := securecookie.Get(r, securecookie.DefaultConfig(
|
||||
authCfg.CookieName,
|
||||
authCfg.CookieSecret,
|
||||
))
|
||||
if err != nil {
|
||||
httpserver.RenderError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
gid, err := gid.ParseGID(sessionID)
|
||||
if err != nil {
|
||||
httpserver.RenderError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = usrmgrSvc.SignOut(r.Context(), gid)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot sign out: %w", err))
|
||||
}
|
||||
|
||||
securecookie.Clear(w, securecookie.DefaultConfig(
|
||||
authCfg.CookieName,
|
||||
authCfg.CookieSecret,
|
||||
))
|
||||
|
||||
httpserver.RenderJSON(w, http.StatusOK, map[string]bool{"success": true})
|
||||
}
|
||||
}
|
||||
88
pkg/server/api/console/v1/sign_up_handler.go
Normal file
88
pkg/server/api/console/v1/sign_up_handler.go
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package console_v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/securecookie"
|
||||
"github.com/getprobo/probo/pkg/usrmgr"
|
||||
"go.gearno.de/kit/httpserver"
|
||||
)
|
||||
|
||||
type (
|
||||
SignUpRequest struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
FullName string `json:"fullName"`
|
||||
}
|
||||
|
||||
SignUpResponse struct {
|
||||
User UserResponse `json:"user"`
|
||||
}
|
||||
)
|
||||
|
||||
func SignUpHandler(usrmgrSvc *usrmgr.Service, authCfg AuthConfig) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req SignUpRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot decode body: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
user, session, err := usrmgrSvc.SignUp(
|
||||
r.Context(),
|
||||
req.Email,
|
||||
req.Password,
|
||||
req.FullName,
|
||||
)
|
||||
if err != nil {
|
||||
var errUserAlreadyExists *coredata.ErrUserAlreadyExists
|
||||
if errors.As(err, &errUserAlreadyExists) {
|
||||
httpserver.RenderError(w, http.StatusBadRequest, fmt.Errorf("cannot register user: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
panic(fmt.Errorf("cannot register user: %w", err))
|
||||
}
|
||||
|
||||
securecookie.Set(
|
||||
w,
|
||||
securecookie.DefaultConfig(
|
||||
authCfg.CookieName,
|
||||
authCfg.CookieSecret,
|
||||
),
|
||||
session.ID.String(),
|
||||
)
|
||||
|
||||
httpserver.RenderJSON(
|
||||
w,
|
||||
http.StatusOK,
|
||||
SignUpResponse{
|
||||
User: UserResponse{
|
||||
ID: user.ID,
|
||||
Email: user.EmailAddress,
|
||||
FullName: user.FullName,
|
||||
CreatedAt: user.CreatedAt,
|
||||
UpdatedAt: user.UpdatedAt,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
)
|
||||
|
||||
type Node interface {
|
||||
|
||||
@@ -16,7 +16,9 @@ package usrmgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/coredata"
|
||||
@@ -32,16 +34,22 @@ type (
|
||||
hp *passwdhash.Profile
|
||||
}
|
||||
|
||||
RegisterUserParams struct {
|
||||
Email string
|
||||
Password string
|
||||
FullName string
|
||||
}
|
||||
|
||||
ErrInvalidCredentials struct {
|
||||
message string
|
||||
}
|
||||
|
||||
ErrInvalidEmail struct {
|
||||
email string
|
||||
}
|
||||
|
||||
ErrInvalidPassword struct {
|
||||
length int
|
||||
}
|
||||
|
||||
ErrInvalidFullName struct {
|
||||
fullName string
|
||||
}
|
||||
|
||||
ErrUserAlreadyExists struct {
|
||||
message string
|
||||
}
|
||||
@@ -71,78 +79,93 @@ func (e ErrSessionExpired) Error() string {
|
||||
return e.message
|
||||
}
|
||||
|
||||
func (e ErrInvalidEmail) Error() string {
|
||||
return fmt.Sprintf("invalid email: %s", e.email)
|
||||
}
|
||||
|
||||
func (e ErrInvalidPassword) Error() string {
|
||||
return fmt.Sprintf("invalid password: the length must be at least %d characters", e.length)
|
||||
}
|
||||
|
||||
func (e ErrInvalidFullName) Error() string {
|
||||
return fmt.Sprintf("invalid full name: %s", e.fullName)
|
||||
}
|
||||
|
||||
func NewService(
|
||||
ctx context.Context,
|
||||
pgClient *pg.Client,
|
||||
pepper []byte,
|
||||
hp *passwdhash.Profile,
|
||||
) (*Service, error) {
|
||||
hp, err := passwdhash.NewProfile(pepper)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create hashing profile: %w", err)
|
||||
}
|
||||
|
||||
return &Service{
|
||||
pg: pgClient,
|
||||
hp: hp,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s Service) RegisterUser(
|
||||
func (s Service) SignUp(
|
||||
ctx context.Context,
|
||||
params RegisterUserParams,
|
||||
) (*coredata.User, error) {
|
||||
if params.Email == "" || params.Password == "" || params.FullName == "" {
|
||||
return nil, fmt.Errorf("email, password, and full name are required")
|
||||
email, password, fullName string,
|
||||
) (*coredata.User, *coredata.Session, error) {
|
||||
if !strings.Contains(email, "@") {
|
||||
return nil, nil, &ErrInvalidEmail{email}
|
||||
}
|
||||
|
||||
// Use a high iteration count for password hashing
|
||||
const iterations = 600000
|
||||
hashedPassword, err := s.hp.HashPassword([]byte(params.Password), iterations)
|
||||
if len(password) < 8 {
|
||||
return nil, nil, &ErrInvalidPassword{len(password)}
|
||||
}
|
||||
|
||||
if fullName == "" {
|
||||
return nil, nil, &ErrInvalidFullName{fullName}
|
||||
}
|
||||
|
||||
hashedPassword, err := s.hp.HashPassword([]byte(password))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot hash password: %w", err)
|
||||
return nil, nil, fmt.Errorf("cannot hash password: %w", err)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
user := &coredata.User{
|
||||
ID: gid.New(gid.NilTenant, coredata.UserEntityType),
|
||||
EmailAddress: params.Email,
|
||||
EmailAddress: email,
|
||||
HashedPassword: hashedPassword,
|
||||
FullName: params.FullName,
|
||||
FullName: fullName,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
session := &coredata.Session{
|
||||
ID: gid.New(gid.NilTenant, coredata.SessionEntityType),
|
||||
UserID: user.ID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err = s.pg.WithTx(
|
||||
ctx,
|
||||
func(tx pg.Conn) error {
|
||||
// Check if user already exists
|
||||
existingUser := &coredata.User{}
|
||||
err := existingUser.LoadByEmail(ctx, tx, params.Email)
|
||||
if err == nil {
|
||||
return &ErrUserAlreadyExists{message: "user with this email already exists"}
|
||||
}
|
||||
|
||||
// Insert the new user
|
||||
if err := user.Insert(ctx, tx); err != nil {
|
||||
return fmt.Errorf("cannot insert user: %w", err)
|
||||
}
|
||||
|
||||
if err := session.Insert(ctx, tx); err != nil {
|
||||
return fmt.Errorf("cannot insert session: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
return user, session, nil
|
||||
}
|
||||
|
||||
func (s Service) Login(
|
||||
func (s Service) SignIn(
|
||||
ctx context.Context,
|
||||
email string,
|
||||
password string,
|
||||
) (*coredata.Session, error) {
|
||||
email, password string,
|
||||
) (*coredata.User, *coredata.Session, error) {
|
||||
now := time.Now()
|
||||
user := &coredata.User{}
|
||||
session := &coredata.Session{
|
||||
@@ -157,7 +180,13 @@ func (s Service) Login(
|
||||
ctx,
|
||||
func(tx pg.Conn) error {
|
||||
if err := user.LoadByEmail(ctx, tx, email); err != nil {
|
||||
return &ErrInvalidCredentials{message: "invalid email or password"}
|
||||
var errUserNotFound *coredata.ErrUserNotFound
|
||||
|
||||
if errors.As(err, &errUserNotFound) {
|
||||
return &ErrInvalidCredentials{message: "invalid email or password"}
|
||||
}
|
||||
|
||||
return fmt.Errorf("cannot load user by email: %w", err)
|
||||
}
|
||||
|
||||
ok, err := s.hp.ComparePasswordAndHash([]byte(password), user.HashedPassword)
|
||||
@@ -169,7 +198,6 @@ func (s Service) Login(
|
||||
return &ErrInvalidCredentials{message: "invalid email or password"}
|
||||
}
|
||||
|
||||
// Set the user ID in the session
|
||||
session.UserID = user.ID
|
||||
|
||||
if err := session.Insert(ctx, tx); err != nil {
|
||||
@@ -181,20 +209,25 @@ func (s Service) Login(
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return session, nil
|
||||
return user, session, nil
|
||||
}
|
||||
|
||||
func (s Service) Logout(
|
||||
func (s Service) SignOut(
|
||||
ctx context.Context,
|
||||
sessionID gid.GID,
|
||||
) error {
|
||||
return s.pg.WithTx(
|
||||
return s.pg.WithConn(
|
||||
ctx,
|
||||
func(tx pg.Conn) error {
|
||||
return coredata.DeleteSession(ctx, tx, sessionID)
|
||||
err := coredata.DeleteSession(ctx, tx, sessionID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete session: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user