Skip to content

Commit

Permalink
feat: Add support for base64 and OAuth tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
jimisola committed May 25, 2023
1 parent e30ef3e commit 5bbea04
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 87 deletions.
5 changes: 5 additions & 0 deletions src/maven_artifact/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from maven_artifact.requestor import Requestor, RequestException # noqa: F401
from maven_artifact.artifact import Artifact # noqa: F401
from maven_artifact.resolver import Resolver # noqa: F401
from maven_artifact.downloader import Downloader # noqa: F401
from maven_artifact.utils import Utils # noqa: F401
18 changes: 18 additions & 0 deletions src/maven_artifact/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,21 @@ def __str__(self):
return "%s:%s:%s:%s" % (self.group_id, self.artifact_id, self.extension, self.version)
else:
return "%s:%s:%s" % (self.group_id, self.artifact_id, self.version)

@staticmethod
def parse(maven_coordinate):
parts = maven_coordinate.split(":")
if len(parts) >= 3:
g = parts[0]
a = parts[1]
v = parts[len(parts) - 1]
t = None
c = None
if len(parts) == 4:
t = parts[2]
if len(parts) == 5:
t = parts[2]
c = parts[3]
return Artifact(group_id=g, artifact_id=a, version=v, classifier=c, extension=t)
else:
return None
2 changes: 1 addition & 1 deletion src/maven_artifact/downloader.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import hashlib
import os

from maven_artifact.requestor import Requestor
from maven_artifact.requestor import RequestException, Requestor
from maven_artifact.resolver import Resolver


Expand Down
128 changes: 68 additions & 60 deletions src/maven_artifact/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
import os
import sys
import textwrap
from maven_artifact.artifact import Artifact

try:
from maven_artifact.utils import Utils
except ImportError:
sys.path.append(os.path.dirname(__file__))
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from maven_artifact.utils import Utils

from maven_artifact import __version__
from maven_artifact.requestor import RequestException
from maven_artifact.downloader import Downloader

Expand Down Expand Up @@ -55,75 +55,83 @@ def _split_lines(self, text, width):
return lines


class MainCommand:
def _get_arguments(self):
parser = argparse.ArgumentParser(formatter_class=WrappedNewlineFormatter, epilog=__epilog__)
parser.add_argument(
"maven_coordinate",
help="""
defined by http://maven.apache.org/pom.html#Maven_Coordinates. The possible options are:
- groupId:artifactId:version
- groupId:artifactId:packaging:version
- groupId:artifactId:packaging:classifier:version""",
)
parser.add_argument(
"filename",
nargs="?",
help="""
If not supplied the filename will be <artifactId>.<extension>.
The filename directory must exist prior to download.""",
)
parser.add_argument(
"-m",
"--maven-repo",
dest="base",
default="https://repo.maven.apache.org/maven2/",
help="Maven repository URL (default: https://repo.maven.apache.org/maven2/)",
)

parser.add_argument("-u", "--username", help="username (must be combined with --password)")
parser.add_argument(
"-p",
"--password",
help="""
password (must be combined with --username) or
base64 encoded username and password (can not not be combined with --username)""",
)
parser.add_argument(
"-t", "--token", help="OAuth bearer token (can not be combined with --username or --password)"
)

parser.add_argument("-ht", "--hash-type", default="md5", help="hash type (default: md5)")

args = parser.parse_args()

username = args.username
password = args.password
token = args.token

if username and not password:
parser.error("The 'username' parameter requires the 'password' parameter.")
elif (username or password) and token:
parser.error("The 'token' parameter cannot be used together with 'username' or 'password'.")
elif (password) and not (username or token) and not Utils.is_base64(password):
parser.error("The 'password' parameter must be base64 if not used together with 'username'.")

return args


__epilog__ = """
Example:
%(prog)s "org.apache.solr:solr:war:3.5.0"\n
"""


def main():
parser = argparse.ArgumentParser(formatter_class=WrappedNewlineFormatter, epilog=__epilog__)
parser.add_argument(
"maven_coordinate",
help="""
defined by http://maven.apache.org/pom.html#Maven_Coordinates. The possible options are:
- groupId:artifactId:version
- groupId:artifactId:packaging:version
- groupId:artifactId:packaging:classifier:version""",
)
parser.add_argument(
"filename",
nargs="?",
help="""
If not supplied the filename will be <artifactId>.<extension>.
The filename directory must exist prior to download.""",
)
parser.add_argument(
"-m",
"--maven-repo",
dest="base",
default="https://repo.maven.apache.org/maven2/",
help="Maven repository URL (default: https://repo.maven.apache.org/maven2/)",
)

parser.add_argument("-u", "--username", help="username (must be combined with --password)")
parser.add_argument(
"-p", "--password",
help="""
password (must be combined with --username) or
base64 encoded username and password (can not not be combined with --username)"""
)
parser.add_argument("-t", "--token", help="OAuth bearer token (can not be combined with --username or --password)")

parser.add_argument("-ht", "--hash-type", default="md5", help="hash type (default: md5)")

args = parser.parse_args()

base = args.base
username = args.username
password = args.password
token = args.token
hash_type = args.hash_type

if username and not password:
parser.error("The 'username' parameter requires the 'password' parameter.")
elif (username or password) and token:
parser.error("The 'token' parameter cannot be used together with 'username' or 'password'.")
elif (password) and not (username or token) and not Utils.is_base64(password):
parser.error("The 'password' parameter must be base64 if not used together with 'username'.")

dl = Downloader(base=base, username=username, password=password, token=token)

artifact = Utils.parse(args.maven_coordinate)

filename = args.filename
mc = MainCommand()
args = mc._get_arguments()

try:
if dl.download(artifact, filename, hash_type):
dl = Downloader(base=args.base, username=args.username, password=args.password, token=args.token)

artifact = Artifact.parse(args.maven_coordinate)

filename = args.filename

if dl.download(artifact, filename, args.hash_type):
sys.exit(0)
else:
parser.print_usage()
print("Download failed.")
sys.exit(1)
except RequestException as e:
print(e.msg)
Expand Down
7 changes: 4 additions & 3 deletions src/maven_artifact/requestor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from maven_artifact.utils import Utils


class RequestException(Exception):
def __init__(self, msg):
self.msg = msg
Expand All @@ -20,11 +21,11 @@ def request(self, url, onFail, onSuccess=None, method: str = "get", **kwargs):

if self.username and self.password:
token = self.username + ":" + self.password
headers["Authorization"] = "Basic " + base64.b64encode(token.encode()).decode()
headers["Authorization"] = f"Basic {base64.b64encode(token.encode()).decode()}"
elif Utils.is_base64(self.password):
headers["Authorization"] = "Basic " + base64.decode(self.password)
headers["Authorization"] = f"Basic {self.password}"
elif self.token:
headers["Authorization"] = "Bearer " + self.token
headers["Authorization"] = f"Bearer {base64.b64encode(self.token.encode()).decode()}"

try:
response = getattr(requests, method)(url, headers=headers, **kwargs)
Expand Down
22 changes: 0 additions & 22 deletions src/maven_artifact/utils.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
import base64

from maven_artifact.artifact import Artifact


class Utils:

@staticmethod
def parse(maven_coordinate):
parts = maven_coordinate.split(":")
if len(parts) >= 3:
g = parts[0]
a = parts[1]
v = parts[len(parts) - 1]
t = None
c = None
if len(parts) == 4:
t = parts[2]
if len(parts) == 5:
t = parts[2]
c = parts[3]
return Artifact(group_id=g, artifact_id=a, version=v, classifier=c, extension=t)
else:
return None

@staticmethod
def is_base64(sb):
try:
Expand All @@ -36,4 +15,3 @@ def is_base64(sb):
return base64.b64encode(base64.b64decode(sb_bytes)) == sb_bytes
except Exception:
return False

3 changes: 2 additions & 1 deletion tests/integration/maven_artifact/test_downloader.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os
import tempfile

from maven_artifact import Artifact, Downloader
from maven_artifact import Downloader
from maven_artifact.artifact import Artifact


def test_downloader_of_existing_artifact():
Expand Down

0 comments on commit 5bbea04

Please sign in to comment.