Skip to content

Commit 815c93a

Browse files
committed
Detect non-Ascii characters in Sonatype credentials
1 parent 6d4db24 commit 815c93a

File tree

4 files changed

+50
-16
lines changed

4 files changed

+50
-16
lines changed

modules/cli/src/main/scala/scala/cli/commands/publish/Publish.scala

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,14 @@ import scala.cli.commands.shared.{
5656
import scala.cli.commands.util.{BuildCommandHelpers, ScalaCliSttpBackend}
5757
import scala.cli.commands.{ScalaCommand, SpecificationLevel, WatchUtil}
5858
import scala.cli.config.{ConfigDb, Keys, PasswordOption, PublishCredentials}
59-
import scala.cli.errors._
59+
import scala.cli.errors.{
60+
FailedToSignFileError,
61+
InvalidSonatypePublishCredentials,
62+
MalformedChecksumsError,
63+
MissingPublishOptionError,
64+
UploadError,
65+
WrongSonatypeServerError
66+
}
6067
import scala.cli.packaging.Library
6168
import scala.cli.publish.BouncycastleSignerMaker
6269
import scala.cli.util.ArgHelpers.*
@@ -70,12 +77,16 @@ object Publish extends ScalaCommand[PublishOptions] with BuildCommandHelpers {
7077
override def scalaSpecificationLevel: SpecificationLevel = SpecificationLevel.EXPERIMENTAL
7178

7279
import scala.cli.commands.shared.HelpGroup.*
80+
7381
val primaryHelpGroups: Seq[HelpGroup] = Seq(Publishing, Signing, PGP)
7482
val hiddenHelpGroups: Seq[HelpGroup] = Seq(Scala, Java, Entrypoint, Dependency, Watch)
83+
7584
override def helpFormat: HelpFormat = super.helpFormat
7685
.withHiddenGroups(hiddenHelpGroups)
7786
.withPrimaryGroups(primaryHelpGroups)
87+
7888
override def group: String = HelpCommandGroup.Main.toString
89+
7990
override def sharedOptions(options: PublishOptions): Option[SharedOptions] =
8091
Some(options.shared)
8192

@@ -364,18 +375,22 @@ object Publish extends ScalaCommand[PublishOptions] with BuildCommandHelpers {
364375
"publish.organization"
365376
))
366377
}
378+
367379
private def defaultName(workspace: os.Path, logger: Logger): String = {
368380
val name = workspace.last
369381
logger.message(
370382
s"Using directive publish.name not specified, using workspace directory name $name as default name"
371383
)
372384
name
373385
}
386+
374387
def defaultComputeVersion(mayDefaultToGitTag: Boolean): Option[ComputeVersion] =
375388
if (mayDefaultToGitTag) Some(ComputeVersion.GitTag(os.rel, dynVer = false, positions = Nil))
376389
else None
390+
377391
def defaultVersionError =
378392
new MissingPublishOptionError("version", "--project-version", "publish.version")
393+
379394
def defaultVersion: Either[BuildException, String] =
380395
Left(defaultVersionError)
381396

@@ -490,7 +505,8 @@ object Publish extends ScalaCommand[PublishOptions] with BuildCommandHelpers {
490505
case None =>
491506
val computeVer = publishOptions.contextual(isCi).computeVersion.orElse {
492507
def isGitRepo = GitRepo.gitRepoOpt(workspace).isDefined
493-
val default = defaultComputeVersion(!isCi && isGitRepo)
508+
509+
val default = defaultComputeVersion(!isCi && isGitRepo)
494510
if (default.isDefined)
495511
logger.message(
496512
s"Using directive ${defaultVersionError.directiveName} not set, assuming git:tag as publish.computeVersion"
@@ -1018,8 +1034,12 @@ object Publish extends ScalaCommand[PublishOptions] with BuildCommandHelpers {
10181034
if (repoParams.isIvy2LocalLike) fileSet2
10191035
else fileSet2.order(ec).unsafeRun()(ec)
10201036

1021-
val isSnapshot0 = modVersionOpt.exists(_._2.endsWith("SNAPSHOT"))
1022-
val authOpt0 = value(authOpt(repoParams.repo.repo(isSnapshot0).root, isSonatype))
1037+
val isSnapshot0 = modVersionOpt.exists(_._2.endsWith("SNAPSHOT"))
1038+
val authOpt0 = value(authOpt(repoParams.repo.repo(isSnapshot0).root, isSonatype))
1039+
val asciiRegex = """[\u0000-\u007f]*""".r
1040+
val usernameOnlyAscii = authOpt0.exists(auth => asciiRegex.matches(auth.user))
1041+
val passwordOnlyAscii = authOpt0.exists(_.passwordOpt.exists(pass => asciiRegex.matches(pass)))
1042+
10231043
if (repoParams.shouldAuthenticate && authOpt0.isEmpty)
10241044
logger.diagnostic(
10251045
"Publishing to a repository that needs authentication, but no credentials are available.",
@@ -1039,7 +1059,7 @@ object Publish extends ScalaCommand[PublishOptions] with BuildCommandHelpers {
10391059
if "Failed to get .*oss\\.sonatype\\.org.*/staging/profiles \\(http status: 401,".r.unanchored.matches(
10401060
e.getMessage
10411061
) =>
1042-
logger.exit(new InvalidPublishCredentials)
1062+
logger.exit(new InvalidSonatypePublishCredentials(usernameOnlyAscii, passwordOnlyAscii))
10431063
case NonFatal(e) =>
10441064
throw new Exception(e)
10451065
}
@@ -1112,7 +1132,6 @@ object Publish extends ScalaCommand[PublishOptions] with BuildCommandHelpers {
11121132
|Uploading files failed!
11131133
|Possible causes:
11141134
|- incorrect Sonatype credentials
1115-
|- your Sonatype password or username may contain unsupported characters
11161135
|- incorrect Sonatype server was used, try ${
11171136
if isLegacySonatype then "'central-s01'" else "'central'"
11181137
}

modules/cli/src/main/scala/scala/cli/errors/InvalidPublishCredentials.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package scala.cli.errors
2+
3+
import scala.build.errors.BuildException
4+
5+
final class InvalidSonatypePublishCredentials(usernameIsAscii: Boolean, passwordIsAscii: Boolean)
6+
extends BuildException(
7+
if (usernameIsAscii && passwordIsAscii)
8+
"Username or password to the publish repository are incorrect"
9+
else
10+
s"Your Sonatype ${InvalidSonatypePublishCredentials.isUsernameOrPassword(
11+
usernameIsAscii,
12+
passwordIsAscii
13+
)} unsupported characters"
14+
)
15+
16+
object InvalidSonatypePublishCredentials {
17+
def isUsernameOrPassword(usernameIsAscii: Boolean, passwordIsAscii: Boolean): String =
18+
if (!usernameIsAscii && !passwordIsAscii)
19+
"password and username contain"
20+
else if (!usernameIsAscii)
21+
"username contains"
22+
else
23+
"password contains"
24+
}

modules/core/src/main/scala/scala/build/internals/OsLibc.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,8 @@ object OsLibc {
7373
else s"temurin:$jvmVersion"
7474
}
7575

76-
def defaultJvm(os: String): String = {
76+
def defaultJvm(os: String): String =
7777
baseDefaultJvm(os, defaultJvmVersion)
78-
}
7978

8079
def javaVersion(javaCmd: String): Int = {
8180
val javaVersionOutput = os.proc(javaCmd, "-version").call(

0 commit comments

Comments
 (0)