Skip to content

Commit

Permalink
Merge pull request #155 from dwyl/username-repository-validation-#154
Browse files Browse the repository at this point in the history
display 404 invalid badge when user or repository invalid
  • Loading branch information
nelsonic committed Mar 14, 2022
2 parents c629c8f + 2f4df0b commit 6f32a14
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 23 deletions.
19 changes: 17 additions & 2 deletions lib/hits.ex
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,23 @@ defmodule Hits do
"""
end

def svg_invalid_badge do
"""
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96" height="20" role="img" aria-label="hits: invalid url">
<title>hits: invalid url</title>
<g shape-rendering="crispEdges"><rect width="31" height="20" fill="#555"/>
<rect x="31" width="65" height="20" fill="#e05d44"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif"
text-rendering="geometricPrecision" font-size="110">
<text x="165" y="140" transform="scale(.1)" fill="#fff" textLength="210">hits</text>
<text x="625" y="140" transform="scale(.1)" fill="#fff" textLength="550">invalid url</text>
</g>
</svg>
"""
end

@doc """
make_badge/1 from a given svg template style, substituting the count value. Default style is 'flat-square'
Expand All @@ -90,8 +107,6 @@ defmodule Hits do
# stackoverflow.com/a/1084759
|> String.replace(~r/<!--(.*?)-->/, "")
end


end

@doc """
Expand Down
62 changes: 42 additions & 20 deletions lib/hits_web/controllers/hit_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,35 @@ defmodule HitsWeb.HitController do

def index(conn, %{"user" => user, "repository" => repository} = params) do
if String.ends_with?(repository, ".svg") do
# insert hit
{_user_schema, _useragent_schema, repo} = insert_hit(conn, user, repository)

count =
if params["show"] == "unique" do
Hit.count_unique_hits(repo.id)
else
Hit.count_hits(repo.id)
end

# Send hit to connected clients via channel github.com/dwyl/hits/issues/79
HitsWeb.Endpoint.broadcast("hit:lobby", "hit", %{
"user" => user,
"repo" => repository,
"count" => count
})

# render badge
render_badge(conn, count, params["style"])
if user_valid?(user) and repository_valid?(repository) do
# insert hit
{_user_schema, _useragent_schema, repo} = insert_hit(conn, user, repository)

count =
if params["show"] == "unique" do
Hit.count_unique_hits(repo.id)
else
Hit.count_hits(repo.id)
end

# Send hit to connected clients via channel github.com/dwyl/hits/issues/79
HitsWeb.Endpoint.broadcast("hit:lobby", "hit", %{
"user" => user,
"repo" => repository,
"count" => count
})

# render badge
render_badge(conn, count, params["style"])
else
render_invalid_badge(conn)
end
else
render(conn, "index.html", params)
if user_valid?(user) and repository_valid?(repository) do
render(conn, "index.html", params)
else
redirect(conn, to: "/error/#{user}/#{repository}")
end
end
end

Expand Down Expand Up @@ -85,6 +93,12 @@ defmodule HitsWeb.HitController do
|> send_resp(200, Hits.make_badge(count, style))
end

def render_invalid_badge(conn) do
conn
|> put_resp_content_type("image/svg+xml")
|> send_resp(404, Hits.svg_invalid_badge())
end

@doc """
edgecase/2 handles the case where people did not follow the instructions
for creating their badge ... 🙄 see: https://github.com/dwyl/hits/issues/67
Expand All @@ -108,4 +122,12 @@ defmodule HitsWeb.HitController do
|> send_resp(404, Hits.make_badge(404, params["style"]))
end
end

# see issue https://github.com/dwyl/hits/issues/154
# alphanumeric follow by one or zeor "-" or just alphanumerics
defp user_valid?(user), do: String.match?(user, ~r/^([[:alnum:]]+-)*[[:alnum:]]+$/)

# ^[[:alnum:]-_.]+$ means the name is composed of one or multiple alphanumeric character
# or "-_." characters
defp repository_valid?(repo), do: String.match?(repo, ~r/^[[:alnum:]-_.]+$/)
end
4 changes: 4 additions & 0 deletions lib/hits_web/controllers/page_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ defmodule HitsWeb.PageController do
def index(conn, _params) do
render(conn, "index.html")
end

def error(conn, %{"user" => user, "repository" => repository} = params) do
render(conn, "error.html", user: user, repository: repository)
end
end
1 change: 1 addition & 0 deletions lib/hits_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ defmodule HitsWeb.Router do
pipe_through(:browser)

get("/", PageController, :index)
get("/error/:user/:repository", PageController, :error)

get("/:user/:repository", HitController, :index)
get("/:etc/:user/:repository", HitController, :edgecase)
Expand Down
26 changes: 26 additions & 0 deletions lib/hits_web/templates/page/error.html.eex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<h2 class="bg-teal white h-25 tc ttu f1 lh-title lh-solid mt0 pa2 pb3 mb0 pb0">
Validation Error!
</h2>

<div class="pa3">
<p>Please make sure the username and the repository values are valid:</p>

<ul>
<li><strong><%=@user%></strong> - username may only contain alphanumeric characters or single hyphens, and cannot begin or end with a hyphen</li>
<li><strong><%=@repository%></strong> - repository may contain alphanumeric values and the following characters: "-", "_" "."</li>
</ul>

<%= link "Create a new badge", to: "/", class: "f6 link dim br2 ph3 pv2 mb2 dib white bg-teal" %>
</div>

<style>
.teal {
color: #4DB6AC;
}
.bg-teal {
background: #4DB6AC;
}
body { /* dwyl font */
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
</style>
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Hits.MixProject do
def project do
[
app: :hits,
version: "1.6.2",
version: "1.6.3",
elixir: "~> 1.12",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
Expand Down
18 changes: 18 additions & 0 deletions test/hits_web/controllers/hit_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,22 @@ defmodule HitsWeb.HitControllerTest do

assert res.resp_body =~ ~s(404)
end

test "GET /-user/repo.svg invalid user", %{conn: conn} do
res =
put_req_header(conn, "user-agent", "Hackintosh")
|> put_req_header("accept-language", "en-GB,en;q=0.5")
|> get("/-user/repo.svg")

assert res.resp_body =~ Hits.svg_invalid_badge()
end

test "GET /user/repo{}!!.svg invalid repository", %{conn: conn} do
res =
put_req_header(conn, "user-agent", "Hackintosh")
|> put_req_header("accept-language", "en-GB,en;q=0.5")
|> get("/user/repo{}!!.svg")

assert res.resp_body =~ Hits.svg_invalid_badge()
end
end
15 changes: 15 additions & 0 deletions test/hits_web/controllers/page_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,19 @@ defmodule HitsWeb.PageControllerTest do
conn = get(conn, "/")
assert html_response(conn, 200) =~ "Hits!"
end

test "GET /user/repo", %{conn: conn} do
conn = get(conn, "/user/repo")
assert html_response(conn, 200) =~ "dashboard"
end

test "GET /--user/repo$", %{conn: conn} do
conn = get(conn, "/--user/repo$")
assert html_response(conn, 302)
end

test "GET /error/--user/repo$", %{conn: conn} do
conn = get(conn, "/error/--user/repo$")
assert html_response(conn, 200) =~ "Validation Error!"
end
end

0 comments on commit 6f32a14

Please sign in to comment.