-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
teacherModel.go
154 lines (135 loc) · 4.74 KB
/
teacherModel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package models
import (
"context"
"math/rand"
"os"
"strconv"
"strings"
"time"
"unicode"
"github.com/SowinskiBraeden/school-management-api/database"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"golang.org/x/crypto/bcrypt"
)
var (
lowerCharSet = "abcdedfghijklmnopqrst"
upperCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
specialCharSet = "!@#$%&*?,.`~"
numberSet = "0123456789"
allCharSet = lowerCharSet + upperCharSet + specialCharSet + numberSet
)
var TeacherCollection *mongo.Collection = database.OpenCollection(database.Client, "teachers")
type Teacher struct {
ID primitive.ObjectID `bson:"_id"`
Personal struct {
FirstName string `json:"firstname" validate:"required"`
MiddleName string `json:"middlename"`
LastName string `json:"lastname" validate:"required"`
Email string `json:"email" validate:"required"`
Address string `json:"address"`
City string `json:"city"`
Province string `json:"province"`
Postal string `json:"postal"`
DOB string `json:"dob" validate:"required"`
} `json:"personal"`
School struct {
TID string `json:"tid"` // Teacher ID
Homeroom string `json:"homeroom"`
PhotoName string `json:"photoname"` // name of photo in db
} `json:"School"`
Account struct {
VerifiedEmail bool `json:"verifiedemail"`
SchoolEmail string `json:"schoolemail"`
Password string `json:"-" validate:"min=10,max=32"`
AccountDisabled bool `bson:"accountdisabled"`
TempPassword bool `json:"temppassword"`
Attempts int `json:"attempts"` // login attempts max 5
HashHistory []string `json:"-"` // List of old hashed passwords (not including auto generated passwords)
} `json:"Account"`
Created_at time.Time `json:"created_at"`
Updated_at time.Time `json:"updated_at"`
}
func (t *Teacher) UsedPassword(password string) bool {
for _, oldHash := range t.Account.HashHistory {
if oldHash == t.HashPassword(password) {
return true
}
}
return false
}
func (t *Teacher) HashPassword(password string) string {
hash, _ := bcrypt.GenerateFromPassword([]byte(password), 14)
return string(hash)
}
func (t *Teacher) EmailExists(email string) bool {
var teacher Teacher
findErr := TeacherCollection.FindOne(context.TODO(), bson.M{"account.schoolemail": email}).Decode(&teacher)
return findErr == nil
}
func (t *Teacher) GenerateSchoolEmail(offset int, lastEmail string) string {
addr := os.Getenv("SYSTEM_EMAIL_ADDRESS")
var email string = strings.ToLower(t.Personal.LastName) + "_" + strings.ToLower(string(t.Personal.FirstName[0])) + addr
if offset > 0 && offset < len([]rune(t.Personal.FirstName))-1 {
email = lastEmail[:strings.Index(lastEmail, "_")+offset+1] + strings.ToLower(string(t.Personal.FirstName[offset])) + addr
}
if offset == len([]rune(t.Personal.FirstName))-1 {
email = strings.ToLower(t.Personal.LastName) + "_" + strings.ToLower(t.Personal.FirstName) + addr
}
if offset > len([]rune(t.Personal.FirstName))-1 {
email = strings.ToLower(t.Personal.LastName) + "_" + strings.ToLower(t.Personal.FirstName) + strconv.Itoa(offset-len([]rune(t.Personal.FirstName))) + addr
}
return email
}
func (t *Teacher) ComparePasswords(password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(t.Account.Password), []byte(password))
return err == nil
}
func (t *Teacher) CheckPasswordStrength(password string) bool {
var hasUpper bool = false
for _, r := range password {
if unicode.IsUpper(r) && unicode.IsLetter(r) {
hasUpper = true
}
}
var hasLower bool = false
for _, r := range password {
if unicode.IsLower(r) && unicode.IsLetter(r) {
hasLower = true
}
}
if strings.ContainsAny(password, specialCharSet) && hasLower && hasUpper && len(password) >= 8 {
return true
} else {
return false
}
}
func (t *Teacher) GeneratePassword(passwordLength, minSpecialChar, minNum, minUpperCase int) string {
var password strings.Builder
//Set special character
for i := 0; i < minSpecialChar; i++ {
random := rand.Intn(len(specialCharSet))
password.WriteString(string(specialCharSet[random]))
}
//Set numeric
for i := 0; i < minNum; i++ {
random := rand.Intn(len(numberSet))
password.WriteString(string(numberSet[random]))
}
//Set uppercase
for i := 0; i < minUpperCase; i++ {
random := rand.Intn(len(upperCharSet))
password.WriteString(string(upperCharSet[random]))
}
remainingLength := passwordLength - minSpecialChar - minNum - minUpperCase
for i := 0; i < remainingLength; i++ {
random := rand.Intn(len(allCharSet))
password.WriteString(string(allCharSet[random]))
}
inRune := []rune(password.String())
rand.Shuffle(len(inRune), func(i, j int) {
inRune[i], inRune[j] = inRune[j], inRune[i]
})
return string(inRune)
}