Skip to content

Commit 0cd6b7b

Browse files
authored
Merge pull request #24 from csesoc/feat/API
Backend draft
2 parents be9901a + 4d0eada commit 0cd6b7b

File tree

7 files changed

+651
-1
lines changed

7 files changed

+651
-1
lines changed

server/category.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
7+
"go.mongodb.org/mongo-driver/bson"
8+
"go.mongodb.org/mongo-driver/mongo"
9+
)
10+
11+
// GetCat - Retrieve a category from the database
12+
func GetCat(collection *mongo.Collection, id int, token string) *Category {
13+
if !validToken(token) {
14+
return nil
15+
}
16+
17+
var result *Category
18+
filter := bson.D{{"categoryID", id}}
19+
20+
// Find a category
21+
err := collection.FindOne(context.TODO(), filter).Decode(&result)
22+
if err != nil {
23+
log.Fatal(err)
24+
}
25+
26+
return result
27+
}
28+
29+
// NewCat - Add a new category
30+
func NewCat(collection *mongo.Collection, catID int, index int, name string, token string) {
31+
if !validToken(token) {
32+
return
33+
}
34+
35+
category := Category{
36+
categoryID: catID,
37+
categoryName: name,
38+
index: index,
39+
}
40+
41+
_, err := collection.InsertOne(context.TODO(), category)
42+
if err != nil {
43+
log.Fatal(err)
44+
}
45+
}
46+
47+
// PatchCat - Update a category with new information
48+
func PatchCat(collection *mongo.Collection, catID int, name string, index int, token string) {
49+
if !validToken(token) {
50+
return
51+
}
52+
53+
filter := bson.D{{"categoryID", catID}}
54+
update := bson.D{
55+
{"$set", bson.D{
56+
{"categoryName", name},
57+
{"index", index},
58+
}},
59+
}
60+
61+
// Find a category by id and update it
62+
_, err := collection.UpdateOne(context.TODO(), filter, update)
63+
if err != nil {
64+
log.Fatal(err)
65+
}
66+
}
67+
68+
// DeleteCat - Delete a category from the database
69+
func DeleteCat(collection *mongo.Collection, id int, token string) {
70+
if !validToken(token) {
71+
return
72+
}
73+
74+
filter := bson.D{{"categoryID", id}}
75+
76+
// Find a category by id and delete it
77+
_, err := collection.DeleteOne(context.TODO(), filter)
78+
if err != nil {
79+
log.Fatal(err)
80+
}
81+
}

server/go.mod

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,18 @@ module csesoc.unsw.edu.au/m/v2
22

33
go 1.13
44

5-
require github.com/labstack/echo/v4 v4.1.10 // indirect
5+
require (
6+
github.com/dgrijalva/jwt-go v3.2.0+incompatible
7+
github.com/go-stack/stack v1.8.0 // indirect
8+
github.com/golang/snappy v0.0.1 // indirect
9+
github.com/google/go-cmp v0.3.1 // indirect
10+
github.com/google/uuid v1.1.1
11+
github.com/labstack/echo/v4 v4.1.10
12+
github.com/tidwall/pretty v1.0.0 // indirect
13+
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
14+
github.com/xdg/stringprep v1.0.0 // indirect
15+
go.mongodb.org/mongo-driver v1.1.2
16+
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
17+
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
18+
gopkg.in/ldap.v2 v2.5.1
19+
)

server/go.sum

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
12
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
24
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
5+
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
6+
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
7+
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
8+
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
9+
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
10+
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
11+
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
12+
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
313
github.com/labstack/echo/v4 v4.1.10 h1:/yhIpO50CBInUbE/nHJtGIyhBv0dJe2cDAYxc3V3uMo=
414
github.com/labstack/echo/v4 v4.1.10/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
515
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
@@ -9,23 +19,40 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
919
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
1020
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
1121
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
22+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1223
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1324
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
25+
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
1426
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
27+
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
28+
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
1529
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
1630
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
1731
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
1832
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
33+
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
34+
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
35+
github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
36+
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
37+
go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA=
38+
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
1939
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
2040
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
2141
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
2242
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
2343
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
44+
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
45+
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
2446
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
2547
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
2648
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2749
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2850
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
2951
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
52+
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
53+
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
3054
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
55+
gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU=
56+
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
57+
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
3158
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

server/login.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"crypto/sha256"
6+
"log"
7+
"time"
8+
9+
"github.com/dgrijalva/jwt-go"
10+
"go.mongodb.org/mongo-driver/bson"
11+
"go.mongodb.org/mongo-driver/mongo"
12+
"gopkg.in/ldap.v2"
13+
)
14+
15+
var jwtKey = []byte("secret_text")
16+
17+
// Auth - to login
18+
func Auth(collection *mongo.Collection, zid string, password string, permissions string) string {
19+
// Connect to UNSW LDAP server
20+
l, err := ldap.Dial("tcp", "ad.unsw.edu.au")
21+
if err != nil {
22+
log.Fatal(err)
23+
}
24+
25+
// Attempt to sign in using credentials
26+
hashedZID := sha256.Sum256([]byte(zid))
27+
stringZID := string(hashedZID[:])
28+
username := zid + "ad.unsw.edu.au"
29+
30+
err = l.Bind(username, password)
31+
if err != nil {
32+
log.Fatal(err)
33+
}
34+
35+
// Retrieve first name from Identity Manager
36+
baseDN := "OU=IDM_People,OU=IDM,DC=ad,DC=unsw,DC=edu,DC=au"
37+
searchScope := ldap.ScopeWholeSubtree
38+
aliases := ldap.NeverDerefAliases
39+
retrieveAttributes := []string{"givenName"}
40+
searchFilter := "cn=" + username //cn = common name
41+
42+
searchRequest := ldap.NewSearchRequest(
43+
baseDN, searchScope, aliases, 0, 0, false,
44+
searchFilter, retrieveAttributes, nil,
45+
)
46+
47+
searchResult, err := l.Search(searchRequest)
48+
if err != nil {
49+
log.Fatal(err)
50+
}
51+
52+
// Encode user details into a JWT and turn it into a string
53+
54+
userFound := searchResult.Entries[0]
55+
expirationTime := time.Now().Add(time.Hour * 24)
56+
claims := &Claims{
57+
hashedZID: hashedZID,
58+
firstName: userFound.GetAttributeValue("firstName"),
59+
permissions: permissions,
60+
StandardClaims: jwt.StandardClaims{
61+
ExpiresAt: expirationTime.Unix(),
62+
},
63+
}
64+
tokenJWT := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
65+
tokenString, _ := tokenJWT.SignedString(jwtKey)
66+
67+
// Insert a new user into the collection if user has never logged in before
68+
// Or update the existing token if it has expired
69+
user := User{
70+
userID: stringZID,
71+
userToken: tokenString,
72+
role: "user", // Change this???
73+
}
74+
75+
var isValidUser *User
76+
userFilter := bson.D{{"userID", stringZID}}
77+
err = collection.FindOne(context.TODO(), userFilter).Decode(&isValidUser)
78+
79+
if isValidUser == nil { // Never logged in before
80+
_, err = collection.InsertOne(context.TODO(), user)
81+
if err != nil {
82+
log.Fatal(err)
83+
}
84+
} else { // Logged in before - check validity of token
85+
claims = &Claims{}
86+
decodedToken, _ := jwt.ParseWithClaims(isValidUser.userToken, claims, func(token *jwt.Token) (interface{}, error) {
87+
return jwtKey, nil
88+
})
89+
decodedTokenString, _ := decodedToken.SignedString(jwtKey)
90+
91+
if !decodedToken.Valid { // Logged in before but token is invalid - replace with new token
92+
filter := bson.D{{"userID", stringZID}}
93+
update := bson.D{
94+
{"$set", bson.D{
95+
{"userToken", decodedTokenString},
96+
}},
97+
}
98+
_, err = collection.UpdateOne(context.TODO(), filter, update)
99+
if err != nil {
100+
log.Fatal(err)
101+
}
102+
}
103+
}
104+
105+
return tokenString
106+
}
107+
108+
// validToken - returns true if a token is valid and false otherwise.
109+
func validToken(tokenString string) bool {
110+
claims := &Claims{}
111+
tkn, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
112+
return jwtKey, nil
113+
})
114+
115+
if err != nil {
116+
if err == jwt.ErrSignatureInvalid {
117+
return false
118+
}
119+
}
120+
121+
if !tkn.Valid || claims.permissions != "staff" {
122+
return false
123+
}
124+
125+
return true
126+
}

0 commit comments

Comments
 (0)