first commit
This commit is contained in:
@@ -70,13 +70,7 @@ func (s *PasswordAuthenticator) Register(ctx context.Context, registration auth.
|
|||||||
Enabled: true,
|
Enabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := s.userRepository.CountUsers()
|
// TODO: create team "Espace personnel" and put user in it
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if count == 0 {
|
|
||||||
user.Administrator = true
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err = s.userRepository.CreateUser(user)
|
user, err = s.userRepository.CreateUser(user)
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package turso
|
package turso
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/golang-migrate/migrate/v4"
|
"github.com/golang-migrate/migrate/v4"
|
||||||
"github.com/golang-migrate/migrate/v4/database/sqlite3"
|
"github.com/golang-migrate/migrate/v4/database/sqlite3"
|
||||||
"github.com/golang-migrate/migrate/v4/source/iofs"
|
"github.com/golang-migrate/migrate/v4/source/iofs"
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/config"
|
"trankilou.fr/lassistanoque/backend/internal/config"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/domain"
|
"trankilou.fr/lassistanoque/backend/internal/domain"
|
||||||
@@ -18,11 +18,11 @@ import (
|
|||||||
var FS embed.FS
|
var FS embed.FS
|
||||||
|
|
||||||
type TursoDB struct {
|
type TursoDB struct {
|
||||||
DB *sqlx.DB
|
DB *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTursoDB(cfg *config.Config) (*TursoDB, error) {
|
func NewTursoDB(cfg *config.Config) (*TursoDB, error) {
|
||||||
db, err := sqlx.Connect("turso", cfg.DatabaseURL)
|
db, err := sql.Open("turso", cfg.DatabaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error connecting to db %: %s", cfg.DatabaseURL, err)
|
return nil, fmt.Errorf("error connecting to db %: %s", cfg.DatabaseURL, err)
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ func (db *TursoDB) Close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *TursoDB) Migrate() error {
|
func (db *TursoDB) Migrate() error {
|
||||||
sqldb := db.DB.DB
|
sqldb := db.DB
|
||||||
dbDriver, err := sqlite3.WithInstance(sqldb, &sqlite3.Config{})
|
dbDriver, err := sqlite3.WithInstance(sqldb, &sqlite3.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -57,13 +57,13 @@ func (db *TursoDB) Migrate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *TursoDB) UserRepository() domain.UserRepository {
|
func (db *TursoDB) UserRepository() domain.UserRepository {
|
||||||
return &TursoUserRepository{DB: db.DB}
|
return NewTursoUserRepository(db.DB)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *TursoDB) SettingsRepository() domain.SettingsRepository {
|
func (db *TursoDB) SettingsRepository() domain.SettingsRepository {
|
||||||
return &TursoSettingsRepository{DB: db.DB}
|
return NewTursoSettingsRepository(db.DB)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *TursoDB) FileRepository() domain.FileRepository {
|
func (db *TursoDB) FileRepository() domain.FileRepository {
|
||||||
return &TursoFileRepository{DB: db.DB}
|
return NewTursoFileRepository(db.DB)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +1,47 @@
|
|||||||
package turso
|
package turso
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"gitea.trankilou.fr/fabien/lasebuche"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/adapter/database/dberrors"
|
|
||||||
"trankilou.fr/lassistanoque/backend/internal/domain"
|
"trankilou.fr/lassistanoque/backend/internal/domain"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/utility"
|
"trankilou.fr/lassistanoque/backend/internal/utility"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TursoFileRepository struct {
|
type TursoFileRepository struct {
|
||||||
DB *sqlx.DB
|
db *sql.DB
|
||||||
|
FileTable lasebuche.Table[domain.File]
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTursoFileRepository(db *sql.DB) *TursoFileRepository {
|
||||||
|
dialect := lasebuche.NewSqliteDialect()
|
||||||
|
fileTable, err := lasebuche.NewTable[domain.File](db, dialect, "settings")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error creating lasebuche team table")
|
||||||
|
}
|
||||||
|
return &TursoFileRepository{
|
||||||
|
db: db,
|
||||||
|
FileTable: fileTable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TursoFileRepository) FindByID(id string) (*domain.File, error) {
|
func (fr *TursoFileRepository) FindByID(id string) (*domain.File, error) {
|
||||||
var file domain.File
|
return fr.FileTable.Get(id)
|
||||||
err := fr.DB.Get(&file, "select id, name, content_type, storage_path, storage_filename, date_created, date_updated, _version from files where id=$1", id)
|
|
||||||
return &file, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TursoFileRepository) Create(file *domain.File) (*domain.File, error) {
|
func (fr *TursoFileRepository) Create(file *domain.File) (*domain.File, error) {
|
||||||
file.ID = utility.GenID()
|
return fr.FileTable.Insert(file)
|
||||||
file.VersionId = utility.GenID()
|
|
||||||
file.DateCreated = time.Now()
|
|
||||||
file.DateUpdated = time.Now()
|
|
||||||
_, err := fr.DB.NamedExec(
|
|
||||||
`insert into files (id, name, content_type, storage_path, storage_filename, date_created, date_updated, _version)
|
|
||||||
values (:id, :name, :content_type, :storage_path, :storage_filename, :date_created, :date_updated, :_version)`,
|
|
||||||
file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return file, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TursoFileRepository) Update(file *domain.File) (*domain.File, error) {
|
func (fr *TursoFileRepository) Update(file *domain.File) (*domain.File, error) {
|
||||||
newVersion := utility.GenID()
|
return fr.FileTable.Update(file)
|
||||||
file.DateUpdated = time.Now()
|
|
||||||
res, err := fr.DB.Exec(
|
|
||||||
`update files
|
|
||||||
set name=$1,
|
|
||||||
content_type=$2,
|
|
||||||
storage_path=$3,
|
|
||||||
storage_filename=$4,
|
|
||||||
date_updated=$5,
|
|
||||||
_version=$6
|
|
||||||
where id=$7 and _version=$8`,
|
|
||||||
file.Name, file.ContentType, file.StoragePath, file.StorageFilename, file.DateUpdated,
|
|
||||||
newVersion, file.ID, file.VersionId,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if count, _ := res.RowsAffected(); count == 0 {
|
|
||||||
return nil, dberrors.ErrNoRowUpdated
|
|
||||||
}
|
|
||||||
|
|
||||||
file.VersionId = newVersion
|
|
||||||
|
|
||||||
return file, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TursoFileRepository) Delete(id string) error {
|
func (fr *TursoFileRepository) Delete(id string) error {
|
||||||
res, err := fr.DB.Exec("delete from files where id=$1", id)
|
return fr.FileTable.Delete(id)
|
||||||
if count, _ := res.RowsAffected(); count == 0 {
|
|
||||||
return dberrors.ErrNoRowUpdated
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TursoFileRepository) Upload(reader io.Reader, path string, name string, contentType string, replace bool) (*domain.File, error) {
|
func (fr *TursoFileRepository) Upload(reader io.Reader, path string, name string, contentType string, replace bool) (*domain.File, error) {
|
||||||
@@ -90,18 +63,9 @@ func (fr *TursoFileRepository) Upload(reader io.Reader, path string, name string
|
|||||||
Content: bytes,
|
Content: bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = fr.DB.NamedExec(
|
return fr.FileTable.Insert(file)
|
||||||
`insert into files (id, name, content_type, storage_path, storage_filename, date_created, date_updated, _version, content)
|
|
||||||
values (:id, :name, :content_type, :storage_path, :storage_filename, :date_created, :date_updated, :_version, :content)`,
|
|
||||||
file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return file, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TursoFileRepository) Download(id string) (*domain.File, error) {
|
func (fr *TursoFileRepository) Download(id string) (*domain.File, error) {
|
||||||
var file domain.File
|
return fr.FileTable.Get(id)
|
||||||
err := fr.DB.Get(&file, "select * from files where id=$1", id)
|
|
||||||
return &file, err
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ drop table system;
|
|||||||
drop table oidc;
|
drop table oidc;
|
||||||
drop table users;
|
drop table users;
|
||||||
drop table user_addresses;
|
drop table user_addresses;
|
||||||
|
drop table teams;
|
||||||
|
drop table user_teams;
|
||||||
drop table channels;
|
drop table channels;
|
||||||
drop table tools;
|
drop table tools;
|
||||||
drop table tasks;
|
drop table tasks;
|
||||||
drop table history;
|
drop table history;
|
||||||
|
drop table files;
|
||||||
|
drop table share;
|
||||||
|
|||||||
@@ -1,36 +1,46 @@
|
|||||||
create table providers (
|
create table providers (
|
||||||
id text not null primary key,
|
id text not null primary key,
|
||||||
name text,
|
team_id text not null,
|
||||||
|
name text not null,
|
||||||
key text,
|
key text,
|
||||||
url text,
|
url text,
|
||||||
_version text
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table models (
|
create table models (
|
||||||
id text not null primary key,
|
id text not null primary key,
|
||||||
provider_id text,
|
team_id text not null,
|
||||||
name text,
|
provider_id text not null,
|
||||||
modelname text,
|
name text not null default '',
|
||||||
configuration text,
|
modelname text not null default '',
|
||||||
_version text
|
configuration text not null default '{}',
|
||||||
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table settings (
|
create table settings (
|
||||||
chat_model_id text,
|
id text not null primary key,
|
||||||
default_lang text,
|
default_lang text not null default 'en',
|
||||||
register_enabled numeric,
|
register_enabled numeric not null default 1,
|
||||||
password_enabled numeric,
|
password_enabled numeric not null default 1,
|
||||||
_version text
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table oidc (
|
create table oidc (
|
||||||
id text not null primary key,
|
id text not null primary key,
|
||||||
label text,
|
label text not null,
|
||||||
domain text,
|
domain text not null,
|
||||||
client_id text,
|
client_id text not null,
|
||||||
client_secret text,
|
client_secret text not null,
|
||||||
wellknown_url text,
|
wellknown_url text not null,
|
||||||
_version text
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table users (
|
create table users (
|
||||||
@@ -41,55 +51,112 @@ create table users (
|
|||||||
email text not null unique,
|
email text not null unique,
|
||||||
picture text not null default '',
|
picture text not null default '',
|
||||||
enabled numeric default true,
|
enabled numeric default true,
|
||||||
administrator numeric default false,
|
theme text default 'auto',
|
||||||
|
lang text default 'en',
|
||||||
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
_version text not null
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table user_addresses (
|
create table user_addresses (
|
||||||
id text not null primary key,
|
id text not null primary key,
|
||||||
user_id text,
|
user_id text not null,
|
||||||
type text,
|
type text not null,
|
||||||
address text,
|
address text not null,
|
||||||
_version text
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
|
);
|
||||||
|
|
||||||
|
create table teams (
|
||||||
|
id text not null primary key,
|
||||||
|
label text not null,
|
||||||
|
default_model_id text,
|
||||||
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric ,
|
||||||
|
_version text not null
|
||||||
|
);
|
||||||
|
|
||||||
|
create table user_teams (
|
||||||
|
id text not null primary key,
|
||||||
|
user_id text not null,
|
||||||
|
team_id text not null,
|
||||||
|
administrator bool default 0,
|
||||||
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table channels (
|
create table channels (
|
||||||
id text not null primary key,
|
id text not null primary key,
|
||||||
name text,
|
team_id text not null,
|
||||||
type text,
|
name text not null,
|
||||||
enabled numeric,
|
type text not null,
|
||||||
configuration text,
|
enabled numeric not null default 1,
|
||||||
_version text
|
configuration text not null default '{}',
|
||||||
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table tools (
|
create table tools (
|
||||||
id text not null primary key,
|
id text not null primary key,
|
||||||
name text,
|
team_id text not null,
|
||||||
type text,
|
name text not null,
|
||||||
enabled numeric,
|
type text not null,
|
||||||
configuration text,
|
enabled numeric not null default 1,
|
||||||
_version text
|
configuration text not null default '{}',
|
||||||
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table tasks (
|
create table tasks (
|
||||||
id text not null primary key,
|
id text not null primary key,
|
||||||
owner_id text,
|
team_id text not null,
|
||||||
model_id text,
|
model_id text not null,
|
||||||
label text,
|
label text not null,
|
||||||
prompt text,
|
prompt text not null,
|
||||||
cron text,
|
cron text not null,
|
||||||
status text,
|
status text not null,
|
||||||
next_datetime numeric,
|
next_datetime numeric,
|
||||||
_version text
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table history (
|
create table history (
|
||||||
id text not null primary key,
|
id text not null primary key,
|
||||||
task_id text,
|
task_id text not null,
|
||||||
start_datetimle numeric,
|
start_datetime numeric,
|
||||||
end_datetime numeric,
|
end_datetime numeric,
|
||||||
prompt text,
|
prompt text not null,
|
||||||
log text,
|
log text not null,
|
||||||
response text,
|
response text not null,
|
||||||
_version text
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
|
);
|
||||||
|
|
||||||
|
create table files (
|
||||||
|
id text not null primary key,
|
||||||
|
name text not null default '',
|
||||||
|
content_type text not null default '',
|
||||||
|
storage_path text not null default '',
|
||||||
|
storage_filename text not null default '',
|
||||||
|
content blob,
|
||||||
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric ,
|
||||||
|
_version text not null
|
||||||
|
);
|
||||||
|
|
||||||
|
create table share (
|
||||||
|
id text not null primary key,
|
||||||
|
object_id text not null,
|
||||||
|
object_type text not null,
|
||||||
|
team_id text not null,
|
||||||
|
enabled numeric not null default 0,
|
||||||
|
_date_created numeric not null default current_timestamp,
|
||||||
|
_date_updated numeric,
|
||||||
|
_version text not null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
insert into settings (default_lang, register_enabled, password_enabled, _version)
|
insert into settings (id, default_lang, register_enabled, password_enabled, _version)
|
||||||
values ('en', true, true, 'init');
|
values ('settings', 'en', true, true, 'init');
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
drop table files;
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
create table files (
|
|
||||||
id text not null primary key,
|
|
||||||
name text not null default '',
|
|
||||||
content_type text not null default '',
|
|
||||||
storage_path text not null default '',
|
|
||||||
storage_filename text not null default '',
|
|
||||||
date_created numeric not null default current_timestamp,
|
|
||||||
date_updated numeric not null default 0,
|
|
||||||
content blob,
|
|
||||||
_version text not null
|
|
||||||
);
|
|
||||||
@@ -1,45 +1,34 @@
|
|||||||
package turso
|
package turso
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jmoiron/sqlx"
|
"database/sql"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/adapter/database/dberrors"
|
"log"
|
||||||
|
|
||||||
|
"gitea.trankilou.fr/fabien/lasebuche"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/domain"
|
"trankilou.fr/lassistanoque/backend/internal/domain"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/utility"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TursoSettingsRepository struct {
|
type TursoSettingsRepository struct {
|
||||||
DB *sqlx.DB
|
db *sql.DB
|
||||||
|
SettingsTable lasebuche.Table[domain.Settings]
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTursoSettingsRepository(db *sql.DB) *TursoSettingsRepository {
|
||||||
|
dialect := lasebuche.NewSqliteDialect()
|
||||||
|
settingsTable, err := lasebuche.NewTable[domain.Settings](db, dialect, "settings")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error creating lasebuche team table")
|
||||||
|
}
|
||||||
|
return &TursoSettingsRepository{
|
||||||
|
db: db,
|
||||||
|
SettingsTable: settingsTable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *TursoSettingsRepository) GetSettings() (*domain.Settings, error) {
|
func (sr *TursoSettingsRepository) GetSettings() (*domain.Settings, error) {
|
||||||
var settings domain.Settings
|
return sr.SettingsTable.Get("settings")
|
||||||
err := sr.DB.Get(&settings, "select * from settings limit 1")
|
|
||||||
return &settings, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sr *TursoSettingsRepository) UpdateSettings(setting *domain.Settings) (*domain.Settings, error) {
|
func (sr *TursoSettingsRepository) UpdateSettings(setting *domain.Settings) (*domain.Settings, error) {
|
||||||
newVersion := utility.GenID()
|
return sr.SettingsTable.Update(setting)
|
||||||
|
|
||||||
res, err := sr.DB.Exec(
|
|
||||||
`update settings
|
|
||||||
set chat_model_id=$1,
|
|
||||||
default_lang=$2,
|
|
||||||
register_enabled=$3,
|
|
||||||
password_enabled=$4,
|
|
||||||
_version=:$5
|
|
||||||
where _version=$6`,
|
|
||||||
setting.ChatModelID, setting.DefaultLang, setting.RegisterEnabled,
|
|
||||||
setting.PasswordEnabled, newVersion, setting.VersionId,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if count, _ := res.RowsAffected(); count == 0 {
|
|
||||||
return nil, dberrors.ErrNoRowUpdated
|
|
||||||
}
|
|
||||||
|
|
||||||
setting.VersionId = newVersion
|
|
||||||
|
|
||||||
return setting, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,90 +1,143 @@
|
|||||||
package turso
|
package turso
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jmoiron/sqlx"
|
"database/sql"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/adapter/database/dberrors"
|
"log"
|
||||||
|
|
||||||
"trankilou.fr/lassistanoque/backend/internal/domain"
|
"trankilou.fr/lassistanoque/backend/internal/domain"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/utility"
|
|
||||||
|
"gitea.trankilou.fr/fabien/lasebuche"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TursoUserRepository struct {
|
type TursoUserRepository struct {
|
||||||
DB *sqlx.DB
|
DB *sql.DB
|
||||||
|
UserTable lasebuche.Table[domain.User]
|
||||||
|
TeamTable lasebuche.Table[domain.Team]
|
||||||
|
UserTeamTable lasebuche.Table[domain.UserTeam]
|
||||||
|
AddressTable lasebuche.Table[domain.UserAddress]
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTursoUserRepository(db *sql.DB) *TursoUserRepository {
|
||||||
|
dialect := lasebuche.NewSqliteDialect()
|
||||||
|
userTable, err := lasebuche.NewTable[domain.User](db, dialect, "users")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error creating lasebuche user table")
|
||||||
|
}
|
||||||
|
teamTable, err := lasebuche.NewTable[domain.Team](db, dialect, "teams")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error creating lasebuche team table")
|
||||||
|
}
|
||||||
|
userTeamTable, err := lasebuche.NewTable[domain.UserTeam](db, dialect, "user_teams")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error creating lasebuche team table")
|
||||||
|
}
|
||||||
|
userAddressTable, err := lasebuche.NewTable[domain.UserAddress](db, dialect, "user_addresses")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error creating lasebuche team table")
|
||||||
|
}
|
||||||
|
return &TursoUserRepository{
|
||||||
|
DB: db,
|
||||||
|
UserTable: userTable,
|
||||||
|
TeamTable: teamTable,
|
||||||
|
UserTeamTable: userTeamTable,
|
||||||
|
AddressTable: userAddressTable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur *TursoUserRepository) FindUser(id string) (*domain.User, error) {
|
func (ur *TursoUserRepository) FindUser(id string) (*domain.User, error) {
|
||||||
var user domain.User
|
return ur.UserTable.Get(id)
|
||||||
err := ur.DB.Get(&user, "select * from users where id=$1", id)
|
|
||||||
return &user, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur *TursoUserRepository) FindUserByEmail(email string) (*domain.User, error) {
|
func (ur *TursoUserRepository) FindUserByEmail(email string) (*domain.User, error) {
|
||||||
var user domain.User
|
return ur.UserTable.SelectOne("email=$1", email)
|
||||||
err := ur.DB.Get(&user, "select * from users where email=$1", email)
|
|
||||||
return &user, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ur *TursoUserRepository) CountUsers() (int, error) {
|
|
||||||
var count int
|
|
||||||
err := ur.DB.Get(&count, "select count(*) from users")
|
|
||||||
return count, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur *TursoUserRepository) ListUsers() ([]*domain.User, error) {
|
func (ur *TursoUserRepository) ListUsers() ([]*domain.User, error) {
|
||||||
var users []*domain.User
|
return ur.UserTable.SelectWhere("")
|
||||||
err := ur.DB.Select(&users, "select * from users order by lastname, firstname")
|
|
||||||
return users, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur *TursoUserRepository) CreateUser(user *domain.User) (*domain.User, error) {
|
func (ur *TursoUserRepository) CreateUser(user *domain.User) (*domain.User, error) {
|
||||||
|
return ur.UserTable.Insert(user)
|
||||||
user.ID = utility.GenID()
|
|
||||||
user.VersionId = utility.GenID()
|
|
||||||
|
|
||||||
_, err := ur.DB.NamedExec(
|
|
||||||
`insert into users (id, email, firstname, lastname, enabled, password, administrator, _version)
|
|
||||||
values (:id, :email, :firstname, :lastname, :enabled, :password, :administrator, :_version)`,
|
|
||||||
user)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return user, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur *TursoUserRepository) UpdateUser(user *domain.User) (*domain.User, error) {
|
func (ur *TursoUserRepository) UpdateUser(user *domain.User) (*domain.User, error) {
|
||||||
|
return ur.UserTable.Update(user)
|
||||||
newVersion := utility.GenID()
|
|
||||||
|
|
||||||
res, err := ur.DB.Exec(
|
|
||||||
`update users
|
|
||||||
set email=$1,
|
|
||||||
firstname=$2,
|
|
||||||
lastname=$3,
|
|
||||||
enabled=$4,
|
|
||||||
administrator=$5
|
|
||||||
_version=:$6
|
|
||||||
where id=$7 and _version=$8`,
|
|
||||||
user.Email, user.Firstname, user.Lastname,
|
|
||||||
user.Enabled, user.Administrator,
|
|
||||||
newVersion, user.ID, user.VersionId,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if count, _ := res.RowsAffected(); count == 0 {
|
|
||||||
return nil, dberrors.ErrNoRowUpdated
|
|
||||||
}
|
|
||||||
|
|
||||||
user.VersionId = newVersion
|
|
||||||
|
|
||||||
return user, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur *TursoUserRepository) DeleteUser(id string) error {
|
func (ur *TursoUserRepository) DeleteUser(id string) error {
|
||||||
res, err := ur.DB.Exec("delete from users where id=$1", id)
|
return ur.UserTable.Delete(id)
|
||||||
if count, _ := res.RowsAffected(); count == 0 {
|
|
||||||
return dberrors.ErrNoRowUpdated
|
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
|
func (ur *TursoUserRepository) FindTeam(userid string, teamid string) (*domain.Team, error) {
|
||||||
|
return ur.TeamTable.SelectOne("id=$1 and user_id=$2", teamid, userid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) ListTeams(userid string) ([]*domain.Team, error) {
|
||||||
|
return ur.TeamTable.SelectWhere("user_id=$1", userid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) CreateTeam(userid string, team *domain.Team) (*domain.Team, error) {
|
||||||
|
// TODO : gérér dans une transaction
|
||||||
|
// TODO : déplacer dans le service
|
||||||
|
team, err := ur.TeamTable.Insert(team)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
userTeam := &domain.UserTeam{
|
||||||
|
UserID: userid,
|
||||||
|
TeamID: team.ID,
|
||||||
|
Administrator: true,
|
||||||
|
}
|
||||||
|
_, err = ur.UserTeamTable.Insert(userTeam)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return team, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) UpdateTeam(userid string, team *domain.Team) (*domain.Team, error) {
|
||||||
|
return ur.TeamTable.Update(team)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) DeleteTeam(userid string, teamid string) error {
|
||||||
|
return ur.TeamTable.Delete(teamid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) FindUserTeam(userid string, teamid string) (*domain.UserTeam, error) {
|
||||||
|
return ur.UserTeamTable.SelectOne("team_id=$1 and user_id=$2", teamid, userid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) ListUserTeams(userid string) ([]*domain.UserTeam, error) {
|
||||||
|
return ur.UserTeamTable.SelectWhere("user_id=$1", userid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) CreateUserTeam(userid string, team *domain.UserTeam) (*domain.UserTeam, error) {
|
||||||
|
return ur.UserTeamTable.Insert(team)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) UpdateUserTeam(userid string, team *domain.UserTeam) (*domain.UserTeam, error) {
|
||||||
|
return ur.UserTeamTable.Update(team)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) DeleteUserTeam(userid string, teamid string) error {
|
||||||
|
return ur.UserTeamTable.Delete(teamid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) PopulateUserWithTeams(user *domain.User) (*domain.UserWithTeams, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) ListUserAddresses(id string) ([]*domain.UserAddress, error) {
|
||||||
|
return ur.AddressTable.SelectWhere("user_id=$1", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ur *TursoUserRepository) CreateUserAddress(userid string, addr *domain.UserAddress) (*domain.UserAddress, error) {
|
||||||
|
addr.UserID = userid
|
||||||
|
return ur.AddressTable.Insert(addr)
|
||||||
|
}
|
||||||
|
func (ur *TursoUserRepository) UpdateUserAddress(userid string, addr *domain.UserAddress) (*domain.UserAddress, error) {
|
||||||
|
return ur.AddressTable.Update(addr)
|
||||||
|
}
|
||||||
|
func (ur *TursoUserRepository) DeleteUserAddress(userid string, addrID string) error {
|
||||||
|
return ur.AddressTable.DeleteWhere("id=$1 and user_id=$2", addrID, userid)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ type Claims struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Firstname string `json:"firstname"`
|
Firstname string `json:"firstname"`
|
||||||
Lastname string `json:"lastname"`
|
Lastname string `json:"lastname"`
|
||||||
Administrator bool `json:"administrator"`
|
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +48,6 @@ func (tm *JwtTokenManager) GenerateAccessToken(user *domain.User) (string, time.
|
|||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
Firstname: user.Firstname,
|
Firstname: user.Firstname,
|
||||||
Lastname: user.Lastname,
|
Lastname: user.Lastname,
|
||||||
Administrator: user.Administrator,
|
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
Issuer: tm.issuer,
|
Issuer: tm.issuer,
|
||||||
Subject: user.ID,
|
Subject: user.ID,
|
||||||
@@ -97,7 +95,6 @@ func (tm *JwtTokenManager) ParseAndValidate(tokenString string) (*domain.User, e
|
|||||||
Email: claims.Email,
|
Email: claims.Email,
|
||||||
Firstname: claims.Firstname,
|
Firstname: claims.Firstname,
|
||||||
Lastname: claims.Lastname,
|
Lastname: claims.Lastname,
|
||||||
Administrator: claims.Administrator,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +119,6 @@ func (tm *JwtTokenManager) TokenMiddleware(next echo.HandlerFunc) echo.HandlerFu
|
|||||||
c.Set(auth.ContextUserIDKey, claims.ID)
|
c.Set(auth.ContextUserIDKey, claims.ID)
|
||||||
c.Set(auth.ContextEmailKey, claims.Email)
|
c.Set(auth.ContextEmailKey, claims.Email)
|
||||||
c.Set(auth.ContextNameKey, claims.Firstname+" "+claims.Lastname)
|
c.Set(auth.ContextNameKey, claims.Firstname+" "+claims.Lastname)
|
||||||
c.Set(auth.ContextAdminKey, claims.Administrator)
|
|
||||||
|
|
||||||
return next(c)
|
return next(c)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
import "database/sql"
|
import "time"
|
||||||
|
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
ChatModelID sql.NullString `db:"chat_model_id"`
|
ID string `db:"id" json:"id"`
|
||||||
DefaultLang string `db:"default_lang"`
|
DefaultLang string `db:"default_lang"`
|
||||||
RegisterEnabled bool `db:"register_enabled"`
|
RegisterEnabled bool `db:"register_enabled"`
|
||||||
PasswordEnabled bool `db:"password_enabled"`
|
PasswordEnabled bool `db:"password_enabled"`
|
||||||
VersionId string `db:"_version"`
|
DateCreated *time.Time `db:"_date_created" json:"_date_created"`
|
||||||
|
DateUpdated *time.Time `db:"_date_updated" json:"_date_updated"`
|
||||||
|
VersionId string `db:"_version" json:"_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SettingsRepository interface {
|
type SettingsRepository interface {
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID string `db:"id" json:"id"`
|
ID string `db:"id" json:"id"`
|
||||||
Firstname string `db:"firstname" json:"firstname,omitempty"`
|
Firstname string `db:"firstname" json:"firstname,omitempty"`
|
||||||
@@ -8,16 +12,76 @@ type User struct {
|
|||||||
Email string `db:"email" json:"email,omitempty"`
|
Email string `db:"email" json:"email,omitempty"`
|
||||||
PictureID string `db:"picture" json:"picture,omitempty"`
|
PictureID string `db:"picture" json:"picture,omitempty"`
|
||||||
Enabled bool `db:"enabled" json:"enabled"`
|
Enabled bool `db:"enabled" json:"enabled"`
|
||||||
|
Theme string `db:"theme" json:"theme"`
|
||||||
|
Lang string `db:"lang" json:"lang"`
|
||||||
|
DateCreated time.Time `db:"_date_created" json:"_date_created"`
|
||||||
|
DateUpdated time.Time `db:"_date_updated" json:"_date_updated"`
|
||||||
|
VersionId string `db:"_version" json:"_version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Team struct {
|
||||||
|
ID string `db:"id" json:"id"`
|
||||||
|
Label string `db:"label" json:"label"`
|
||||||
|
DefaultModelID *string `db:"default_model_id" json:"default_model_id"`
|
||||||
|
DateCreated *time.Time `db:"_date_created" json:"_date_created"`
|
||||||
|
DateUpdated *time.Time `db:"_date_updated" json:"_date_updated"`
|
||||||
|
VersionId string `db:"_version" json:"_version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserTeam struct {
|
||||||
|
ID string `db:"id" json:"id"`
|
||||||
|
UserID string `db:"user_id" json:"user_id"`
|
||||||
|
TeamID string `db:"team_id" json:"team_id"`
|
||||||
Administrator bool `db:"administrator" json:"administrator"`
|
Administrator bool `db:"administrator" json:"administrator"`
|
||||||
VersionId string `db:"_version" json:"-"`
|
DateCreated *time.Time `db:"_date_created" json:"_date_created"`
|
||||||
|
DateUpdated *time.Time `db:"_date_updated" json:"_date_updated"`
|
||||||
|
VersionId string `db:"_version" json:"_version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserAddress struct {
|
||||||
|
ID string `db:"id" json:"id"`
|
||||||
|
UserID string `db:"user_id" json:"user_id"`
|
||||||
|
Type string `db:"type" json:"type"`
|
||||||
|
Address string `db:"address_id" json:"address"`
|
||||||
|
DateCreated *time.Time `db:"_date_created" json:"_date_created"`
|
||||||
|
DateUpdated *time.Time `db:"_date_updated" json:"_date_updated"`
|
||||||
|
VersionId string `db:"_version" json:"_version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TeamRelation struct {
|
||||||
|
IsAdministrator bool `json:"administrator"`
|
||||||
|
Team *Team `json:"team"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserWithTeams struct {
|
||||||
|
User *User `json:"user"`
|
||||||
|
Teams []*TeamRelation `json:"teams"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserRepository interface {
|
type UserRepository interface {
|
||||||
CountUsers() (int, error)
|
|
||||||
FindUser(id string) (*User, error)
|
FindUser(id string) (*User, error)
|
||||||
FindUserByEmail(email string) (*User, error)
|
FindUserByEmail(email string) (*User, error)
|
||||||
ListUsers() ([]*User, error)
|
ListUsers() ([]*User, error)
|
||||||
CreateUser(user *User) (*User, error)
|
CreateUser(user *User) (*User, error)
|
||||||
UpdateUser(user *User) (*User, error)
|
UpdateUser(user *User) (*User, error)
|
||||||
DeleteUser(id string) error
|
DeleteUser(id string) error
|
||||||
|
|
||||||
|
FindTeam(userid string, teamid string) (*Team, error)
|
||||||
|
ListTeams(userid string) ([]*Team, error)
|
||||||
|
CreateTeam(userid string, team *Team) (*Team, error)
|
||||||
|
UpdateTeam(userid string, team *Team) (*Team, error)
|
||||||
|
DeleteTeam(userid string, teamid string) error
|
||||||
|
|
||||||
|
FindUserTeam(userid string, teamid string) (*UserTeam, error)
|
||||||
|
ListUserTeams(userid string) ([]*UserTeam, error)
|
||||||
|
CreateUserTeam(userid string, team *UserTeam) (*UserTeam, error)
|
||||||
|
UpdateUserTeam(userid string, team *UserTeam) (*UserTeam, error)
|
||||||
|
DeleteUserTeam(userid string, teamid string) error
|
||||||
|
|
||||||
|
PopulateUserWithTeams(user *User) (*UserWithTeams, error)
|
||||||
|
|
||||||
|
ListUserAddresses(userid string) ([]*UserAddress, error)
|
||||||
|
CreateUserAddress(userid string, addr *UserAddress) (*UserAddress, error)
|
||||||
|
UpdateUserAddress(userid string, addr *UserAddress) (*UserAddress, error)
|
||||||
|
DeleteUserAddress(userid string, addrID string) error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/labstack/echo/v5"
|
"github.com/labstack/echo/v5"
|
||||||
|
"trankilou.fr/lassistanoque/backend/internal/domain"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/service/auth"
|
"trankilou.fr/lassistanoque/backend/internal/service/auth"
|
||||||
"trankilou.fr/lassistanoque/backend/internal/service/user"
|
"trankilou.fr/lassistanoque/backend/internal/service/user"
|
||||||
)
|
)
|
||||||
@@ -15,7 +16,7 @@ func NewUserGroup(prefix string, e *echo.Group, service *user.Service, middlewar
|
|||||||
_ = userHandler
|
_ = userHandler
|
||||||
auth := e.Group(prefix, middlewares...)
|
auth := e.Group(prefix, middlewares...)
|
||||||
auth.GET("/me", userHandler.Me)
|
auth.GET("/me", userHandler.Me)
|
||||||
// auth.GET("/register", userHandler.Register)
|
auth.PUT("/:id", userHandler.Update)
|
||||||
return auth
|
return auth
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +28,30 @@ func (h UserHandler) Me(c *echo.Context) error {
|
|||||||
userID := c.Get(auth.ContextUserIDKey).(string)
|
userID := c.Get(auth.ContextUserIDKey).(string)
|
||||||
user, err := h.userService.GetUser(userID)
|
user, err := h.userService.GetUser(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusForbidden, err.Error())
|
return echo.NewHTTPError(http.StatusUnauthorized, err.Error())
|
||||||
}
|
}
|
||||||
return c.JSON(http.StatusOK, user)
|
return c.JSON(http.StatusOK, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h UserHandler) Update(c *echo.Context) error {
|
||||||
|
userID := c.Get(auth.ContextUserIDKey).(string)
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
var updUser domain.User
|
||||||
|
if err := c.Bind(&updUser); err != nil {
|
||||||
|
return c.String(http.StatusBadRequest, "bad request")
|
||||||
|
}
|
||||||
|
updUser.ID = id
|
||||||
|
|
||||||
|
isAdmin := false // TODO : check if caller is admin
|
||||||
|
if !(isAdmin || userID == id) {
|
||||||
|
return echo.NewHTTPError(http.StatusForbidden, "unauthorized to update user")
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := h.userService.UpdateUser(&updUser, isAdmin)
|
||||||
|
if err != nil {
|
||||||
|
return c.String(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, user)
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ type Session struct {
|
|||||||
const ContextUserIDKey = "userID"
|
const ContextUserIDKey = "userID"
|
||||||
const ContextEmailKey = "userEmail"
|
const ContextEmailKey = "userEmail"
|
||||||
const ContextNameKey = "userName"
|
const ContextNameKey = "userName"
|
||||||
const ContextAdminKey = "admin"
|
|
||||||
|
|
||||||
// Interface définie ici car c'est un port propre au cas d'usage "auth"
|
// Interface définie ici car c'est un port propre au cas d'usage "auth"
|
||||||
type Authenticator interface {
|
type Authenticator interface {
|
||||||
|
|||||||
@@ -26,3 +26,22 @@ func (s *Service) GetUser(id string) (*domain.User, error) {
|
|||||||
}
|
}
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) UpdateUser(updUser *domain.User, fromAdmin bool) (*domain.User, error) {
|
||||||
|
user, err := s.repo.FindUser(updUser.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fromAdmin {
|
||||||
|
user.Enabled = updUser.Enabled
|
||||||
|
}
|
||||||
|
user.Email = updUser.Email
|
||||||
|
user.Firstname = updUser.Firstname
|
||||||
|
user.Lastname = updUser.Lastname
|
||||||
|
user.Theme = updUser.Theme
|
||||||
|
user.Lang = updUser.Lang
|
||||||
|
|
||||||
|
return s.repo.UpdateUser(user)
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,47 @@
|
|||||||
|
# Canaux de commuinication
|
||||||
|
|
||||||
|
Ce sont les cananus de communication de l'agent pour l'équipe.
|
||||||
|
|
||||||
|
## Paramètre :
|
||||||
|
- Canal de communication avec l'équipe / public (ça ne peut pas être les deux)
|
||||||
|
|
||||||
|
## Réception
|
||||||
|
Je recois un message sur ce canal
|
||||||
|
- C'est le
|
||||||
|
|
||||||
|
## Emission :
|
||||||
|
La tâche de l'équipe peut utiliser ce canal.
|
||||||
|
Si le canal disparait, la tâche échoue.
|
||||||
|
|
||||||
|
# Equipe
|
||||||
|
|
||||||
|
Modèle -> par équipe ou partagé
|
||||||
|
Outils -> par équipe ou partagé
|
||||||
|
Canaux de communication -> par équipe ou partagé
|
||||||
|
Skill -> par équipe ou partagé
|
||||||
|
Base de connaissance -> par équipe ou partagé
|
||||||
|
Agent -> par équipe ou partagé
|
||||||
|
Mémoire -> par équipe ou partagé
|
||||||
|
Canaux -> par équipe ou partagé
|
||||||
|
|
||||||
|
|
||||||
|
# ORM
|
||||||
|
|
||||||
|
Gestion des transactions ou non
|
||||||
|
|
||||||
|
sur table :
|
||||||
|
- Insert
|
||||||
|
- Update sur ID ou sur filtre. avec vérification de version et mise à jour de la date_update
|
||||||
|
- Delete
|
||||||
|
- Select 1 sur ID ou sur filtre
|
||||||
|
- Select sur filtres (clause where)
|
||||||
|
|
||||||
|
Cas de
|
||||||
|
|
||||||
|
user, err := TUser.Get(id)
|
||||||
|
user, err := TUser.Select("email=$1", email)
|
||||||
|
users, err := TUser.SelectAll("admin=$1", true)
|
||||||
|
err := TUser.Delete(id)
|
||||||
|
err := TUser.DeleteAll("admin=$1", true)
|
||||||
|
user2, err := TUser.Insert(user2)
|
||||||
|
user2, err := TUser.Update(user2)
|
||||||
@@ -3,9 +3,9 @@ module trankilou.fr/lassistanoque
|
|||||||
go 1.26.5
|
go 1.26.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
gitea.trankilou.fr/fabien/lasebuche v0.0.0-20260808210632-98bd52d7c29e
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||||
github.com/golang-migrate/migrate/v4 v4.19.1
|
github.com/golang-migrate/migrate/v4 v4.19.1
|
||||||
github.com/jmoiron/sqlx v1.4.0
|
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/labstack/echo/v5 v5.3.1
|
github.com/labstack/echo/v5 v5.3.1
|
||||||
github.com/mattn/go-sqlite3 v1.14.42
|
github.com/mattn/go-sqlite3 v1.14.42
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
gitea.trankilou.fr/fabien/lasebuche v0.0.0-20260808210109-480734046bca h1:83fRxFj6Fb/yLIyz6b3JFNINWfalX7Ia+D3WPct/oIw=
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
gitea.trankilou.fr/fabien/lasebuche v0.0.0-20260808210109-480734046bca/go.mod h1:/Vk2CqBfE7O8jGSQ8H0tB7CI0paO0DAveK2WIgi1FIg=
|
||||||
|
gitea.trankilou.fr/fabien/lasebuche v0.0.0-20260808210632-98bd52d7c29e h1:M73kAt45VlJCVwbyFXrBn9oTZRPcoImlUMm0Qj96Y2U=
|
||||||
|
gitea.trankilou.fr/fabien/lasebuche v0.0.0-20260808210632-98bd52d7c29e/go.mod h1:/Vk2CqBfE7O8jGSQ8H0tB7CI0paO0DAveK2WIgi1FIg=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
|
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
|
||||||
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
|
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||||
github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA=
|
github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA=
|
||||||
@@ -15,19 +17,22 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
|
||||||
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/labstack/echo/v5 v5.3.1 h1:75maCxkQVGualckLc/5s/ihgpH1a1Dc6AuGWNVNs6bw=
|
github.com/labstack/echo/v5 v5.3.1 h1:75maCxkQVGualckLc/5s/ihgpH1a1Dc6AuGWNVNs6bw=
|
||||||
github.com/labstack/echo/v5 v5.3.1/go.mod h1:4iEGNQiPPZnkfYpNR/L6fINd3NLiGWUD5+eBotFALas=
|
github.com/labstack/echo/v5 v5.3.1/go.mod h1:4iEGNQiPPZnkfYpNR/L6fINd3NLiGWUD5+eBotFALas=
|
||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
|
||||||
|
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
||||||
github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo=
|
github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo=
|
||||||
github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
|
github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
|
||||||
|
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
||||||
|
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sixafter/aes-ctr-drbg v1.19.2 h1:+Bd1tS9/y/GapqgyyRjmrce6a5wUAQPusJXlAOh44yM=
|
github.com/sixafter/aes-ctr-drbg v1.19.2 h1:+Bd1tS9/y/GapqgyyRjmrce6a5wUAQPusJXlAOh44yM=
|
||||||
github.com/sixafter/aes-ctr-drbg v1.19.2/go.mod h1:iOBiPPkiy5Z5cEWm2yCoqEtnkfafxNTokJLL0zOPZeQ=
|
github.com/sixafter/aes-ctr-drbg v1.19.2/go.mod h1:iOBiPPkiy5Z5cEWm2yCoqEtnkfafxNTokJLL0zOPZeQ=
|
||||||
@@ -59,5 +64,13 @@ golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
|||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
modernc.org/libc v1.74.4 h1:fX1Omw4o2/1C2iRkkIsrQTasJQldLhRmuPreXLoWs9k=
|
||||||
|
modernc.org/libc v1.74.4/go.mod h1:eeQAS9W3sZeKYMFubydxJpII9ybHWshk+7or7bLG9co=
|
||||||
|
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||||
|
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||||
|
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||||
|
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||||
|
modernc.org/sqlite v1.56.0 h1:/D8e2RfFqoy/Zc6PuC76U28zFwmI/sYx1Kjm4yEn9e0=
|
||||||
|
modernc.org/sqlite v1.56.0/go.mod h1:yCJ2cmAaIkHQ25oXWrF8H4O1lIfPYPR26yCEDj2P3pQ=
|
||||||
turso.tech/database/tursogo v0.7.2 h1:WhsLl67w/Kw7ACEsJaTlXIb1parIgRqUcB8AbNZsBqU=
|
turso.tech/database/tursogo v0.7.2 h1:WhsLl67w/Kw7ACEsJaTlXIb1parIgRqUcB8AbNZsBqU=
|
||||||
turso.tech/database/tursogo v0.7.2/go.mod h1:tmC+H2Ot+guA9bs5oOcbbmpj1mHFTa/g7QREXG5QHq0=
|
turso.tech/database/tursogo v0.7.2/go.mod h1:tmC+H2Ot+guA9bs5oOcbbmpj1mHFTa/g7QREXG5QHq0=
|
||||||
|
|||||||
Reference in New Issue
Block a user