635 lines
28 KiB
Go
635 lines
28 KiB
Go
package client
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
// User is the public user representation returned by the API.
|
|
type User struct {
|
|
ID int `json:"id"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Name string `json:"name"`
|
|
Email string `json:"email"`
|
|
Color string `json:"color"`
|
|
Activated bool `json:"activated"`
|
|
Role string `json:"role"`
|
|
Permissions []string `json:"permissions"`
|
|
}
|
|
|
|
// AdminUserInviteInput contains the identity fields for an administrator-created
|
|
// account invitation.
|
|
type AdminUserInviteInput struct {
|
|
Name string `json:"name"`
|
|
Email string `json:"email"`
|
|
}
|
|
|
|
// IsAdmin reports whether the user can manage application roles.
|
|
func (user User) IsAdmin() bool { return user.Can("roles:manage") }
|
|
|
|
// Can reports whether the API-resolved application permissions contain permission.
|
|
func (user User) Can(permission string) bool {
|
|
for _, granted := range user.Permissions {
|
|
if granted == permission || granted == "*" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// AccountSession describes one server-side login session for the current user.
|
|
type AccountSession struct {
|
|
ID string `json:"id"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
Current bool `json:"current"`
|
|
}
|
|
|
|
// Garden is the public garden representation returned by the API.
|
|
type Garden struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
ImageData string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
Role string `json:"role"`
|
|
Permissions []string `json:"permissions"`
|
|
}
|
|
|
|
// Can reports whether the authenticated member has a concrete permission in
|
|
// this garden. The API resolves role defaults and garden-specific overrides.
|
|
func (garden Garden) Can(permission string) bool {
|
|
for _, granted := range garden.Permissions {
|
|
if granted == permission || granted == "*" || granted == "garden:*" && permission != "garden:delete" {
|
|
return true
|
|
}
|
|
}
|
|
if garden.Permissions != nil {
|
|
return false
|
|
}
|
|
// Compatibility for older API responses. Custom roles deliberately have no
|
|
// fallback: their effective permissions must always come from the API.
|
|
switch garden.Role {
|
|
case "owner":
|
|
return validLegacyGardenPermission(permission)
|
|
case "admin":
|
|
return validLegacyGardenPermission(permission) && permission != "garden:delete"
|
|
case "member":
|
|
switch permission {
|
|
case "garden:read", "content:write",
|
|
"plants:create", "plants:read:own", "plants:read:other", "plants:update:own", "plants:delete:own",
|
|
"locations:create", "locations:read:own", "locations:read:other", "locations:update:own", "locations:delete:own",
|
|
"tasks:create", "tasks:read:own", "tasks:read:other", "tasks:update:own", "tasks:delete:own", "tasks:complete:own", "tasks:complete:other":
|
|
return true
|
|
}
|
|
case "viewer":
|
|
return permission == "garden:read" || permission == "plants:read:own" || permission == "plants:read:other" ||
|
|
permission == "locations:read:own" || permission == "locations:read:other" || permission == "tasks:read:own" || permission == "tasks:read:other"
|
|
case "worker":
|
|
return permission == "garden:read" || permission == "tasks:read:own" || permission == "tasks:read:other" ||
|
|
permission == "tasks:complete:own" || permission == "tasks:complete:other"
|
|
}
|
|
return false
|
|
}
|
|
|
|
func validLegacyGardenPermission(permission string) bool {
|
|
switch permission {
|
|
case "garden:read", "garden:update", "garden:delete", "content:write", "members:write", "species:write",
|
|
"plants:create", "plants:read:own", "plants:read:other", "plants:update:own", "plants:update:other", "plants:delete:own", "plants:delete:other",
|
|
"locations:create", "locations:read:own", "locations:read:other", "locations:update:own", "locations:update:other", "locations:delete:own", "locations:delete:other",
|
|
"tasks:create", "tasks:read:own", "tasks:read:other", "tasks:update:own", "tasks:update:other", "tasks:delete:own", "tasks:delete:other", "tasks:complete:own", "tasks:complete:other":
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// GardenMember describes a user's role within one garden.
|
|
type GardenMember struct {
|
|
GardenID int `json:"garden_id"`
|
|
UserID int `json:"user_id"`
|
|
Role string `json:"role"`
|
|
JoinedAt time.Time `json:"joined_at"`
|
|
Name string `json:"name"`
|
|
Email string `json:"email"`
|
|
}
|
|
|
|
// GardenInvite describes a pending invitation to a garden.
|
|
type GardenInvite struct {
|
|
ID int `json:"id"`
|
|
GardenID int `json:"garden_id"`
|
|
Email string `json:"email"`
|
|
Role string `json:"role"`
|
|
InvitedBy int `json:"invited_by"`
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// GardenInviteInput contains the recipient and role for a garden invitation.
|
|
type GardenInviteInput struct {
|
|
Email string `json:"email"`
|
|
Role string `json:"role"`
|
|
}
|
|
|
|
// Role is an application or garden role with its base permissions.
|
|
type Role struct {
|
|
Name string `json:"name"`
|
|
Scope string `json:"scope"`
|
|
GardenID *int `json:"garden_id,omitempty"`
|
|
Label string `json:"label"`
|
|
System bool `json:"system"`
|
|
Permissions []string `json:"permissions"`
|
|
}
|
|
|
|
// RoleInput contains writable role fields.
|
|
type RoleInput struct {
|
|
Name string `json:"name,omitempty"`
|
|
Scope string `json:"scope,omitempty"`
|
|
Label string `json:"label"`
|
|
Permissions []string `json:"permissions"`
|
|
}
|
|
|
|
// GardenRoleSetting combines a role template with its effective permissions in
|
|
// one garden.
|
|
type GardenRoleSetting struct {
|
|
Role Role `json:"role"`
|
|
EffectivePermissions []string `json:"effective_permissions"`
|
|
}
|
|
|
|
// CreateGardenInput contains writable fields for a new garden.
|
|
type CreateGardenInput struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
ImageData string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
}
|
|
|
|
// UpdateGardenInput contains optional garden fields for a partial update.
|
|
type UpdateGardenInput struct {
|
|
Name *string `json:"name,omitempty"`
|
|
Description *string `json:"description,omitempty"`
|
|
ImageData *string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
}
|
|
|
|
// Species describes global or garden-specific plant master data.
|
|
type Species struct {
|
|
ID int `json:"id"`
|
|
GardenID *int `json:"garden_id,omitempty"`
|
|
CommonName string `json:"common_name"`
|
|
Cultivar string `json:"cultivar"`
|
|
BotanicalName string `json:"botanical_name"`
|
|
CategoryID *int `json:"category_id,omitempty"`
|
|
Category string `json:"category"`
|
|
SunExposure *string `json:"sun_exposure,omitempty"`
|
|
SoilCondition *string `json:"soil_condition,omitempty"`
|
|
SoilReaction *string `json:"soil_reaction,omitempty"`
|
|
WinterProtection *string `json:"winter_protection,omitempty"`
|
|
SpacingCM *int `json:"spacing_cm,omitempty"`
|
|
HeightCM *int `json:"height_cm,omitempty"`
|
|
SowMonthFrom *int `json:"sow_month_from,omitempty"`
|
|
SowDayFrom *int `json:"sow_day_from,omitempty"`
|
|
SowMonthTo *int `json:"sow_month_to,omitempty"`
|
|
SowDayTo *int `json:"sow_day_to,omitempty"`
|
|
PlantingMonthFrom *int `json:"planting_month_from,omitempty"`
|
|
PlantingDayFrom *int `json:"planting_day_from,omitempty"`
|
|
PlantingMonthTo *int `json:"planting_month_to,omitempty"`
|
|
PlantingDayTo *int `json:"planting_day_to,omitempty"`
|
|
HarvestMonthFrom *int `json:"harvest_month_from,omitempty"`
|
|
HarvestDayFrom *int `json:"harvest_day_from,omitempty"`
|
|
HarvestMonthTo *int `json:"harvest_month_to,omitempty"`
|
|
HarvestDayTo *int `json:"harvest_day_to,omitempty"`
|
|
Notes string `json:"notes"`
|
|
ImageData string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
Attributes json.RawMessage `json:"attributes"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
CreatedBy int `json:"created_by"`
|
|
UpdatedBy int `json:"updated_by"`
|
|
}
|
|
|
|
// SpeciesInput contains optional species fields used for creation and updates.
|
|
type SpeciesInput struct {
|
|
Global bool `json:"global,omitempty"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
CommonName *string `json:"common_name,omitempty"`
|
|
Cultivar *string `json:"cultivar,omitempty"`
|
|
BotanicalName *string `json:"botanical_name,omitempty"`
|
|
CategoryID *int `json:"category_id,omitempty"`
|
|
ClearCategoryID bool `json:"clear_category_id,omitempty"`
|
|
SunExposure *string `json:"sun_exposure,omitempty"`
|
|
SoilCondition *string `json:"soil_condition,omitempty"`
|
|
SoilReaction *string `json:"soil_reaction,omitempty"`
|
|
WinterProtection *string `json:"winter_protection,omitempty"`
|
|
SpacingCM *int `json:"spacing_cm,omitempty"`
|
|
HeightCM *int `json:"height_cm,omitempty"`
|
|
SowMonthFrom *int `json:"sow_month_from,omitempty"`
|
|
SowDayFrom *int `json:"sow_day_from,omitempty"`
|
|
ClearSowDayFrom bool `json:"clear_sow_day_from,omitempty"`
|
|
SowMonthTo *int `json:"sow_month_to,omitempty"`
|
|
SowDayTo *int `json:"sow_day_to,omitempty"`
|
|
ClearSowDayTo bool `json:"clear_sow_day_to,omitempty"`
|
|
PlantingMonthFrom *int `json:"planting_month_from,omitempty"`
|
|
PlantingDayFrom *int `json:"planting_day_from,omitempty"`
|
|
ClearPlantingDayFrom bool `json:"clear_planting_day_from,omitempty"`
|
|
PlantingMonthTo *int `json:"planting_month_to,omitempty"`
|
|
PlantingDayTo *int `json:"planting_day_to,omitempty"`
|
|
ClearPlantingDayTo bool `json:"clear_planting_day_to,omitempty"`
|
|
HarvestMonthFrom *int `json:"harvest_month_from,omitempty"`
|
|
HarvestDayFrom *int `json:"harvest_day_from,omitempty"`
|
|
ClearHarvestDayFrom bool `json:"clear_harvest_day_from,omitempty"`
|
|
HarvestMonthTo *int `json:"harvest_month_to,omitempty"`
|
|
HarvestDayTo *int `json:"harvest_day_to,omitempty"`
|
|
ClearHarvestDayTo bool `json:"clear_harvest_day_to,omitempty"`
|
|
ClearSowRange bool `json:"clear_sow_range,omitempty"`
|
|
ClearPlantingRange bool `json:"clear_planting_range,omitempty"`
|
|
ClearHarvestRange bool `json:"clear_harvest_range,omitempty"`
|
|
Notes *string `json:"notes,omitempty"`
|
|
ImageData *string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
Attributes json.RawMessage `json:"attributes,omitempty"`
|
|
}
|
|
|
|
// SpeciesCategory classifies species and optionally supplies a lifecycle.
|
|
type SpeciesCategory struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
SortOrder int `json:"sort_order"`
|
|
Active bool `json:"active"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
Lifecycle *string `json:"lifecycle,omitempty"`
|
|
}
|
|
|
|
// SpeciesCategoryInput contains writable category fields.
|
|
type SpeciesCategoryInput struct {
|
|
Name *string `json:"name,omitempty"`
|
|
SortOrder *int `json:"sort_order,omitempty"`
|
|
Active *bool `json:"active,omitempty"`
|
|
Lifecycle *string `json:"lifecycle,omitempty"`
|
|
}
|
|
|
|
// TaskPriority maps a display name to the numeric priority stored on tasks.
|
|
type TaskPriority struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
Value int `json:"value"`
|
|
SortOrder int `json:"sort_order"`
|
|
Active bool `json:"active"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
}
|
|
|
|
// TaskPriorityInput contains writable priority-catalogue fields.
|
|
type TaskPriorityInput struct {
|
|
Name *string `json:"name,omitempty"`
|
|
Value *int `json:"value,omitempty"`
|
|
SortOrder *int `json:"sort_order,omitempty"`
|
|
Active *bool `json:"active,omitempty"`
|
|
}
|
|
|
|
// Plant represents a plant instance owned by a garden.
|
|
type Plant struct {
|
|
ID int `json:"id"`
|
|
GardenID int `json:"garden_id"`
|
|
SpeciesID *int `json:"species_id,omitempty"`
|
|
Name string `json:"name"`
|
|
Notes string `json:"notes"`
|
|
ImageData string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
AcquiredAt *time.Time `json:"acquired_at,omitempty"`
|
|
Status string `json:"status"`
|
|
RemovedAt *time.Time `json:"removed_at,omitempty"`
|
|
Attributes json.RawMessage `json:"attributes"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
CreatedBy int `json:"created_by"`
|
|
UpdatedBy int `json:"updated_by"`
|
|
PlantedBy int `json:"planted_by"`
|
|
PlantedByName string `json:"planted_by_name,omitempty"`
|
|
}
|
|
|
|
// PlantInput contains optional plant fields used for creation and updates.
|
|
type PlantInput struct {
|
|
Tags []string `json:"tags,omitempty"`
|
|
SpeciesID *int `json:"species_id,omitempty"`
|
|
ClearSpeciesID bool `json:"clear_species_id,omitempty"`
|
|
Name *string `json:"name,omitempty"`
|
|
Notes *string `json:"notes,omitempty"`
|
|
ImageData *string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
AcquiredAt *time.Time `json:"acquired_at,omitempty"`
|
|
ClearAcquiredAt bool `json:"clear_acquired_at,omitempty"`
|
|
Status *string `json:"status,omitempty"`
|
|
RemovedAt *time.Time `json:"removed_at,omitempty"`
|
|
Attributes json.RawMessage `json:"attributes,omitempty"`
|
|
}
|
|
|
|
// Location describes a hierarchical place within a garden.
|
|
type Location struct {
|
|
ID int `json:"id"`
|
|
GardenID int `json:"garden_id"`
|
|
ParentID *int `json:"parent_id,omitempty"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
ImageData string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
Kind string `json:"kind"`
|
|
AreaSQM *float64 `json:"area_sqm,omitempty"`
|
|
SunExposure *string `json:"sun_exposure,omitempty"`
|
|
SoilCondition *string `json:"soil_condition,omitempty"`
|
|
SoilReaction *string `json:"soil_reaction,omitempty"`
|
|
Attributes json.RawMessage `json:"attributes"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
CreatedBy int `json:"created_by"`
|
|
UpdatedBy int `json:"updated_by"`
|
|
}
|
|
|
|
// LocationInput contains optional location fields used for creation and updates.
|
|
type LocationInput struct {
|
|
ParentID *int `json:"parent_id,omitempty"`
|
|
ClearParentID bool `json:"clear_parent_id,omitempty"`
|
|
Name *string `json:"name,omitempty"`
|
|
Description *string `json:"description,omitempty"`
|
|
ImageData *string `json:"image_data,omitempty"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
Kind *string `json:"kind,omitempty"`
|
|
AreaSQM *float64 `json:"area_sqm,omitempty"`
|
|
SunExposure *string `json:"sun_exposure,omitempty"`
|
|
SoilCondition *string `json:"soil_condition,omitempty"`
|
|
SoilReaction *string `json:"soil_reaction,omitempty"`
|
|
Attributes json.RawMessage `json:"attributes,omitempty"`
|
|
}
|
|
|
|
// PlantLocation represents a plant's assignment to a location.
|
|
type PlantLocation struct {
|
|
ID int `json:"id"`
|
|
PlantID int `json:"plant_id"`
|
|
LocationID int `json:"location_id"`
|
|
Quantity int `json:"quantity"`
|
|
PlantedAt *time.Time `json:"planted_at,omitempty"`
|
|
RemovedAt *time.Time `json:"removed_at,omitempty"`
|
|
Notes string `json:"notes"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
Version int `json:"version"`
|
|
}
|
|
|
|
// PlantLocationInput contains optional assignment fields used for creation and updates.
|
|
type PlantLocationInput struct {
|
|
LocationID *int `json:"location_id,omitempty"`
|
|
Quantity *int `json:"quantity,omitempty"`
|
|
PlantedAt *time.Time `json:"planted_at,omitempty"`
|
|
ClearPlantedAt bool `json:"clear_planted_at,omitempty"`
|
|
RemovedAt *time.Time `json:"removed_at,omitempty"`
|
|
Notes *string `json:"notes,omitempty"`
|
|
}
|
|
|
|
// Task represents a manual or generated garden work item.
|
|
type Task struct {
|
|
ID int `json:"id"`
|
|
GardenID int `json:"garden_id"`
|
|
PlantID *int `json:"plant_id,omitempty"`
|
|
LocationID *int `json:"location_id,omitempty"`
|
|
TemplateID *int `json:"template_id,omitempty"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
DueAtStart *time.Time `json:"due_at_start,omitempty"`
|
|
DueAtEnd *time.Time `json:"due_at_end,omitempty"`
|
|
GeneratedFor *time.Time `json:"generated_for,omitempty"`
|
|
Recurrence string `json:"recurrence,omitempty"`
|
|
RecurrenceInterval int `json:"recurrence_interval"`
|
|
RepeatFromID *int `json:"repeat_from_id,omitempty"`
|
|
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
|
CompletedBy *int `json:"completed_by,omitempty"`
|
|
Priority int `json:"priority"`
|
|
Active *bool `json:"active,omitempty"`
|
|
CreatedBy int `json:"created_by"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
PlantStatusOnCompletion *string `json:"plant_status_on_completion,omitempty"`
|
|
}
|
|
|
|
// TaskInput contains writable fields for task creation and partial updates.
|
|
type TaskInput struct {
|
|
Tags []string `json:"tags,omitempty"`
|
|
PlantID *int `json:"plant_id,omitempty"`
|
|
LocationID *int `json:"location_id,omitempty"`
|
|
ClearPlantID bool `json:"clear_plant_id,omitempty"`
|
|
ClearLocationID bool `json:"clear_location_id,omitempty"`
|
|
Title *string `json:"title,omitempty"`
|
|
Description *string `json:"description,omitempty"`
|
|
DueAtStart *time.Time `json:"due_at_start,omitempty"`
|
|
DueAtEnd *time.Time `json:"due_at_end,omitempty"`
|
|
ClearDueAtStart bool `json:"clear_due_at_start,omitempty"`
|
|
ClearDueAtEnd bool `json:"clear_due_at_end,omitempty"`
|
|
Recurrence *string `json:"recurrence,omitempty"`
|
|
RecurrenceInterval *int `json:"recurrence_interval,omitempty"`
|
|
Priority *int `json:"priority,omitempty"`
|
|
Active *bool `json:"active,omitempty"`
|
|
Completed *bool `json:"completed,omitempty"`
|
|
PlantStatusOnCompletion *string `json:"plant_status_on_completion,omitempty"`
|
|
}
|
|
|
|
// CareInstruction is garden-specific cultivation guidance for a species.
|
|
type CareInstruction struct {
|
|
ID int `json:"id"`
|
|
SpeciesID int `json:"species_id"`
|
|
Text string `json:"text"`
|
|
Status string `json:"status"`
|
|
CreatedBy int `json:"created_by"`
|
|
UpdatedBy int `json:"updated_by"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
}
|
|
|
|
// CareInstructionInput contains writable care-instruction fields.
|
|
type CareInstructionInput struct {
|
|
Text *string `json:"text,omitempty"`
|
|
Status *string `json:"status,omitempty"`
|
|
}
|
|
|
|
// JournalEntry is a garden journal or pinboard entry with related media.
|
|
type JournalEntry struct {
|
|
ID int `json:"id"`
|
|
GardenID int `json:"garden_id"`
|
|
AuthorID int `json:"author_id"`
|
|
AuthorName string `json:"author_name"`
|
|
AuthorColor string `json:"author_color"`
|
|
EntryType string `json:"entry_type"`
|
|
Title string `json:"title"`
|
|
Body string `json:"body"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
Attachments []JournalAttachment `json:"attachments,omitempty"`
|
|
}
|
|
|
|
// JournalEntryInput contains writable journal-entry fields.
|
|
type JournalEntryInput struct {
|
|
Title *string `json:"title,omitempty"`
|
|
Body *string `json:"body,omitempty"`
|
|
CreatedAt *time.Time `json:"created_at,omitempty"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
EntryType *string `json:"entry_type,omitempty"`
|
|
}
|
|
|
|
// JournalAttachment describes attachment metadata without its binary body.
|
|
type JournalAttachment struct {
|
|
ID int `json:"id"`
|
|
EntryID int `json:"entry_id"`
|
|
FileName string `json:"file_name"`
|
|
MediaType string `json:"media_type"`
|
|
Size int64 `json:"size"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
ImageID *int `json:"image_id,omitempty"`
|
|
}
|
|
|
|
// JournalAttachmentData combines attachment metadata with its binary body.
|
|
type JournalAttachmentData struct {
|
|
JournalAttachment
|
|
Data []byte
|
|
}
|
|
|
|
// SpeciesTaskTemplate describes a rule for generating tasks from species data.
|
|
type SpeciesTaskTemplate struct {
|
|
ID int `json:"id"`
|
|
SpeciesID int `json:"species_id"`
|
|
Origin string `json:"origin"`
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
TriggerType string `json:"trigger_type"`
|
|
MonthFrom *int `json:"month_from,omitempty"`
|
|
DayFrom *int `json:"day_from,omitempty"`
|
|
MonthTo *int `json:"month_to,omitempty"`
|
|
DayTo *int `json:"day_to,omitempty"`
|
|
OffsetDaysFrom *int `json:"offset_days_from,omitempty"`
|
|
OffsetDaysTo *int `json:"offset_days_to,omitempty"`
|
|
IntervalDays *int `json:"interval_days,omitempty"`
|
|
TriggerOffset int `json:"trigger_offset"`
|
|
TriggerOffsetUnit string `json:"trigger_offset_unit"`
|
|
Duration int `json:"duration"`
|
|
DurationUnit string `json:"duration_unit"`
|
|
Recurrence string `json:"recurrence,omitempty"`
|
|
RecurrenceInterval int `json:"recurrence_interval"`
|
|
Priority int `json:"priority"`
|
|
Active bool `json:"active"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
}
|
|
|
|
// ApplicationSettings contains application-wide lifecycle automation settings.
|
|
type ApplicationSettings struct {
|
|
LifecycleStatusEnabled bool `json:"lifecycle_status_enabled"`
|
|
LifecycleRemovalMonth int `json:"lifecycle_removal_month"`
|
|
LifecycleRemovalDay int `json:"lifecycle_removal_day"`
|
|
Timezone string `json:"timezone"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Version int `json:"version"`
|
|
}
|
|
|
|
// ApplicationSettingsInput contains writable lifecycle automation settings.
|
|
type ApplicationSettingsInput struct {
|
|
LifecycleStatusEnabled *bool `json:"lifecycle_status_enabled,omitempty"`
|
|
LifecycleRemovalMonth *int `json:"lifecycle_removal_month,omitempty"`
|
|
LifecycleRemovalDay *int `json:"lifecycle_removal_day,omitempty"`
|
|
Timezone *string `json:"timezone,omitempty"`
|
|
}
|
|
|
|
// EnvironmentVariable describes one effective process configuration value.
|
|
// Sensitive values are masked by the API before they leave the process.
|
|
type EnvironmentVariable struct {
|
|
Component string `json:"component"`
|
|
Name string `json:"name"`
|
|
Value string `json:"value"`
|
|
}
|
|
|
|
// SpeciesTaskTemplateInput contains writable task-template fields.
|
|
type SpeciesTaskTemplateInput struct {
|
|
Title *string `json:"title,omitempty"`
|
|
Description *string `json:"description,omitempty"`
|
|
TriggerType *string `json:"trigger_type,omitempty"`
|
|
MonthFrom *int `json:"month_from,omitempty"`
|
|
DayFrom *int `json:"day_from,omitempty"`
|
|
ClearDayFrom bool `json:"clear_day_from,omitempty"`
|
|
MonthTo *int `json:"month_to,omitempty"`
|
|
DayTo *int `json:"day_to,omitempty"`
|
|
ClearDayTo bool `json:"clear_day_to,omitempty"`
|
|
OffsetDaysFrom *int `json:"offset_days_from,omitempty"`
|
|
OffsetDaysTo *int `json:"offset_days_to,omitempty"`
|
|
IntervalDays *int `json:"interval_days,omitempty"`
|
|
ClearIntervalDays bool `json:"clear_interval_days,omitempty"`
|
|
TriggerOffset *int `json:"trigger_offset,omitempty"`
|
|
TriggerOffsetUnit *string `json:"trigger_offset_unit,omitempty"`
|
|
Duration *int `json:"duration,omitempty"`
|
|
DurationUnit *string `json:"duration_unit,omitempty"`
|
|
Recurrence *string `json:"recurrence,omitempty"`
|
|
RecurrenceInterval *int `json:"recurrence_interval,omitempty"`
|
|
Priority *int `json:"priority,omitempty"`
|
|
Active *bool `json:"active,omitempty"`
|
|
}
|
|
|
|
// Credentials contains email and password authentication input.
|
|
type Credentials struct {
|
|
Email string `json:"email"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
// RegisterUserInput contains the fields required to register an account.
|
|
type RegisterUserInput struct {
|
|
Name string `json:"name"`
|
|
Email string `json:"email"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
// TokenInput wraps a plaintext activation or reset token.
|
|
type TokenInput struct {
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
// EmailInput wraps an email address for token requests.
|
|
type EmailInput struct {
|
|
Email string `json:"email"`
|
|
}
|
|
|
|
// UpdatePasswordInput contains a new password and its reset token.
|
|
type UpdatePasswordInput struct {
|
|
Password string `json:"password"`
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
// AuthenticationToken is a bearer token and its expiration time.
|
|
type AuthenticationToken struct {
|
|
Token string `json:"token"`
|
|
Expiry time.Time `json:"expiry"`
|
|
}
|
|
|
|
// Health describes API availability and build information.
|
|
type Health struct {
|
|
Status string `json:"status"`
|
|
ServerTime time.Time `json:"server_time"`
|
|
SystemInfo SystemInfo `json:"system_info"`
|
|
}
|
|
|
|
// SystemInfo identifies the running API environment and version.
|
|
type SystemInfo struct {
|
|
Environment string `json:"environment"`
|
|
Version string `json:"version"`
|
|
}
|