mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
108 lines
3.8 KiB
Go
108 lines
3.8 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package convert
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
|
|
activities_model "github.com/hanzoai/git/models/activities"
|
|
access_model "github.com/hanzoai/git/models/perm/access"
|
|
"github.com/hanzoai/git/modules/log"
|
|
api "github.com/hanzoai/git/modules/structs"
|
|
)
|
|
|
|
// ToNotificationThread convert a Notification to api.NotificationThread
|
|
func ToNotificationThread(ctx context.Context, n *activities_model.Notification) *api.NotificationThread {
|
|
result := &api.NotificationThread{
|
|
ID: n.ID,
|
|
Unread: !(n.Status == activities_model.NotificationStatusRead || n.Status == activities_model.NotificationStatusPinned),
|
|
Pinned: n.Status == activities_model.NotificationStatusPinned,
|
|
UpdatedAt: n.UpdatedUnix.AsTime(),
|
|
URL: n.APIURL(),
|
|
}
|
|
|
|
// since user only get notifications when he has access to use minimal access mode
|
|
if n.Repository == nil {
|
|
return result
|
|
}
|
|
perm, err := access_model.GetIndividualUserRepoPermission(ctx, n.Repository, n.User)
|
|
if err != nil {
|
|
log.Error("GetIndividualUserRepoPermission failed: %v", err)
|
|
return result
|
|
}
|
|
// if the user has been revoked access to the repo, do not leak repo or subject info
|
|
if !perm.HasAnyUnitAccessOrPublicAccess() {
|
|
return result
|
|
}
|
|
result.Repository = ToRepo(ctx, n.Repository, perm)
|
|
// This permission is not correct and we should not be reporting it
|
|
for repository := result.Repository; repository != nil; repository = repository.Parent {
|
|
repository.Permissions = nil
|
|
}
|
|
|
|
// handle Subject
|
|
switch n.Source {
|
|
case activities_model.NotificationSourceIssue:
|
|
result.Subject = &api.NotificationSubject{Type: api.NotifySubjectIssue}
|
|
if n.Issue != nil {
|
|
result.Subject.Title = n.Issue.Title
|
|
result.Subject.URL = n.Issue.APIURL(ctx)
|
|
result.Subject.HTMLURL = n.Issue.HTMLURL(ctx)
|
|
result.Subject.State = api.NotifySubjectStateType(n.Issue.State())
|
|
comment, err := n.Issue.GetLastComment(ctx)
|
|
if err == nil && comment != nil {
|
|
result.Subject.LatestCommentURL = comment.APIURL(ctx)
|
|
result.Subject.LatestCommentHTMLURL = comment.HTMLURL(ctx)
|
|
}
|
|
}
|
|
case activities_model.NotificationSourcePullRequest:
|
|
result.Subject = &api.NotificationSubject{Type: api.NotifySubjectPull}
|
|
if n.Issue != nil {
|
|
result.Subject.Title = n.Issue.Title
|
|
result.Subject.URL = n.Issue.APIURL(ctx)
|
|
result.Subject.HTMLURL = n.Issue.HTMLURL(ctx)
|
|
result.Subject.State = api.NotifySubjectStateType(n.Issue.State())
|
|
comment, err := n.Issue.GetLastComment(ctx)
|
|
if err == nil && comment != nil {
|
|
result.Subject.LatestCommentURL = comment.APIURL(ctx)
|
|
result.Subject.LatestCommentHTMLURL = comment.HTMLURL(ctx)
|
|
}
|
|
|
|
if err := n.Issue.LoadPullRequest(ctx); err == nil &&
|
|
n.Issue.PullRequest != nil &&
|
|
n.Issue.PullRequest.HasMerged {
|
|
result.Subject.State = api.NotifySubjectStateMerged
|
|
}
|
|
}
|
|
case activities_model.NotificationSourceCommit:
|
|
url := n.Repository.HTMLURL() + "/commit/" + url.PathEscape(n.CommitID)
|
|
result.Subject = &api.NotificationSubject{
|
|
Type: api.NotifySubjectCommit,
|
|
Title: n.CommitID,
|
|
URL: url,
|
|
HTMLURL: url,
|
|
}
|
|
case activities_model.NotificationSourceRepository:
|
|
result.Subject = &api.NotificationSubject{
|
|
Type: api.NotifySubjectRepository,
|
|
Title: n.Repository.FullName(),
|
|
// FIXME: this is a relative URL, rather useless and inconsistent, but keeping for backwards compat
|
|
URL: n.Repository.Link(),
|
|
HTMLURL: n.Repository.HTMLURL(),
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// ToNotifications convert list of Notification to api.NotificationThread list
|
|
func ToNotifications(ctx context.Context, nl activities_model.NotificationList) []*api.NotificationThread {
|
|
result := make([]*api.NotificationThread, 0, len(nl))
|
|
for _, n := range nl {
|
|
result = append(result, ToNotificationThread(ctx, n))
|
|
}
|
|
return result
|
|
}
|