Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] main from go-gitea:main #89

Merged
merged 3 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ require (
github.com/ethantkoenig/rupture v1.0.1
github.com/felixge/fgprof v0.9.5
github.com/fsnotify/fsnotify v1.7.0
github.com/gliderlabs/ssh v0.3.7
github.com/gliderlabs/ssh v0.3.8
github.com/go-ap/activitypub v0.0.0-20240910141749-b4b8c8aa484c
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
github.com/go-chi/chi/v5 v5.1.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 h1:mtDjlmloH7ytdblogrMz1/8Hqua1y8B4ID+bh3rvod0=
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1/go.mod h1:fenKRzpXDjNpsIBhuhUzvjCKlDjKam0boRAenTE0Q6A=
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-ap/activitypub v0.0.0-20240910141749-b4b8c8aa484c h1:82lzmsy5Nr6JA6HcLRVxGfbdSoWfW45C6jnY3zFS7Ks=
Expand Down
40 changes: 20 additions & 20 deletions modules/markup/markdown/markdown_math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ func TestMathRender(t *testing.T) {
}{
{
"$a$",
`<p><code class="language-math is-loading">a</code></p>` + nl,
`<p><code class="language-math">a</code></p>` + nl,
},
{
"$ a $",
`<p><code class="language-math is-loading">a</code></p>` + nl,
`<p><code class="language-math">a</code></p>` + nl,
},
{
"$a$ $b$",
`<p><code class="language-math is-loading">a</code> <code class="language-math is-loading">b</code></p>` + nl,
`<p><code class="language-math">a</code> <code class="language-math">b</code></p>` + nl,
},
{
`\(a\) \(b\)`,
`<p><code class="language-math is-loading">a</code> <code class="language-math is-loading">b</code></p>` + nl,
`<p><code class="language-math">a</code> <code class="language-math">b</code></p>` + nl,
},
{
`$a$.`,
`<p><code class="language-math is-loading">a</code>.</p>` + nl,
`<p><code class="language-math">a</code>.</p>` + nl,
},
{
`.$a$`,
Expand Down Expand Up @@ -64,27 +64,27 @@ func TestMathRender(t *testing.T) {
},
{
"$a$ ($b$) [$c$] {$d$}",
`<p><code class="language-math is-loading">a</code> (<code class="language-math is-loading">b</code>) [$c$] {$d$}</p>` + nl,
`<p><code class="language-math">a</code> (<code class="language-math">b</code>) [$c$] {$d$}</p>` + nl,
},
{
"$$a$$",
`<code class="chroma language-math display">a</code>` + nl,
`<code class="language-math display">a</code>` + nl,
},
{
"$$a$$ test",
`<p><code class="language-math display is-loading">a</code> test</p>` + nl,
`<p><code class="language-math">a</code> test</p>` + nl,
},
{
"test $$a$$",
`<p>test <code class="language-math display is-loading">a</code></p>` + nl,
`<p>test <code class="language-math">a</code></p>` + nl,
},
{
`foo $x=\$$ bar`,
`<p>foo <code class="language-math is-loading">x=\$</code> bar</p>` + nl,
`<p>foo <code class="language-math">x=\$</code> bar</p>` + nl,
},
{
`$\text{$b$}$`,
`<p><code class="language-math is-loading">\text{$b$}</code></p>` + nl,
`<p><code class="language-math">\text{$b$}</code></p>` + nl,
},
}

Expand All @@ -110,7 +110,7 @@ func TestMathRenderBlockIndent(t *testing.T) {
\alpha
\]
`,
`<pre class="code-block is-loading"><code class="chroma language-math display">
`<pre class="code-block is-loading"><code class="language-math display">
\alpha
</code></pre>
`,
Expand All @@ -122,7 +122,7 @@ func TestMathRenderBlockIndent(t *testing.T) {
\alpha
\]
`,
`<pre class="code-block is-loading"><code class="chroma language-math display">
`<pre class="code-block is-loading"><code class="language-math display">
\alpha
</code></pre>
`,
Expand All @@ -137,7 +137,7 @@ a
d
\]
`,
`<pre class="code-block is-loading"><code class="chroma language-math display">
`<pre class="code-block is-loading"><code class="language-math display">
a
b
c
Expand All @@ -154,7 +154,7 @@ c
c
\]
`,
`<pre class="code-block is-loading"><code class="chroma language-math display">
`<pre class="code-block is-loading"><code class="language-math display">
a
b
c
Expand All @@ -165,15 +165,15 @@ c
"indent-0-oneline",
`$$ x $$
foo`,
`<code class="chroma language-math display"> x </code>
`<code class="language-math display"> x </code>
<p>foo</p>
`,
},
{
"indent-3-oneline",
` $$ x $$<SPACE>
foo`,
`<code class="chroma language-math display"> x </code>
`<code class="language-math display"> x </code>
<p>foo</p>
`,
},
Expand All @@ -188,10 +188,10 @@ foo`,
> \]
`,
`<blockquote>
<pre class="code-block is-loading"><code class="chroma language-math display">
<pre class="code-block is-loading"><code class="language-math display">
a
</code></pre>
<pre class="code-block is-loading"><code class="chroma language-math display">
<pre class="code-block is-loading"><code class="language-math display">
b
</code></pre>
</blockquote>
Expand All @@ -207,7 +207,7 @@ b
2. b`,
`<ol>
<li>a
<pre class="code-block is-loading"><code class="chroma language-math display">
<pre class="code-block is-loading"><code class="language-math display">
x
</code></pre>
</li>
Expand Down
13 changes: 12 additions & 1 deletion modules/markup/markdown/math/block_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ import (
"github.com/yuin/goldmark/util"
)

// Block render output:
// <pre class="code-block is-loading"><code class="language-math display">...</code></pre>
//
// Keep in mind that there is another "code block" render in "func (r *GlodmarkRender) highlightingRenderer"
// "highlightingRenderer" outputs the math block with extra "chroma" class:
// <pre class="code-block is-loading"><code class="chroma language-math display">...</code></pre>
//
// Special classes:
// * "is-loading": show a loading indicator
// * "display": used by JS to decide to render as a block, otherwise render as inline

// BlockRenderer represents a renderer for math Blocks
type BlockRenderer struct {
renderInternal *internal.RenderInternal
Expand All @@ -38,7 +49,7 @@ func (r *BlockRenderer) writeLines(w util.BufWriter, source []byte, n gast.Node)
func (r *BlockRenderer) renderBlock(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
n := node.(*Block)
if entering {
code := giteaUtil.Iif(n.Inline, "", `<pre class="code-block is-loading">`) + `<code class="chroma language-math display">`
code := giteaUtil.Iif(n.Inline, "", `<pre class="code-block is-loading">`) + `<code class="language-math display">`
_ = r.renderInternal.FormatWithSafeAttrs(w, code)
r.writeLines(w, source, n)
} else {
Expand Down
9 changes: 4 additions & 5 deletions modules/markup/markdown/math/inline_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import (
"github.com/yuin/goldmark/util"
)

// Inline render output:
// <code class="language-math">...</code>

// InlineRenderer is an inline renderer
type InlineRenderer struct {
renderInternal *internal.RenderInternal
Expand All @@ -25,11 +28,7 @@ func NewInlineRenderer(renderInternal *internal.RenderInternal) renderer.NodeRen

func (r *InlineRenderer) renderInline(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
if entering {
extraClass := ""
if _, ok := n.(*InlineBlock); ok {
extraClass = "display "
}
_ = r.renderInternal.FormatWithSafeAttrs(w, `<code class="language-math %sis-loading">`, extraClass)
_ = r.renderInternal.FormatWithSafeAttrs(w, `<code class="language-math">`)
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
segment := c.(*ast.Text).Segment
value := util.EscapeHTML(segment.Value(source))
Expand Down
70 changes: 62 additions & 8 deletions modules/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import (
"errors"
"fmt"
"io"
"maps"
"net"
"os"
"os/exec"
"path/filepath"
"reflect"
"strconv"
"strings"
"sync"
Expand All @@ -33,9 +35,22 @@ import (
gossh "golang.org/x/crypto/ssh"
)

type contextKey string

const giteaKeyID = contextKey("gitea-key-id")
// The ssh auth overall works like this:
// NewServerConn:
// serverHandshake+serverAuthenticate:
// PublicKeyCallback:
// PublicKeyHandler (our code):
// reset(ctx.Permissions) and set ctx.Permissions.giteaKeyID = keyID
// pubKey.Verify
// return ctx.Permissions // only reaches here, the pub key is really authenticated
// set conn.Permissions from serverAuthenticate
// sessionHandler(conn)
//
// Then sessionHandler should only use the "verified keyID" from the original ssh conn, but not the ctx one.
// Otherwise, if a user provides 2 keys A (a correct one) and B (public key matches but no private key),
// then only A succeeds to authenticate, sessionHandler will see B's keyID

const giteaPermissionExtensionKeyID = "gitea-perm-ext-key-id"

func getExitStatusFromError(err error) int {
if err == nil {
Expand All @@ -61,8 +76,32 @@ func getExitStatusFromError(err error) int {
return waitStatus.ExitStatus()
}

// sessionPartial is the private struct from "gliderlabs/ssh/session.go"
// We need to read the original "conn" field from "ssh.Session interface" which contains the "*session pointer"
// https://github.com/gliderlabs/ssh/blob/d137aad99cd6f2d9495bfd98c755bec4e5dffb8c/session.go#L109-L113
// If upstream fixes the problem and/or changes the struct, we need to follow.
// If the struct mismatches, the builtin ssh server will fail during integration tests.
type sessionPartial struct {
sync.Mutex
gossh.Channel
conn *gossh.ServerConn
}

func ptr[T any](intf any) *T {
// https://pkg.go.dev/unsafe#Pointer
// (1) Conversion of a *T1 to Pointer to *T2.
// Provided that T2 is no larger than T1 and that the two share an equivalent memory layout,
// this conversion allows reinterpreting data of one type as data of another type.
v := reflect.ValueOf(intf)
p := v.UnsafePointer()
return (*T)(p)
}

func sessionHandler(session ssh.Session) {
keyID := fmt.Sprintf("%d", session.Context().Value(giteaKeyID).(int64))
// here can't use session.Permissions() because it only uses the value from ctx, which might not be the authenticated one.
// so we must use the original ssh conn, which always contains the correct (verified) keyID.
sshConn := ptr[sessionPartial](session)
keyID := sshConn.conn.Permissions.Extensions[giteaPermissionExtensionKeyID]

command := session.RawCommand()

Expand Down Expand Up @@ -164,6 +203,23 @@ func sessionHandler(session ssh.Session) {
}

func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
// The publicKeyHandler (PublicKeyCallback) only helps to provide the candidate keys to authenticate,
// It does NOT really verify here, so we could only record the related information here.
// After authentication (Verify), the "Permissions" will be assigned to the ssh conn,
// then we can use it in the "session handler"

// first, reset the ctx permissions (just like https://github.com/gliderlabs/ssh/pull/243 does)
// it shouldn't be reused across different ssh conn (sessions), each pub key should have its own "Permissions"
oldCtxPerm := ctx.Permissions().Permissions
ctx.Permissions().Permissions = &gossh.Permissions{}
ctx.Permissions().Permissions.CriticalOptions = maps.Clone(oldCtxPerm.CriticalOptions)

setPermExt := func(keyID int64) {
ctx.Permissions().Permissions.Extensions = map[string]string{
giteaPermissionExtensionKeyID: fmt.Sprint(keyID),
}
}

if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
log.Debug("Handle Public Key: Fingerprint: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
}
Expand Down Expand Up @@ -238,8 +294,7 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
log.Debug("Successfully authenticated: %s Certificate Fingerprint: %s Principal: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key), principal)
}
ctx.SetValue(giteaKeyID, pkey.ID)

setPermExt(pkey.ID)
return true
}

Expand All @@ -266,8 +321,7 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
log.Debug("Successfully authenticated: %s Public Key Fingerprint: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
}
ctx.SetValue(giteaKeyID, pkey.ID)

setPermExt(pkey.ID)
return true
}

Expand Down
12 changes: 12 additions & 0 deletions services/feed/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,12 @@ func (a *actionNotifier) SyncPushCommits(ctx context.Context, pusher *user_model
}

func (a *actionNotifier) SyncCreateRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refFullName git.RefName, refID string) {
// ignore pull sync message for pull requests refs
// TODO: it's better to have a UI to let users chose
if refFullName.IsPull() {
return
}

if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{
ActUserID: repo.OwnerID,
ActUser: repo.MustOwner(ctx),
Expand All @@ -431,6 +437,12 @@ func (a *actionNotifier) SyncCreateRef(ctx context.Context, doer *user_model.Use
}

func (a *actionNotifier) SyncDeleteRef(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, refFullName git.RefName) {
// ignore pull sync message for pull requests refs
// TODO: it's better to have a UI to let users chose
if refFullName.IsPull() {
return
}

if err := activities_model.NotifyWatchers(ctx, &activities_model.Action{
ActUserID: repo.OwnerID,
ActUser: repo.MustOwner(ctx),
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/view_list.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{/* use grid layout, still use the old ID because there are many other CSS styles depending on this ID */}}
<div id="repo-files-table" {{if .HasFilesWithoutLatestCommit}}hx-indicator="#repo-files-table .repo-file-cell.message" hx-trigger="load" hx-swap="morph" hx-post="{{.LastCommitLoaderURL}}"{{end}}>
<div class="repo-file-line">
<div class="repo-file-line repo-file-last-commit">
<div class="latest-commit">{{template "repo/latest_commit" .}}</div>
<div>{{if and .LatestCommit .LatestCommit.Committer}}{{DateUtils.TimeSince .LatestCommit.Committer.When}}{{end}}</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions web_src/css/repo/clone.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/* only used by "repo/empty.tmpl" */
.clone-buttons-combo {
display: flex;
align-items: center;
flex: 1;
}

.clone-buttons-combo input {
border-left: none !important;
border-radius: 0 !important;
height: 30px;
}

/* used by the clone-panel popup */
Expand Down
5 changes: 5 additions & 0 deletions web_src/css/repo/home-file-list.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
padding: 6px 10px;
}

#repo-files-table .repo-file-last-commit {
background: var(--color-box-header);
}

#repo-files-table .repo-file-cell.name {
max-width: 300px;
white-space: nowrap;
Expand All @@ -59,6 +63,7 @@
}

#repo-files-table .repo-file-cell.age {
text-align: right;
white-space: nowrap;
color: var(--color-text-light-1);
}
Expand Down
Loading
Loading