<commit_before>package authguard

import (
	"encoding/gob"
	"os"
)

type Options struct {
	Attempts        int
	LockoutDuration int // lockout time in seconds
	MaxLockouts     int // the maximum amount of lockouts, before ban
	BanDuration     int // subj; seconds
	ResetDuration   int // time after which to reset the number of lockouts
	BindToHost      bool
	BindToUserAgent bool

	UpdateDataDuration int // actualize records every X seconds
	UpdateDataAfter    int // actualize immediately after X updates

	SyncDuration int // sync every X seconds
	SyncAfter    int // sync immediately after X updates

	Store string // "::memory::", "/url/to/file"

	// LogDestination // TODO : make log writer

	// Exceptions

	// Backend // ql || gob || ...
}

// place for client data
type Client struct{}

type AuthGuard struct {
	options *Options
	file    *os.File
	data    []*Client
	// log // TODO : make logger

	// TODO : create mutex?
}

func New(o Options) (*AuthGuard, error) {
	ag := &AuthGuard{options: &o}

	if ag.options.Store == "::memory::" {
		// create new data struct and put in ag.data
	} else if ag.options.Store == "" {
		// error
	} else {
		data := []*Client{}
		// open gob file
		file, err := os.OpenFile(ag.options.Store, os.O_CREATE|os.O_RDWR|os.O_SYNC, 700)
		if err != nil {
			// return error
		}

		dec := gob.NewDecoder(file)
		if err := dec.Decode(&data); err != nil {
			// return error
		}

		ag.data = data
	}

	return ag, nil
}<commit_msg>WIP sync<commit_after>package authguard

import (
	"encoding/gob"
	"fmt"
	"net/http"
	"os"
	"sync"
	// "time"
)

// Options - structure, which is used to configure authguard.
type Options struct {
	Attempts        int
	LockoutDuration int // lockout time in seconds
	MaxLockouts     int // the maximum amount of lockouts, before ban
	BanDuration     int // subj; seconds
	ResetDuration   int // time after which to reset the number of lockouts
	BindToHost      bool
	BindToUserAgent bool

	UpdateDataDuration int // actualize records every X seconds
	UpdateDataAfter    int // actualize immediately after X updates

	SyncDuration int // sync every X seconds
	SyncAfter    int // sync immediately after X updates

	Store string // "::memory::", "/url/to/file"

	// LogDestination // TODO : make log writer

	// Exceptions

	// Backend // ql || gob || ...
}

// place for client data
type Client struct {
	ag *AuthGuard
	mu sync.Mutex
}

// reset cliet
func (c *Client) Reset() {
	// reset
	// sync
}

// AuthGuard - main struct.
type AuthGuard struct {
	options *Options
	file    *os.File
	data    []*Client
	// log // TODO : make logger

	mu sync.Mutex
}

// New - init and return new AuthGuard struct.
func New(o Options) (*AuthGuard, error) {
	ag := &AuthGuard{options: &o}

	if ag.options.Store == "::memory::" {
		ag.data = []*Client{}
	} else if ag.options.Store == "" {
		return ag, fmt.Errorf("LoginRoute not declared\n")
	} else {
		data := []*Client{}

		file, err := os.OpenFile(
			ag.options.Store,
			os.O_CREATE|os.O_RDWR|os.O_SYNC,
			700,
		)
		if err != nil {
			return ag, fmt.Errorf("error to open Store file: %v\n", err)
		}

		dec := gob.NewDecoder(file)
		if err := dec.Decode(&data); err != nil {
			return ag, fmt.Errorf("error to read Store file: %v\n", err)
		}

		ag.data = data
	}

	// TODO : check options

	return ag, nil
}

func (ag *AuthGuard) sync() error {
	ag.mu.Lock()
	defer ag.mu.Unlock()

	enc := gob.NewEncoder(ag.file)
	if err := enc.Encode(&ag.data); err != nil {
		return fmt.Errorf("error to encode Store file: %v\n", err)
	}

	return nil
}

func (ag *AuthGuard) Check(req *http.Request) bool {
	// get client
	// check client
	// sync on fail
	return true
}
{'fraction_non_alphanumeric': 0.128680479825518, 'fraction_numerical': 0.0016357688113413304, 'mean_word_length': 2.798136645962733, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5793726', 'n_tokens_mistral': 1282, 'n_tokens_neox': 1214, 'n_words': 407}