Skip to content

Commit

Permalink
Add support for Digital Asset Links in web app and CLI.
Browse files Browse the repository at this point in the history
  • Loading branch information
chayev committed Jan 22, 2023
1 parent 4e90f81 commit 9aaeb2e
Show file tree
Hide file tree
Showing 14 changed files with 456 additions and 48 deletions.
8 changes: 4 additions & 4 deletions cli/cmd/aasa_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
"github.com/spf13/cobra"
)

// validateCmd represents the validate command
var validateCmd = &cobra.Command{
// validateAASACmd represents the validate command for Apple App Site Association
var validateAASACmd = &cobra.Command{
Use: "validate <URL>",
Short: "Validate your link against Apple's requirements",
Run: func(cmd *cobra.Command, args []string) {
output := yurllib.CheckDomain(args[0], "", "", true)
output := yurllib.CheckAASADomain(args[0], "", "", true)

for _, item := range output {
fmt.Print(item)
Expand All @@ -23,5 +23,5 @@ var validateCmd = &cobra.Command{
}

func init() {
aasaCmd.AddCommand(validateCmd)
aasaCmd.AddCommand(validateAASACmd)
}
16 changes: 16 additions & 0 deletions cli/cmd/assetlink.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cmd

import (
"github.com/spf13/cobra"
)

var (
assetlinkCmd = &cobra.Command{
Use: "assetlink",
Short: "Command for Android Asset Link utils.",
}
)

func init() {
rootCmd.AddCommand(assetlinkCmd)
}
27 changes: 27 additions & 0 deletions cli/cmd/assetlink_validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package cmd

import (
"fmt"

"github.com/chayev/yurl/yurllib"

"github.com/spf13/cobra"
)

// validateAssetLinkCmd represents the validate command for ASset Links
var validateAssetLinkCmd = &cobra.Command{
Use: "validate <URL>",
Short: "Validate your link against Android's requirements",
Run: func(cmd *cobra.Command, args []string) {
output := yurllib.CheckAssetLinkDomain(args[0], "", "")

for _, item := range output {
fmt.Print(item)
}

},
}

func init() {
assetlinkCmd.AddCommand(validateAssetLinkCmd)
}
54 changes: 51 additions & 3 deletions webapp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func main() {
log.Println("Listening on :8080...")
http.HandleFunc("/", handler)
http.HandleFunc("/results", viewResults)
http.HandleFunc("/android", android)
http.HandleFunc("/android-results", viewResultsAndroid)
log.Fatal(http.ListenAndServe(":8080", nil))
}

Expand All @@ -32,7 +34,7 @@ func handler(w http.ResponseWriter, r *http.Request) {

content := &PageOutput{CurrentTime: time.Now()}

t, _ := template.ParseFiles("tpl/home.html", "tpl/partials/header.html", "tpl/partials/footer.html")
t, _ := template.ParseFiles("tpl/home.html", "tpl/partials/header.html", "tpl/partials/footer.html", "tpl/partials/navToAndroid.html")
t.ExecuteTemplate(w, "home.html", &content)
}

Expand All @@ -59,7 +61,7 @@ func viewResults(w http.ResponseWriter, r *http.Request) {
if url == "" {
output = append(output, "Enter URL to validate.")
} else {
output = yurllib.CheckDomain(url, prefix, bundle, true)
output = yurllib.CheckAASADomain(url, prefix, bundle, true)
}

content := &PageOutput{URL: url, Prefix: prefix, Bundle: bundle}
Expand All @@ -70,6 +72,52 @@ func viewResults(w http.ResponseWriter, r *http.Request) {

content.CurrentTime = time.Now()

t, _ := template.ParseFiles("tpl/results.html", "tpl/partials/header.html", "tpl/partials/footer.html")
t, _ := template.ParseFiles("tpl/results.html", "tpl/partials/header.html", "tpl/partials/footer.html", "tpl/partials/navToAndroid.html")
t.ExecuteTemplate(w, "results.html", &content)
}

func android(w http.ResponseWriter, r *http.Request) {

content := &PageOutput{CurrentTime: time.Now()}

t, _ := template.ParseFiles("tpl/android.html", "tpl/partials/header.html", "tpl/partials/footer.html", "tpl/partials/navToiOS.html")
t.ExecuteTemplate(w, "android.html", &content)
}

func viewResultsAndroid(w http.ResponseWriter, r *http.Request) {

var url string
var package_name string
var fingerprint string

for _, n := range r.URL.Query()["url"] {
url = n
}

for _, n := range r.URL.Query()["prefix"] {
package_name = n
}

for _, n := range r.URL.Query()["bundle"] {
fingerprint = n
}

var output []string

if url == "" {
output = append(output, "Enter URL to validate.")
} else {
output = yurllib.CheckAssetLinkDomain(url, package_name, fingerprint)
}

content := &PageOutput{URL: url, Prefix: package_name, Bundle: fingerprint}

for _, item := range output {
content.Content += item
}

content.CurrentTime = time.Now()

t, _ := template.ParseFiles("tpl/android-results.html", "tpl/partials/header.html", "tpl/partials/footer.html", "tpl/partials/navToiOS.html")
t.ExecuteTemplate(w, "android-results.html", &content)
}
2 changes: 1 addition & 1 deletion webapp/static/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,4 @@ footer a {
padding-left: 15px;
padding-right: 15px;
}
}
}
27 changes: 27 additions & 0 deletions webapp/tpl/android-results.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{{ template "header" }}
<body id="results">
<header class="padding">
<h1><a href="/android" aria-label="Go to Homepage" tabindex="-1">yURL</a><span id="description">: Asset Links File Validator</span></h1>
<a href="https://www.github.com/chayev/yurl" target="_blank" rel="noopener" title="Go to the GitHub project" aria-label="Go to the GitHub project" tabindex="-1"><i class="fab fa-github"></i></a>
</header>
{{ template "navToiOS" }}
<main class="padding">
<form method="GET" action="/android-results" id="assetlink">
<label class="wide" for="url">URL</label>
<label class="wide" for="prefix">Package Name</label>
<label class="wide" for="bundle">Package Fingerprint</label>
<label class="mini" for="url">URL</label>
<input type="text" name="url" placeholder="Required" value="{{ .URL }}" tabindex="1"/>
<label class="mini" for="prefix">Package</label>
<input type="text" name="prefix" placeholder="Optional" value="{{ .Prefix }}" tabindex="2" />
<label class="mini" for="bundle">Fingerprint</label>
<input type="text" name="bundle" placeholder="Optional" value="{{ .Bundle }}" tabindex="3" />
<a class="wide" href="#" onclick="document.getElementById('assetlink').submit()" tabindex="4"><i class="fas fa-redo-alt"></i></a>
<input class="mini" type="submit" value="Validate" tabindex="-1" />
</form>
<h2>Results:</h2>
<pre>{{ .Content }}</pre>
</main>
{{ template "footer" . }}
</body>
</html>
17 changes: 17 additions & 0 deletions webapp/tpl/android.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{ template "header" }}
<body>
{{ template "navToiOS" }}
<header><a href="https://www.github.com/chayev/yurl" id="github-home" target="_blank" rel="noopener" title="Go to the GitHub project" aria-label="Go to the GitHub project"><i class="fab fa-github"></i></a></header>
<main>
<h1><span id="name">yURL</span>: Asset Links File Validator</h1>
<p>yURL allows you to validate whether a URL is properly configured for Android Asset Links. This allows you to check if the assetlinks.json file exists and is in the proper format as <a href="https://developers.google.com/digital-asset-links/v1/getting-started" target="_blank" rel="noopener" aria-label="Google Digital Asset Links Requirements">defined by Google</a>.</p>
<form method="GET" action="/android-results">
<input type="text" name="url" placeholder="Enter a URL test (e.g. https://app.chayev.com/xyx)" tabindex="1" />
<input type="text" name="prefix" placeholder="Package Name (Optional)" tabindex="2" />
<input type="text" name="bundle" placeholder="Package Fingerprint (Optional)" tabindex="3" />
<input type="submit" value="Validate" tabindex="4" />
</form>
</main>
{{ template "footer" . }}
</body>
</html>
1 change: 1 addition & 0 deletions webapp/tpl/home.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{{ template "header" }}
<body>
{{ template "navToAndroid" }}
<header><a href="https://www.github.com/chayev/yurl" id="github-home" target="_blank" rel="noopener" title="Go to the GitHub project" aria-label="Go to the GitHub project"><i class="fab fa-github"></i></a></header>
<main>
<h1><span id="name">yURL</span>: Universal Links / AASA File Validator</h1>
Expand Down
5 changes: 5 additions & 0 deletions webapp/tpl/partials/navToAndroid.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{ define "navToAndroid" }}
<div style="background-color: #333333; padding: 5px;">
<a href="/android" style="text-decoration: none; color: #ffffff">Click here to validate Android Deep Linking instead</a>
</div>
{{end}}
5 changes: 5 additions & 0 deletions webapp/tpl/partials/navToiOS.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{ define "navToiOS" }}
<div style="background-color: #333333; padding: 5px;">
<a href="/"style="text-decoration: none; color: #ffffff">Click here to validate iOS Deep Linking instead</a>
</div>
{{end}}
1 change: 1 addition & 0 deletions webapp/tpl/results.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<h1><a href="/" aria-label="Go to Homepage" tabindex="-1">yURL</a><span id="description">: Universal Links / AASA File Validator</span></h1>
<a href="https://www.github.com/chayev/yurl" target="_blank" rel="noopener" title="Go to the GitHub project" aria-label="Go to the GitHub project" tabindex="-1"><i class="fab fa-github"></i></a>
</header>
{{ template "navToAndroid" }}
<main class="padding">
<form method="GET" action="/results" id="aasa">
<label class="wide" for="url">URL</label>
Expand Down
44 changes: 4 additions & 40 deletions yurllib/aasa.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"

"go.mozilla.org/pkcs7"
Expand Down Expand Up @@ -49,8 +48,8 @@ type genericService struct {
Apps []string `json:"apps,omitempty"`
}

// CheckDomain : Main function used by CLI and WebApp
func CheckDomain(inputURL string, bundleIdentifier string, teamIdentifier string, allowUnencrypted bool) []string {
// CheckAASADomain : Main function used by CLI and WebApp for Apple App Site Association validation
func CheckAASADomain(inputURL string, bundleIdentifier string, teamIdentifier string, allowUnencrypted bool) []string {

var output []string

Expand Down Expand Up @@ -118,31 +117,6 @@ func CheckDomain(inputURL string, bundleIdentifier string, teamIdentifier string
return output
}

func getDomain(input string) (string, []string) {

var output []string

//Clean up domains, removing scheme and path
parsedURL, err := url.Parse(input)
if err != nil {
output = append(output, fmt.Sprintf("The URL failed to parse with error %s \n", err))
}

scheme := parsedURL.Scheme

if scheme != "https" {
output = append(output, fmt.Sprintf("WARNING: The URL must use HTTPS, trying HTTPS instead. \n\n"))

parsedURL.Scheme = "https"
parsedURL, err = url.Parse(parsedURL.String())
if err != nil {
output = append(output, fmt.Sprintf("The URL failed to parse with error %s \n", err))
}
}

return parsedURL.Host, output
}

func loadAASAContents(domain string) (*http.Response, []string, []error) {

var output []string
Expand Down Expand Up @@ -183,16 +157,6 @@ func loadAASAContents(domain string) (*http.Response, []string, []error) {
return nil, output, formatErrors
}

func makeRequest(fileURL string) (*http.Response, error) {

resp, err := http.Get(fileURL)
if err != nil {
return nil, err
}

return resp, nil
}

func evaluateAASA(result []byte, contentType []string, bundleIdentifier string, teamIdentifier string, encrypted bool) ([]string, []error) {

var output []string
Expand Down Expand Up @@ -231,7 +195,7 @@ func evaluateAASA(result []byte, contentType []string, bundleIdentifier string,

output = append(output, fmt.Sprintln("JSON Validation: \t\t Pass"))

validJSON, formatErrors := verifyJSONformat(reqResp)
validJSON, formatErrors := verifyAASAJSONformat(reqResp)

if validJSON {
output = append(output, fmt.Sprintln("JSON Schema: \t\t\t Pass"))
Expand Down Expand Up @@ -263,7 +227,7 @@ func evaluateAASA(result []byte, contentType []string, bundleIdentifier string,

}

func verifyJSONformat(content aasaFile) (bool, []error) {
func verifyAASAJSONformat(content aasaFile) (bool, []error) {

appLinks := content.Applinks

Expand Down
Loading

0 comments on commit 9aaeb2e

Please sign in to comment.