mirror of
https://github.com/mattermost/mattermost.git
synced 2026-05-24 03:05:38 -04:00
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres with binary parameters (push) Blocked by required conditions
Server CI / Postgres (shard 0) (push) Blocked by required conditions
Server CI / Postgres (shard 1) (push) Blocked by required conditions
Server CI / Postgres (shard 2) (push) Blocked by required conditions
Server CI / Postgres (shard 3) (push) Blocked by required conditions
Server CI / Merge Postgres Test Results (push) Blocked by required conditions
Server CI / Postgres (FIPS) (push) Blocked by required conditions
Server CI / Generate Test Coverage (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Tools CI / check-style (mattermost-govet) (push) Waiting to run
Tools CI / Test (mattermost-govet) (push) Waiting to run
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Blocked by required conditions
Web App CI / check-external-links (push) Blocked by required conditions
Web App CI / check-types (push) Blocked by required conditions
Web App CI / test (platform) (push) Blocked by required conditions
Web App CI / test (mattermost-redux) (push) Blocked by required conditions
Web App CI / test (channels shard 1/4) (push) Blocked by required conditions
Web App CI / test (channels shard 2/4) (push) Blocked by required conditions
Web App CI / test (channels shard 3/4) (push) Blocked by required conditions
Web App CI / test (channels shard 4/4) (push) Blocked by required conditions
Web App CI / upload-coverage (push) Blocked by required conditions
Web App CI / build (push) Blocked by required conditions
* Use multi-level logging for shared channel and remote cluster service errors Service-specific log levels (LvlRemoteClusterServiceError, LvlSharedChannelServiceError) were hidden from the main log by default, requiring explicit configuration to see them. Switch all call sites to use LogM with multi-level combos so each log line is attributed to both the standard level (error/warn) and the service-specific level. This surfaces errors in the main log while preserving the ability to isolate them into dedicated files. Each instance was reviewed and either kept as error (DB failures, security issues, config errors, exhausted retries on critical data) or downgraded to warn (transient network failures, remote-side reported errors with retry logic, non-critical data like profile images, reactions, acknowledgements, and status).
88 lines
3.2 KiB
Go
88 lines
3.2 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package sharedchannel
|
|
|
|
import (
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/i18n"
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
"github.com/mattermost/mattermost/server/public/shared/request"
|
|
)
|
|
|
|
var (
|
|
// Team name regex taken from model.IsValidTeamName
|
|
permaLinkRegex = regexp.MustCompile(`https?://[0-9.\-A-Za-z]+/[a-z0-9]+([a-z\-0-9]+|(__)?)[a-z0-9]+/pl/([a-zA-Z0-9]+)`)
|
|
permaLinkSharedRegex = regexp.MustCompile(`https?://[0-9.\-A-Za-z]+/[a-z0-9]+([a-z\-0-9]+|(__)?)[a-z0-9]+/plshared/([a-zA-Z0-9]+)`)
|
|
)
|
|
|
|
const (
|
|
permalinkMarker = "plshared"
|
|
)
|
|
|
|
// processPermalinkToRemote processes all permalinks going towards a remote site.
|
|
func (scs *Service) processPermalinkToRemote(p *model.Post) string {
|
|
// request.CTX is not widely used in the shared channels code.
|
|
// Just create a new request.CTX for now.
|
|
rctx := request.EmptyContext(scs.server.Log())
|
|
|
|
var sent bool
|
|
return permaLinkRegex.ReplaceAllStringFunc(p.Message, func(msg string) string {
|
|
// Extract the postID (This is simple enough not to warrant full-blown URL parsing.)
|
|
lastSlash := strings.LastIndexByte(msg, '/')
|
|
postID := msg[lastSlash+1:]
|
|
opts := model.GetPostsOptions{
|
|
SkipFetchThreads: true,
|
|
}
|
|
postList, err := scs.server.GetStore().Post().Get(rctx, postID, opts, "", map[string]bool{})
|
|
if err != nil {
|
|
scs.server.Log().LogM(mlog.MlvlSharedChannelServiceWarn, "Unable to get post during replacing permalinks", mlog.Err(err))
|
|
return msg
|
|
}
|
|
if len(postList.Order) == 0 {
|
|
scs.server.Log().LogM(mlog.MlvlSharedChannelServiceWarn, "No post found for permalink", mlog.String("postID", postID))
|
|
return msg
|
|
}
|
|
|
|
// If postID is for a different channel
|
|
if postList.Posts[postList.Order[0]].ChannelId != p.ChannelId {
|
|
// Send ephemeral message to OP (only once per message).
|
|
if !sent {
|
|
scs.sendEphemeralPost(p.ChannelId, p.UserId, i18n.T("sharedchannel.permalink.not_found"))
|
|
sent = true
|
|
}
|
|
// But don't modify msg
|
|
return msg
|
|
}
|
|
|
|
// Otherwise, modify pl to plshared as a marker to be replaced by remote sites
|
|
return strings.Replace(msg, "/pl/", "/"+permalinkMarker+"/", 1)
|
|
})
|
|
}
|
|
|
|
// processPermalinkFromRemote processes all permalinks coming from a remote site.
|
|
func (scs *Service) processPermalinkFromRemote(p *model.Post, team *model.Team) string {
|
|
return permaLinkSharedRegex.ReplaceAllStringFunc(p.Message, func(remoteLink string) string {
|
|
// Extract host name
|
|
parsed, err := url.Parse(remoteLink)
|
|
if err != nil {
|
|
scs.server.Log().LogM(mlog.MlvlSharedChannelServiceWarn, "Unable to parse the remote link during replacing permalinks", mlog.Err(err))
|
|
return remoteLink
|
|
}
|
|
|
|
// Replace with local SiteURL
|
|
parsed.Scheme = scs.siteURL.Scheme
|
|
parsed.Host = scs.siteURL.Host
|
|
|
|
// Replace team name with local team
|
|
teamEnd := strings.Index(parsed.Path, "/"+permalinkMarker)
|
|
parsed.Path = "/" + team.Name + parsed.Path[teamEnd:]
|
|
|
|
// Replace plshared with pl
|
|
return strings.Replace(parsed.String(), "/"+permalinkMarker+"/", "/pl/", 1)
|
|
})
|
|
}
|