gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

notification.go (4774B)


      1 // GoToSocial
      2 // Copyright (C) GoToSocial Authors admin@gotosocial.org
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 //
      5 // This program is free software: you can redistribute it and/or modify
      6 // it under the terms of the GNU Affero General Public License as published by
      7 // the Free Software Foundation, either version 3 of the License, or
      8 // (at your option) any later version.
      9 //
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU Affero General Public License for more details.
     14 //
     15 // You should have received a copy of the GNU Affero General Public License
     16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 package timeline
     19 
     20 import (
     21 	"context"
     22 	"errors"
     23 	"fmt"
     24 
     25 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     26 	"github.com/superseriousbusiness/gotosocial/internal/db"
     27 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     28 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     29 	"github.com/superseriousbusiness/gotosocial/internal/log"
     30 	"github.com/superseriousbusiness/gotosocial/internal/oauth"
     31 	"github.com/superseriousbusiness/gotosocial/internal/util"
     32 )
     33 
     34 func (p *Processor) NotificationsGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, excludeTypes []string) (*apimodel.PageableResponse, gtserror.WithCode) {
     35 	notifs, err := p.state.DB.GetAccountNotifications(ctx, authed.Account.ID, maxID, sinceID, minID, limit, excludeTypes)
     36 	if err != nil && !errors.Is(err, db.ErrNoEntries) {
     37 		err = fmt.Errorf("NotificationsGet: db error getting notifications: %w", err)
     38 		return nil, gtserror.NewErrorInternalError(err)
     39 	}
     40 
     41 	count := len(notifs)
     42 	if count == 0 {
     43 		return util.EmptyPageableResponse(), nil
     44 	}
     45 
     46 	var (
     47 		items          = make([]interface{}, 0, count)
     48 		nextMaxIDValue string
     49 		prevMinIDValue string
     50 	)
     51 
     52 	for i, n := range notifs {
     53 		// Set next + prev values before filtering and API
     54 		// converting, so caller can still page properly.
     55 		if i == count-1 {
     56 			nextMaxIDValue = n.ID
     57 		}
     58 
     59 		if i == 0 {
     60 			prevMinIDValue = n.ID
     61 		}
     62 
     63 		// Ensure this notification should be shown to requester.
     64 		if n.OriginAccount != nil {
     65 			// Account is set, ensure it's visible to notif target.
     66 			visible, err := p.filter.AccountVisible(ctx, authed.Account, n.OriginAccount)
     67 			if err != nil {
     68 				log.Debugf(ctx, "skipping notification %s because of an error checking notification visibility: %s", n.ID, err)
     69 				continue
     70 			}
     71 
     72 			if !visible {
     73 				continue
     74 			}
     75 		}
     76 
     77 		if n.Status != nil {
     78 			// Status is set, ensure it's visible to notif target.
     79 			visible, err := p.filter.StatusVisible(ctx, authed.Account, n.Status)
     80 			if err != nil {
     81 				log.Debugf(ctx, "skipping notification %s because of an error checking notification visibility: %s", n.ID, err)
     82 				continue
     83 			}
     84 
     85 			if !visible {
     86 				continue
     87 			}
     88 		}
     89 
     90 		item, err := p.tc.NotificationToAPINotification(ctx, n)
     91 		if err != nil {
     92 			log.Debugf(ctx, "skipping notification %s because it couldn't be converted to its api representation: %s", n.ID, err)
     93 			continue
     94 		}
     95 
     96 		items = append(items, item)
     97 	}
     98 
     99 	return util.PackagePageableResponse(util.PageableResponseParams{
    100 		Items:          items,
    101 		Path:           "api/v1/notifications",
    102 		NextMaxIDValue: nextMaxIDValue,
    103 		PrevMinIDValue: prevMinIDValue,
    104 		Limit:          limit,
    105 	})
    106 }
    107 
    108 func (p *Processor) NotificationGet(ctx context.Context, account *gtsmodel.Account, targetNotifID string) (*apimodel.Notification, gtserror.WithCode) {
    109 	notif, err := p.state.DB.GetNotificationByID(ctx, targetNotifID)
    110 	if err != nil {
    111 		if errors.Is(err, db.ErrNoEntries) {
    112 			return nil, gtserror.NewErrorNotFound(err)
    113 		}
    114 
    115 		// Real error.
    116 		return nil, gtserror.NewErrorInternalError(err)
    117 	}
    118 
    119 	if notifTargetAccountID := notif.TargetAccountID; notifTargetAccountID != account.ID {
    120 		err = fmt.Errorf("account %s does not have permission to view notification belong to account %s", account.ID, notifTargetAccountID)
    121 		return nil, gtserror.NewErrorNotFound(err)
    122 	}
    123 
    124 	apiNotif, err := p.tc.NotificationToAPINotification(ctx, notif)
    125 	if err != nil {
    126 		if errors.Is(err, db.ErrNoEntries) {
    127 			return nil, gtserror.NewErrorNotFound(err)
    128 		}
    129 
    130 		// Real error.
    131 		return nil, gtserror.NewErrorInternalError(err)
    132 	}
    133 
    134 	return apiNotif, nil
    135 }
    136 
    137 func (p *Processor) NotificationsClear(ctx context.Context, authed *oauth.Auth) gtserror.WithCode {
    138 	// Delete all notifications of all types that target the authorized account.
    139 	if err := p.state.DB.DeleteNotifications(ctx, nil, authed.Account.ID, ""); err != nil && !errors.Is(err, db.ErrNoEntries) {
    140 		return gtserror.NewErrorInternalError(err)
    141 	}
    142 
    143 	return nil
    144 }