mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 03:18:24 +00:00 
			
		
		
		
	Refactor legacy code (#35708)
And by the way, remove the legacy TODO, split large functions into small ones, and add more tests
This commit is contained in:
		| @@ -17,29 +17,13 @@ import ( | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
|  | ||||
| 	"golang.org/x/crypto/ssh" | ||||
| ) | ||||
|  | ||||
| //  _____          __  .__                 .__                  .___ | ||||
| // /  _  \  __ ___/  |_|  |__   ___________|__|_______ ____   __| _/ | ||||
| // /  /_\  \|  |  \   __\  |  \ /  _ \_  __ \  \___   // __ \ / __ | | ||||
| // /    |    \  |  /|  | |   Y  (  <_> )  | \/  |/    /\  ___// /_/ | | ||||
| // \____|__  /____/ |__| |___|  /\____/|__|  |__/_____ \\___  >____ | | ||||
| //         \/                 \/                      \/    \/     \/ | ||||
| // ____  __. | ||||
| // |    |/ _|____ ___.__. ______ | ||||
| // |      <_/ __ <   |  |/  ___/ | ||||
| // |    |  \  ___/\___  |\___ \ | ||||
| // |____|__ \___  > ____/____  > | ||||
| //         \/   \/\/         \/ | ||||
| // | ||||
| // This file contains functions for creating authorized_keys files | ||||
| // | ||||
| // There is a dependence on the database within RegeneratePublicKeys however most of these functions probably belong in a module | ||||
|  | ||||
| const ( | ||||
| 	tplCommentPrefix = `# gitea public key` | ||||
| 	tplPublicKey     = tplCommentPrefix + "\n" + `command=%s,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict %s` + "\n" | ||||
| ) | ||||
| // AuthorizedStringCommentPrefix is a magic tag | ||||
| // some functions like RegeneratePublicKeys needs this tag to skip the keys generated by Gitea, while keep other keys | ||||
| const AuthorizedStringCommentPrefix = `# gitea public key` | ||||
|  | ||||
| var sshOpLocker sync.Mutex | ||||
|  | ||||
| @@ -50,17 +34,45 @@ func WithSSHOpLocker(f func() error) error { | ||||
| } | ||||
|  | ||||
| // AuthorizedStringForKey creates the authorized keys string appropriate for the provided key | ||||
| func AuthorizedStringForKey(key *PublicKey) string { | ||||
| func AuthorizedStringForKey(key *PublicKey) (string, error) { | ||||
| 	sb := &strings.Builder{} | ||||
| 	_ = setting.SSH.AuthorizedKeysCommandTemplateTemplate.Execute(sb, map[string]any{ | ||||
| 	_, err := writeAuthorizedStringForKey(key, sb) | ||||
| 	return sb.String(), err | ||||
| } | ||||
|  | ||||
| // WriteAuthorizedStringForValidKey writes the authorized key for the provided key. If the key is invalid, it does nothing. | ||||
| func WriteAuthorizedStringForValidKey(key *PublicKey, w io.Writer) error { | ||||
| 	validKey, err := writeAuthorizedStringForKey(key, w) | ||||
| 	if !validKey { | ||||
| 		log.Debug("WriteAuthorizedStringForValidKey: key %s is not valid: %v", key, err) | ||||
| 		return nil | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func writeAuthorizedStringForKey(key *PublicKey, w io.Writer) (keyValid bool, err error) { | ||||
| 	const tpl = AuthorizedStringCommentPrefix + "\n" + `command=%s,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict %s %s` + "\n" | ||||
| 	pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(key.Content)) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| 	// now the key is valid, the code below could only return template/IO related errors | ||||
| 	sbCmd := &strings.Builder{} | ||||
| 	err = setting.SSH.AuthorizedKeysCommandTemplateTemplate.Execute(sbCmd, map[string]any{ | ||||
| 		"AppPath":     util.ShellEscape(setting.AppPath), | ||||
| 		"AppWorkPath": util.ShellEscape(setting.AppWorkPath), | ||||
| 		"CustomConf":  util.ShellEscape(setting.CustomConf), | ||||
| 		"CustomPath":  util.ShellEscape(setting.CustomPath), | ||||
| 		"Key":         key, | ||||
| 	}) | ||||
|  | ||||
| 	return fmt.Sprintf(tplPublicKey, util.ShellEscape(sb.String()), key.Content) | ||||
| 	if err != nil { | ||||
| 		return true, err | ||||
| 	} | ||||
| 	sshCommandEscaped := util.ShellEscape(sbCmd.String()) | ||||
| 	sshKeyMarshalled := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(pubKey))) | ||||
| 	sshKeyComment := fmt.Sprintf("user-%d", key.OwnerID) | ||||
| 	_, err = fmt.Fprintf(w, tpl, sshCommandEscaped, sshKeyMarshalled, sshKeyComment) | ||||
| 	return true, err | ||||
| } | ||||
|  | ||||
| // appendAuthorizedKeysToFile appends new SSH keys' content to authorized_keys file. | ||||
| @@ -112,7 +124,7 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error { | ||||
| 		if key.Type == KeyTypePrincipal { | ||||
| 			continue | ||||
| 		} | ||||
| 		if _, err = f.WriteString(key.AuthorizedString()); err != nil { | ||||
| 		if err = WriteAuthorizedStringForValidKey(key, f); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| @@ -120,10 +132,9 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error { | ||||
| } | ||||
|  | ||||
| // RegeneratePublicKeys regenerates the authorized_keys file | ||||
| func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error { | ||||
| func RegeneratePublicKeys(ctx context.Context, t io.Writer) error { | ||||
| 	if err := db.GetEngine(ctx).Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) { | ||||
| 		_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString()) | ||||
| 		return err | ||||
| 		return WriteAuthorizedStringForValidKey(bean.(*PublicKey), t) | ||||
| 	}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -144,11 +155,11 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error { | ||||
| 		scanner := bufio.NewScanner(f) | ||||
| 		for scanner.Scan() { | ||||
| 			line := scanner.Text() | ||||
| 			if strings.HasPrefix(line, tplCommentPrefix) { | ||||
| 			if strings.HasPrefix(line, AuthorizedStringCommentPrefix) { | ||||
| 				scanner.Scan() | ||||
| 				continue | ||||
| 			} | ||||
| 			_, err = t.WriteString(line + "\n") | ||||
| 			_, err = io.WriteString(t, line+"\n") | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user