Rundown of Final Version of our code - Alna132/GO-Group-Web-App GitHub Wiki

We have 5 files:

HTML Files

  1. index.html
  2. Internal.html
  3. login.html
  4. signup.html

Go File:

Main.go

index.html

This page is the first thing a user will see on this website, it is accessible to a user regardless of having an account set up.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
	<title>WorkTracker</title>
  <!-- Stylesheets -->
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <!-- JQuery -->
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<!--Adapted from: https://www.sitepoint.com/ -->
</head>
<body>
  <!-- Use Jumbotron template from Bootstrap as our look to the website -->
<div class="jumbotron">
<!-- Display Home Page Header -->
    <h1>Home Page</h1>
</div>

<!-- Create a navbar fixed to the top of the website -->
<nav class="navbar navbar-inverse navbar-fixed-top">
<!-- Like a Stackpanel in C#, A container handles how things are formatted/spaced out -->
      <div class="container">
<!-- Create a NavBar Header -->
  <div class="navbar-header">
  <!-- Creating the NavBar styling -->
  <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
    <span class="sr-only">Toggle navigation</span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
<!-- Using the Success button to create a green button with a Login Link on it -->
	<button class="btn btn-success"><a href="/login">Login</a></button>
<!-- Using the Warning button to create an Orange button with a Sign Up Link on it -->
    <button class="btn btn-warning"><a href="/signup">Sign Up</a></button>
	<button class="navbar-toggle collapsed">To get navbar-brand to appear</button>
  <!-- The title of the website -->
	<a class="navbar-brand" href="#">Work Tracker</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <form class="navbar-form navbar-right">
  
</form>
          </form>
</body>
</html>

Internal.html

This page is only accessible to a user if they have signed up to the website with a username and password, this user is already stored in the database.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<h1>-</h1>
<hr>
<small>Welcome!</small>

<html ng-app> <!-- 'ng-app'' placed within a tag (in this case, the HTML tag)
				allows HTML to become the route element for AngularJS.
				All AngularJS applications must have a root element. Only one instance allowed. --> 
<head>
	<title>WorkTracker</title>
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<!--Adapted from: https://www.sitepoint.com/ -->
  <!-- Using JavaScript -->
  <script language="javascript">
    // Create a Function called Calculate()
		function Calculate()
		{
      //Create a variable called h which gets the values in the hoursWorked dropdownlist
			var h = document.getElementById('hoursWorked').value;
       //Create a variable called t which gets the values in the hourlyPay dropdownlist
			var t = document.getElementById('hourlyPay').value;
      // multiply h (hoursWorked) by t (hourlyPay)
			var result = h * t;
      //Output this result to a label
			document.getElementById('lblRes').innerHTML = result;
		}
    //End the JavaScript
	</script>
</head>
<body>
	<!-- Main jumbotron for a primary marketing message or call to action -->
    <div class="jumbotron">
      <!--Changed the top header here to include a name being entered and shown back to the user with a friendly hello-->
      <div class="container">
        <h2><input type="text" placeholder="Your Name here" ng-model="yes"></h2>
		      <h3><p>Hello <span ng-bind="yes"></span></p></h3>
        <p>This is a place where you can record all of your daily duties in one place, ready to show the boss. </p>
      </div>
    </div>
	<div class="container">
		
	</div>
	<nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
                     <form method="post" action="/logout">
    <button type="submit" class="btn btn-danger">Logout</button>
          </button>
          <a class="navbar-brand" href="#">Work Tracker</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <form class="navbar-form navbar-right">
  
</form>
          </form>
        </div><!--/.navbar-collapse -->
      </div>
    </nav>
	<div class="container">
      <!-- Example row of columns -->
      <div class="row">
        <div class="col-md-4">
          <h2>Job Title</h2>
          <!-- Dropdown list with Tradesperson's job titles
  adapted from https://www.socketloop.com/tutorials/golang-populate-dropdown-with-html-template-example -->
          <select>
    <option value="Beautician">Beautician</option>
    <option value="Builder">Builder</option>
    <option value="Carpenter">Carpenter</option>
    <option value="Cleaner">Cleaner</option>
    <option value="Delivery">Delivery</option>
    <option value="Electrician">Electrician</option>
    <option value="Farmer">Farmer</option>
    <option value="Gardener">Gardener</option>
    <option value="Hair and Beauty">Hair and Beauty</option>
    <option value="Hairdresser">Hairdresser</option>
    <option value="Mechanic">Mechanic</option>
    <option value="Painter">Painter</option>
    <option value="Plumber">Plumber</option>
    <option value="Technician">Technician</option>
    <option value="Tiler">Tiler</option>
    <option value="Transport">Transport</option>
    <option value="Other">Other</option>
 <!-- Code adapted from http://stackoverflow.com/questions/30717105/adding-view-details-button-with-js -->
  </select>
  <!-- Allows you to see more information about the dropdown list -->
          <details>
    <summary>View Details</summary>
    <p>
        Please select your correct job title here from the dropdown list.
    </p>
</details>
</div>

<!-- Code adapted from http://www.w3schools.com/html/html_form_elements.asp -->
  <div class="col-md-4">
     <!-- Dropdown list with Tradesperson's hours worked that week, min 10 max 40 -->
     <h2>Hours Worked This Week</h2>
  <select Id="hoursWorked" onChange="Calculate();">
			  <option value=10>10</option>
			  <option value=11>11</option>
			  <option value=12>12</option>
			  <option value=13>13</option>
			  <option value=14>14</option>
			  <option value=15>15</option>
			  <option value=16>16</option>
			  <option value=17>17</option>
			  <option value=18>18</option>
			  <option value=19>19</option>
			  <option value=20>20</option>
			  <option value=21>21</option>
			  <option value=22>22</option>
			  <option value=23>23</option>
			  <option value=24>24</option>
			  <option value=25>25</option>
			  <option value=26>26</option>
			  <option value=27>27</option>
			  <option value=28>28</option>
			  <option value=29>29</option>
			  <option value=30>30</option>
			  <option value=31>31</option>
			  <option value=32>32</option>
			  <option value=33>33</option>
			  <option value=34>34</option>
			  <option value=35>35</option>
			  <option value=36>36</option>
			  <option value=37>37</option>
			  <option value=38>38</option>
			  <option value=39>39</option>
			  <option value=40>40</option>

			</select>

      <!-- See function in header, it calculates hourly pay that the worker receives  -->
			  &nbsp;&nbsp;
			* &nbsp;
			Hourly Pay:
			<select Id="hourlyPay" onChange="Calculate();">
        <!-- This dropdown list contains the pay rates that are multiplied by the hours worked by the Tradesperson
         within the calculation in the header above -->
			  <option value=6.24>6.24</option>
			  <option value=7.25>7.25</option>
			  <option value=9.15>9.15</option>
			  <option value=11.25>11.25</option>
			  <option value=20.83>20.83</option>
			</select>
      <!-- Just inserts a few spaces -->
			&nbsp;&nbsp;
			
			= Total:&nbsp;&nbsp;
      <!-- label -->
			<label id="lblRes"> <!-- result of Calculating hoursWorked * hourlyPay -->
			 100
			</label>

          <details>
    <summary>View Details</summary>
    <p>
        Please select the correct amount of hours you worked this week. 
        <br> Please note: In order to use this site you have to be working a minimum of 10 hours a week and a maximum of 40 hours. </br>

          </p>
</details>
       </div>

<!-- A textbox which the user can enter into to tell their boss any additional information about their week's work -->
        <div class="col-md-4">
          <h2>Additonal Information</h2>
          <!--Adapted from http://www.w3schools.com/tags/tag_input.asp-->
          <!-- A form action to submit all of the details given on the form -->
          <form action="demo_form.asp">
              <input type="text" name="AddInfo" value=""><br>
              <input type="submit" value="Submit">
</form>
<details>
    <summary>View Details</summary>
    <p>
        Please add any additional information that you feel is relevent for your boss to know about regarding this week's work.
    </p>
</details>
        </div>
      </div>



	  <hr>

    <!-- Just including a Company trademark in the footer -->
      <footer>
        <p>&copy; 2016 WorkTracker, Inc.</p>
      </footer>
    </div> <!-- /container -->
    <!-- To use AngularJS -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js"></script>
</body>
</html>

Signup.html:

This is the page that allows the user to Signup to the website.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WorkTracker</title>
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<!--Adapted from: https://www.sitepoint.com/ -->
</head>
<body>
<div class="jumbotron">
    <h1>Sign up</h1>
    <form method="POST" action="/signup">
        <input type="text" name="username">
        <input type="password" name="password">
        <input type="submit" value="Submit">
    </form>
</div>
<nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
			<button class="navbar-toggle collapsed">To get navbar-brand to appear<button>
			<a class="navbar-brand" href="#">Work Tracker</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <form class="navbar-form navbar-right">
  
</form>
          </form>
</body>
</html>

Login.html:

This is the page that allows the user to login to the website.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WorkTracker</title>
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
	<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<!--Adapted from: https://www.sitepoint.com/ -->
</head>
<body>
<div class="jumbotron">
    <h1>Login Page</h1>
    <form method="POST" action="/login">
        <input type="text" name="username" placeholder="username">
        <input type="password" name="password" placeholder="password">
        <input type="submit" value="Submit">
    </form>
</div>
<nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
			<button class="navbar-toggle collapsed">To get navbar-brand to appear</button>
			<a class="navbar-brand" href="#">Work Tracker</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <form class="navbar-form navbar-right">
  
</form>
          </form>
</body>
</html>

Main.go:

This file contains all of the golang code and handles the connection between the client and server

//https://dinosaurscode.xyz/go/2016/06/19/golang-mysql-authentication/

package main

// This allows us to use the SQL Database
import "database/sql" //need to type "database/sql" into cmder to use 
// This installs a driver in order to be able to use mySQL
import _ "github.com/go-sql-driver/mysql" //need to type "github.com/go-sql-driver/mysql" into cmder to use 
// This import statement allows encryption and decryption of passwords
import "golang.org/x/crypto/bcrypt" //need to type "golang.org/x/crypto/bcrypt" into cmder to use 

import "net/http"


//A variable which initialises the use of sql
var db *sql.DB
// A variable ro handle errors
var err error


//We start off with a Signup function so the user can Signup
// We initialise the use of the response (res) using the ResponseWriter
// and the request (req) by using http.Request
func signupPage(res http.ResponseWriter, req *http.Request) {
	//If the request is not a POST method (the POST request method requests that a web server accept and store
	// the data enclosed in the body of the request message. It is used when submitting a completed web Form)
	if req.Method != "POST" {
	//then serve the SignUp page
		http.ServeFile(res, req, "signup.html")
		return
	}

//The username and password are set up as a formValue
	username := req.FormValue("username")
	password := req.FormValue("password")

//the user is initialised as a string
	var user string

// Query the database to see if the user signing in is clashing credentials
//with any existing users within the database
	err := db.QueryRow("SELECT username FROM users WHERE username=?", username).Scan(&user)

//a switch statement to handle the signin
	switch {
	case err == sql.ErrNoRows:
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
		//If the error list is not equal to null, in other words if there is (are) error(s)
		if err != nil {
		//There will be a server error 500 and your account will not be created
			http.Error(res, "Server error, unable to create your account.", 500)
			return
		}

	   // The "_" (blank identifier) avoids having to declare all the variables for the return values.
	   // Try inserting a username and password into the users table  abd encrypt the password
		_, err = db.Exec("INSERT INTO users(username, password) VALUES(?, ?)", username, hashedPassword)
		//If there are errors
		if err != nil {
		// The response (res) will say Server eror 500 and you can't create your account
			http.Error(res, "Server error, unable to create your account.", 500)
			return
		}

		// Otherwise A user is created
		res.Write([]byte("User created!"))
		return
	case err != nil:
		http.Error(res, "Server error, unable to create your account.", 500)
		return
	default:
		http.Redirect(res, req, "/", 301)
	}
}

// This is a function to allow a user to log into the website
func loginPage(res http.ResponseWriter, req *http.Request) {
	if req.Method != "POST" {
		http.ServeFile(res, req, "login.html")
		return
	}

	username := req.FormValue("username")
	password := req.FormValue("password")

//This time we have a Username variable and a Password variable
	var databaseUsername string
	var databasePassword string

//Scan the database to find the returning user as they login with their username and password
	err := db.QueryRow("SELECT username, password FROM users WHERE username=?", username).Scan(&databaseUsername, &databasePassword)
//If there are errors with the user logging in
	if err != nil {
		//Error 301
		http.Redirect(res, req, "/login", 301)
		return
	}

	err = bcrypt.CompareHashAndPassword([]byte(databasePassword), []byte(password))
	if err != nil {
		http.Redirect(res, req, "/login", 301)
		return
	}

//If all is successful, serve up the internal.html file which only a logged-in user should be able to see
	http.ServeFile(res, req, "Internal.html")
	//res.Write([]byte("Hello" + databaseUsername))
}

//A function to serve up the homepage called index.html which includes the login and signup buttons
func homePage(res http.ResponseWriter, req *http.Request) {
	http.ServeFile(res, req, "index.html")
}

//Main function
func main() {

	//Open an sql connection, and handle errors,
	// The database is mysql, then we have the hostName of the server on Azure (b71da173aea4cf)
	// (05606ea1)
	//TCP stands for Transmission Control Protocol which is a set of networking protocols that allows
	// two or more computers to communicate
	// (eu-cdbr-azure-west-a.cloudapp.net)
	// Port Name on Azure (3306)
	// The name of the database (godatabase)
	db, err = sql.Open("mysql", "b71da173aea4cf:05606ea1@tcp(eu-cdbr-azure-west-a.cloudapp.net:3306)/godatabase")
	//If there are errors connecting to the server
	if err != nil {
	//output a panic error
		panic(err.Error())
	}
	//close the connection to the database
	defer db.Close()

//Checking is the connection to the database still alive
	err = db.Ping()
	//otherwise painic
	if err != nil {
		panic(err.Error())
	}

//Handle all of our functions
	http.HandleFunc("/signup", signupPage)
	http.HandleFunc("/login", loginPage)
	http.HandleFunc("/", homePage)

	//serve on the port 8000 forever
	http.ListenAndServe(":8000", nil)
}
⚠️ **GitHub.com Fallback** ⚠️