Skip to content

Commit

Permalink
Display reason when user is unauthorized
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaudh committed Dec 18, 2020
1 parent 4852041 commit 746f20c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 12 deletions.
41 changes: 30 additions & 11 deletions src/webui/gitutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,31 @@ getrepo(::GitLabAPI, owner::AbstractString, name::AbstractString) =
getrepo(::GitHubAPI, owner::AbstractString, name::AbstractString) =
@gf get_repo(PROVIDERS["github"].client, owner, name)


abstract type AuthResult end
struct AuthSuccess <: AuthResult end
struct AuthFailure <: AuthResult
reason::AbstractString
end

function AuthResult(res::Union{Bool,Nothing}, reason_for_failure::AbstractString)
if res === nothing || !res
return AuthFailure(reason_for_failure)
else
return AuthSuccess()
end
end

is_success(res::AuthSuccess) = true
is_success(res::AuthFailure) = false

# Check for a user's authorization to release a package.
# The criteria is simply whether the user is a collaborator for user-owned repos,
# or whether they're an organization member or collaborator for organization-owned repos.
isauthorized(u, repo) = false
isauthorized(u, repo) = AuthFailure("Unkown user type / repo type")
function isauthorized(u::User{GitHub.User}, repo::GitHub.Repo)
if !get(CONFIG, "allow_private", false)
repo.private && return false
return AuthResult(!repo.private, "Repo $(repo.name) is private")
end

if repo.private
Expand All @@ -40,20 +58,21 @@ function isauthorized(u::User{GitHub.User}, repo::GitHub.Repo)
forge = u.forge
end

hasauth = if repo.organization === nothing
@gf is_collaborator(forge, repo.owner.login, repo.name, u.user.login)
if repo.organization === nothing
hasauth = @gf is_collaborator(forge, repo.owner.login, repo.name, u.user.login)
return AuthResult(hasauth, "User $(u.user.name) is not a collaborator on repo $(repo.name)")
else
# First check for organization membership, and fall back to collaborator status.
ismember = @gf is_member(forge, repo.organization.login, u.user.login)
something(ismember, false) ||
hasauth = something(ismember, false) ||
@gf is_collaborator(forge, repo.organization.login, repo.name, u.user.login)
return AuthResult(hasauth, "User $(u.user.name) is not part of the org $(repo.organization.login) and not a collaborator on repo $(repo.name)")
end
return something(hasauth, false)
end

function isauthorized(u::User{GitLab.User}, repo::GitLab.Project)
if !get(CONFIG, "allow_private", false)
repo.visibility == "private" && return false
return AuthResult(repo.visibility !== "private", "Project $(repo.name) is private")
end

if repo.visibility == "private"
Expand All @@ -62,8 +81,9 @@ function isauthorized(u::User{GitLab.User}, repo::GitLab.Project)
forge = u.forge
end

hasauth = if repo.namespace.kind == "user"
@gf is_collaborator(forge, repo.owner.username, repo.name, u.user.id)
if repo.namespace.kind == "user"
hasauth = @gf is_collaborator(forge, repo.owner.username, repo.name, u.user.id)
return AuthResult(hasauth, "User $(u.user.name) is not a member of project $(repo.name)")
else
# Same as above: group membership then collaborator check.
nspath = split(repo.namespace.full_path, "/")
Expand All @@ -76,9 +96,8 @@ function isauthorized(u::User{GitLab.User}, repo::GitLab.Project)
something(ismember, false) && break
end
end
ismember
return AuthResult(ismember, "Project $(repo.name) belongs to the group $(repo.namespace.full_path), and user $(u.user.name) is not a member of that group or its parent group(s)")
end
return something(hasauth, false)
end

# Get the raw (Julia)Project.toml text from a repository.
Expand Down
5 changes: 4 additions & 1 deletion src/webui/routes/register.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ function register(r::HTTP.Request)
owner, name = splitrepo(package)
repo = getrepo(u.forge, owner, name)
repo === nothing && return json(400; error="Repository was not found")
isauthorized(u, repo) || return json(400; error="Unauthorized to release this package")
auth_result = isauthorized(u, repo)
if !is_success(auth_result)
return json(400; error="Unauthorized to release this package. Reason: $(auth_result.reason)")
end

# Get the (Julia)Project.toml, and make sure it is valid.
toml = gettoml(u.forge, repo, ref)
Expand Down

0 comments on commit 746f20c

Please sign in to comment.