You've already forked openaccounting-server
forked from cybercinch/openaccounting-server
- Add AttachmentInterface to main model interface - Implement attachment CRUD operations with permission checking - Add GetTransaction method for secure attachment access validation - Add accountsContainReadAccess for permission verification - Ensure users can only access attachments for authorized transactions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
163 lines
3.8 KiB
Go
163 lines
3.8 KiB
Go
package model
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/openaccounting/oa-server/core/model/types"
|
|
)
|
|
|
|
type AttachmentInterface interface {
|
|
CreateAttachment(*types.Attachment) (*types.Attachment, error)
|
|
GetAttachmentsByTransaction(string, string, string) ([]*types.Attachment, error)
|
|
GetAttachment(string, string, string, string) (*types.Attachment, error)
|
|
DeleteAttachment(string, string, string, string) error
|
|
}
|
|
|
|
func (model *Model) CreateAttachment(attachment *types.Attachment) (*types.Attachment, error) {
|
|
if attachment.Id == "" {
|
|
return nil, errors.New("attachment ID required")
|
|
}
|
|
|
|
if attachment.TransactionId == "" {
|
|
return nil, errors.New("transaction ID required")
|
|
}
|
|
|
|
if attachment.OrgId == "" {
|
|
return nil, errors.New("organization ID required")
|
|
}
|
|
|
|
if attachment.UserId == "" {
|
|
return nil, errors.New("user ID required")
|
|
}
|
|
|
|
if attachment.FileName == "" {
|
|
return nil, errors.New("file name required")
|
|
}
|
|
|
|
if attachment.FilePath == "" {
|
|
return nil, errors.New("file path required")
|
|
}
|
|
|
|
// Set upload timestamp
|
|
attachment.Uploaded = time.Now()
|
|
attachment.Deleted = false
|
|
|
|
// Save to database
|
|
err := model.db.InsertAttachment(attachment)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return attachment, nil
|
|
}
|
|
|
|
func (model *Model) GetAttachmentsByTransaction(transactionId, orgId, userId string) ([]*types.Attachment, error) {
|
|
if transactionId == "" {
|
|
return nil, errors.New("transaction ID required")
|
|
}
|
|
|
|
if orgId == "" {
|
|
return nil, errors.New("organization ID required")
|
|
}
|
|
|
|
if userId == "" {
|
|
return nil, errors.New("user ID required")
|
|
}
|
|
|
|
// First verify the user has access to the transaction
|
|
tx, err := model.GetTransaction(transactionId, orgId, userId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if tx == nil {
|
|
return nil, errors.New("transaction not found or access denied")
|
|
}
|
|
|
|
// Get attachments for the transaction
|
|
attachments, err := model.db.GetAttachmentsByTransaction(transactionId, orgId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return attachments, nil
|
|
}
|
|
|
|
func (model *Model) GetAttachment(attachmentId, transactionId, orgId, userId string) (*types.Attachment, error) {
|
|
if attachmentId == "" {
|
|
return nil, errors.New("attachment ID required")
|
|
}
|
|
|
|
if transactionId == "" {
|
|
return nil, errors.New("transaction ID required")
|
|
}
|
|
|
|
if orgId == "" {
|
|
return nil, errors.New("organization ID required")
|
|
}
|
|
|
|
if userId == "" {
|
|
return nil, errors.New("user ID required")
|
|
}
|
|
|
|
// First verify the user has access to the transaction
|
|
tx, err := model.GetTransaction(transactionId, orgId, userId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if tx == nil {
|
|
return nil, errors.New("transaction not found or access denied")
|
|
}
|
|
|
|
// Get the attachment
|
|
attachment, err := model.db.GetAttachment(attachmentId, transactionId, orgId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return attachment, nil
|
|
}
|
|
|
|
func (model *Model) DeleteAttachment(attachmentId, transactionId, orgId, userId string) error {
|
|
if attachmentId == "" {
|
|
return errors.New("attachment ID required")
|
|
}
|
|
|
|
if transactionId == "" {
|
|
return errors.New("transaction ID required")
|
|
}
|
|
|
|
if orgId == "" {
|
|
return errors.New("organization ID required")
|
|
}
|
|
|
|
if userId == "" {
|
|
return errors.New("user ID required")
|
|
}
|
|
|
|
// First verify the user has access to the transaction
|
|
tx, err := model.GetTransaction(transactionId, orgId, userId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if tx == nil {
|
|
return errors.New("transaction not found or access denied")
|
|
}
|
|
|
|
// Verify the attachment exists and belongs to the transaction
|
|
attachment, err := model.db.GetAttachment(attachmentId, transactionId, orgId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if attachment == nil {
|
|
return errors.New("attachment not found")
|
|
}
|
|
|
|
// Soft delete the attachment
|
|
err = model.db.DeleteAttachment(attachmentId, transactionId, orgId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
} |