Skip to content

Commit

Permalink
Merge pull request #5 from PreetinderSingh13/main
Browse files Browse the repository at this point in the history
Auth Updated
  • Loading branch information
JeevantVerma authored Jun 19, 2024
2 parents eb37c20 + c793dba commit 9aa77b2
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 163 deletions.
2 changes: 1 addition & 1 deletion backend/go-templates/view.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h1>All Links</h1>
</div>
</div>
<script type="module">
const password = "04b7ea35d471908eb2ec254dac05e80f7bfed03274d17c2d51b1db0dd1b162cf"
const password = "5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5"
let hash = '';
const content = document.querySelector(".content");
while(hash !== password){
Expand Down
1 change: 1 addition & 0 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ require (

require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
)
2 changes: 2 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
Expand Down
7 changes: 5 additions & 2 deletions backend/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"net/http"
"os"

auth "github.com/MicrosoftStudentChapter/Link-Generator/pkg/auth"
router "github.com/MicrosoftStudentChapter/Link-Generator/pkg/router"

"github.com/gorilla/mux"
"github.com/redis/go-redis/v9"
)
Expand All @@ -31,8 +31,11 @@ func main() {
fmt.Println("Redis [PING]: ", res)

r := mux.NewRouter()

r.HandleFunc("/links/all", router.GetAllLinks).Methods(http.MethodOptions, http.MethodGet)
r.HandleFunc("/generate-token", auth.GenerateJWT).Methods(http.MethodOptions, http.MethodGet)
r.Handle("/login", auth.TokenRequired(http.HandlerFunc(auth.ProtectedRoute))).Methods(http.MethodOptions, http.MethodGet)
r.HandleFunc("/register", auth.Register).Methods(http.MethodOptions, http.MethodPost)
r.HandleFunc("/show/users", auth.ShowUsers).Methods(http.MethodOptions, http.MethodGet)
r.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("Service is Alive"))
Expand Down
114 changes: 114 additions & 0 deletions backend/pkg/auth/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package auth

import (
// "fmt"
"encoding/json"
"net/http"
"os"
"time"

"github.com/dgrijalva/jwt-go"
)

var jwtKey = []byte(os.Getenv("JWT_SECRET"))
var users = map[string]string{}

type Claims struct {
Username string "json:username"
jwt.StandardClaims
}

func GenerateJWT(w http.ResponseWriter, r *http.Request) {
username := r.URL.Query().Get("username")
if username == "" {
http.Error(w, "Username is required", http.StatusBadRequest)
return
}

expirationTime := time.Now().Add(30 * time.Minute)
claims := &Claims{
Username: username,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
IssuedAt: time.Now().Unix(),
Issuer: "Linky",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(jwtKey)
if err != nil {
http.Error(w, "Could not generate token", http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"token": tokenString})
}

func ValidateJWT(tokenString string) (string, error) {
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
if err != nil {
if err == jwt.ErrSignatureInvalid {
return "", http.ErrBodyNotAllowed
}
return "", err
}
if !token.Valid {
return "", http.ErrBodyNotAllowed
}
return claims.Username, nil
}

func TokenRequired(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
if tokenString == "" {
http.Error(w, "Token is missing", http.StatusForbidden)
return
}

username, err := ValidateJWT(tokenString)
if err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
}

r.Header.Set("username", username)
next.ServeHTTP(w, r)
})
}

func ProtectedRoute(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "http://localhost:4000/admin", http.StatusSeeOther)
}

func Register(w http.ResponseWriter, r *http.Request) {
var userData struct {
Username string `json:"user"`
Password string `json:"pass"`
}

if err := json.NewDecoder(r.Body).Decode(&userData); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

if _, exists := users[userData.Username]; exists {
http.Error(w, "User already exists", http.StatusBadRequest)
return
}

users[userData.Username] = userData.Password

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"message": "User registered successfully"})
}

func ShowUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
54 changes: 53 additions & 1 deletion frontend/src/Maincontent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,41 @@ import axios from "axios";
const MainContentSection = () => {
const [longUrl, setLongUrl] = useState("");
const [alias, setAlias] = useState("");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [shortenedUrl, setShortenedUrl] = useState("");
const [expiry, setExpiry] = useState(dayjs().add(1, "week"));
const [expiryOption, setExpiryOption] = useState("1 week");
const [noExpiry, setNoExpiry] = useState(false);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [error, setError] = useState("");

const registerUser = async () => {
const userData = JSON.stringify({
user: username,
pass: password,
});

const config = {
method: "POST",
maxBodyLength: Infinity,
url: `http://localhost:4000/register`,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin":
"https://generate.mlsctiet.com, http://localhost:5173",
},
data: userData,
};
const response = await axios.request(config);

if (response.status == 200) {
console.log(userData);
setShortenedUrl("Login success");
} else {
setShortenedUrl("Login Failed");
}
}

const handleShortenUrl = async () => {
const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/;
Expand All @@ -49,7 +78,7 @@ const MainContentSection = () => {

const shortenedUrl = generateShortenedUrl(alias);

const link = "https://l.mlsctiet.com"
const link = "http://localhost:4000"

// api call to add link in the backend
const raw = JSON.stringify({
Expand Down Expand Up @@ -162,6 +191,24 @@ const MainContentSection = () => {
onChange={(e) => setAlias(e.target.value)}
/>
</Grid>
<Grid item xs={12} sx={{ pt: { xs: 32, md: 16 }, pl: 16 }}>
<TextField
label="email"
variant="outlined"
fullWidth
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</Grid>
<Grid item xs={12} sx={{ pt: { xs: 32, md: 16 }, pl: 16 }}>
<TextField
label="password"
variant="outlined"
fullWidth
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</Grid>
<Grid item xs={12} sx={{ pt: { xs: 32, md: 16 }, pl: 16 }}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
Expand Down Expand Up @@ -214,6 +261,11 @@ const MainContentSection = () => {
Shorten URL
</Button>
</Grid>
<Grid item xs={12}>
<Button variant="contained" color="primary" onClick={registerUser}>
Register
</Button>
</Grid>
{shortenedUrl && (
<Grid item xs={12}>
Shortened URL:{" "}
Expand Down
Loading

0 comments on commit 9aa77b2

Please sign in to comment.