Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
165c17cdd6 | ||
|
|
421943d5d4 | ||
|
|
8ee6c40bde | ||
|
|
c83f05674e | ||
|
|
e8c3272677 | ||
|
|
974c512cd1 | ||
|
|
f177e8cef7 | ||
|
|
55ca35034e | ||
|
|
2ef9c71f59 | ||
|
|
f402b27222 | ||
|
|
7bd33decc9 | ||
|
|
456dab3d6f | ||
|
|
27eb0937c7 | ||
|
|
eb065c4142 | ||
|
|
22d41d04dc | ||
|
|
dd0cd7d76c | ||
|
|
52e1c0fb5b | ||
|
|
f8ff2cf90e | ||
|
|
66112d4158 | ||
|
|
39400b371a | ||
|
|
9d44f98ff1 | ||
|
|
c054e3f065 | ||
|
|
b708f1d815 | ||
|
|
471d1c94a0 | ||
|
|
f37e677dbf |
No files matched your search
@@ -0,0 +1,203 @@
|
||||
# School Management API Documentation
|
||||
|
||||
The School Management API Documentation, defining all functions and their purpose. As well as how to use the API, how to properly call functions and provide the necessary fields.
|
||||
|
||||
### Contents
|
||||
|
||||
* [Getting Started](#getting-started)
|
||||
* [General Functions](#general-functions)
|
||||
* [Creating Accounts](#creating-accounts)
|
||||
* [Log into Accounts](#log-into-accounts)
|
||||
* [Updating Account information](#updating-accounts)
|
||||
|
||||
<br>
|
||||
|
||||
## Getting Started
|
||||
|
||||
* ### Installation & Deployment
|
||||
The API is an all in one package and is simple and easy to deploy. Eliminating any long unforgiving configurations you may face in other software.
|
||||
|
||||
1. Clone the repo
|
||||
```
|
||||
$ git clone https://github.com/SowinskiBraeden/school-management-api
|
||||
$ cd school-management-api
|
||||
```
|
||||
|
||||
2. Rename `.env.example` to `.env`
|
||||
|
||||
3. Enter desired values into `.env`
|
||||
```
|
||||
mongoURI='your mongo URI'
|
||||
dbo='school'
|
||||
secret='your 256 bit secret'
|
||||
|
||||
# Suggested port for Production: 80
|
||||
# Suggested port for Development: 8000
|
||||
PORT='desired port'
|
||||
|
||||
# This is to enable the system to send emails
|
||||
SYSTEM_EMAIL='your system email'
|
||||
SYSTEM_PASSWORD='your system email password'
|
||||
```
|
||||
|
||||
4. Run the system in your terminal
|
||||
```
|
||||
$ go run main.go
|
||||
```
|
||||
|
||||
Or...
|
||||
|
||||
5. Build and compile the system into an executable
|
||||
```
|
||||
$ go build
|
||||
```
|
||||
|
||||
* ### Initializing the System
|
||||
|
||||
Upon running the system for the first time, you will be prompted to create an admin.
|
||||
In order to perform many actions with the API, an Admin account is required. You will be prompted to create your default admin account seen below...
|
||||
|
||||

|
||||
|
||||
Upon completing the initial setup and creating your default administrator for the system, it is ready to use and this box will appear below, displaying basic system details seen below...
|
||||
|
||||

|
||||
|
||||
<br>
|
||||
|
||||
## General Functions
|
||||
|
||||
* ### API Status
|
||||
**Method:** `GET`
|
||||
```
|
||||
<API_URL>/api/v1/status
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```
|
||||
{
|
||||
"success": true,
|
||||
"message": "the API is active"
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Creating Accounts
|
||||
|
||||
There are several account that can be registered into the system. As you may guess they are Administrators, Teachers and Students.
|
||||
|
||||
<br>
|
||||
|
||||
+ ### Creating Administrators
|
||||
You can create Administratos who will have permissions to perform majority of the actions in the API. It is common that there are more than one Administrator to help manage the system.
|
||||
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/admin/create
|
||||
```
|
||||
|
||||
**Required:**
|
||||
+ Logged into an existing Admin account
|
||||
+ JSON:
|
||||
```
|
||||
{
|
||||
"firstname": "John",
|
||||
"lastname": "Doe",
|
||||
"dob": "01-01-1999",
|
||||
"email": "john_doe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
+ Status 200: `OK`
|
||||
+ JSON:
|
||||
```
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully inserted admin"
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
+ ### Registering a Teacher
|
||||
Obviosuly a school management system will require teachers to manage and teach students. Teachers have an important role for the system.
|
||||
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/teacher/register
|
||||
```
|
||||
|
||||
**Required:**
|
||||
+ Logged into an existing Admin account
|
||||
+ JSON:
|
||||
```
|
||||
{
|
||||
"firstname": "Homer",
|
||||
"middlename": "Jay",
|
||||
"lastname": "Simson",
|
||||
"dob": "12-05-1956",
|
||||
"email": "homerdog_simpson@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
+ Status 200: `OK`
|
||||
+ JSON:
|
||||
```
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully inserted teacher"
|
||||
}
|
||||
```
|
||||
|
||||
+ ### Enrolling a Student
|
||||
What is a school withouth students? A professional day, but not the point. Students when their application to the school has been accepted by an admin can be enrolled into the school.
|
||||
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/student/enroll
|
||||
```
|
||||
|
||||
**Required:**
|
||||
+ Logged into an existing Admin account
|
||||
+ JSON:
|
||||
```
|
||||
{
|
||||
"firstname": "Bart",
|
||||
"middlename": "JoJo",
|
||||
"lastname": "Simpson",
|
||||
"age": 10,
|
||||
"gradelevel": 4,
|
||||
"dob": "17-12-1979",
|
||||
"province": "...",
|
||||
"city": "Springfield",
|
||||
"address": "742 Evergreen Terrace",
|
||||
"postal": "..."
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
+ Status 200: `OK`
|
||||
+ JSON:
|
||||
```
|
||||
{
|
||||
"success": true,
|
||||
"successfully inserted student"
|
||||
}
|
||||
```
|
||||
+ ### Additional Information After creating an account
|
||||
1. After successfully creating an account for another admin, teacher or student. A school email will be generated for them using their first and last name, each formated differently based on the type of account.
|
||||
|
||||
2. All users are given a random ID used to sign into the system. Each ID is a random 6 digit number.
|
||||
|
||||
3. Students are given a random PEN (Personal Education Number). A random 12 digit number.
|
||||
|
||||
4. Accounts are given a defaul profile image. This can be updated in the future.
|
||||
|
||||
5. All new users, once have verified their email, will recieve and email containing their ID.
|
||||
|
||||
6. All new users, once have verified their email, will recieve and email containing their temporary password.
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
The backend API for a school management system accessible by staff and students.
|
||||
|
||||
<a href="https://github.com/SowinskiBraeden/school-management-api"><strong>Explore the docs »</strong></a>
|
||||
***Explore the docs »***
|
||||
* [Getting Started](#getting-started)
|
||||
* [Usage/Documenation](#usage)
|
||||
* [Contributing](#contributing)
|
||||
* [License](#license)
|
||||
* [Contact](#contact)
|
||||
<br>
|
||||
<br>
|
||||
|
||||
@@ -82,6 +87,8 @@ The systems is easy to start and your local machine. Eliminating any long unforg
|
||||
|
||||
The usage for this API is in the name, school management, it's not an easy task in the areas I live near. Overcrowded schools are far too common and the need for a better school management system is there. The current systems issued by the government work but are poor and outdated.
|
||||
|
||||
To see a full list of features and how to use the system, read the [documentation](DOCUMENTATION.md)
|
||||
|
||||
|
||||
<!-- CONTRIBUTING -->
|
||||
## Contributing
|
||||
|
||||
+171
-101
@@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -12,10 +13,8 @@ import (
|
||||
"github.com/SowinskiBraeden/school-management-api/models"
|
||||
"github.com/howeyc/gopass"
|
||||
|
||||
"net/smtp"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
@@ -27,6 +26,67 @@ var studentCollection *mongo.Collection = database.OpenCollection(database.Clien
|
||||
var contactCollection *mongo.Collection = database.OpenCollection(database.Client, "contacts")
|
||||
var adminCollection *mongo.Collection = database.OpenCollection(database.Client, "admins")
|
||||
|
||||
func confirm(s string) bool {
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
|
||||
fmt.Printf("%s [y/n]: ", s)
|
||||
res, err := r.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return strings.ToLower(strings.TrimSpace(res))[0] == 'y'
|
||||
}
|
||||
|
||||
func CreateDefaultAdmin() models.Admin {
|
||||
fmt.Println()
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Print("First Name: ")
|
||||
firstname, _ := reader.ReadString('\n')
|
||||
fmt.Print("Last Name: ")
|
||||
lastname, _ := reader.ReadString('\n')
|
||||
fmt.Print("Email: ")
|
||||
email, _ := reader.ReadString('\n')
|
||||
fmt.Print("Password: ")
|
||||
password, _ := gopass.GetPasswd()
|
||||
|
||||
// Clear values of new lines and enter characters
|
||||
firstname = strings.ReplaceAll(firstname, "\n", "")
|
||||
lastname = strings.ReplaceAll(lastname, "\n", "")
|
||||
email = strings.ReplaceAll(email, "\n", "")
|
||||
firstname = strings.ReplaceAll(firstname, "\r", "")
|
||||
lastname = strings.ReplaceAll(lastname, "\r", "")
|
||||
email = strings.ReplaceAll(email, "\r", "")
|
||||
|
||||
var admin models.Admin
|
||||
admin.FirstName = firstname
|
||||
admin.LastName = lastname
|
||||
admin.Email = email
|
||||
|
||||
temp := admin.GenerateSchoolEmail()
|
||||
fmt.Println(temp)
|
||||
admin.SchoolEmail = temp
|
||||
|
||||
pass := strings.TrimSuffix(string(password), "\n")
|
||||
admin.Password = admin.HashPassword(pass)
|
||||
admin.TempPassword = false
|
||||
|
||||
var aid string
|
||||
for {
|
||||
aid = GenerateID(6)
|
||||
if ValidateID(aid, 3) == true {
|
||||
break
|
||||
}
|
||||
}
|
||||
admin.AID = aid
|
||||
|
||||
admin.Created_at, _ = time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
admin.Updated_at, _ = time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
admin.ID = primitive.NewObjectID()
|
||||
|
||||
return admin
|
||||
}
|
||||
|
||||
func NewSystem() {
|
||||
count, err := adminCollection.CountDocuments(context.Background(), bson.D{})
|
||||
if err != nil {
|
||||
@@ -35,47 +95,21 @@ func NewSystem() {
|
||||
|
||||
if count == 0 {
|
||||
fmt.Println("Admin account setup...")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Print("First Name: ")
|
||||
firstname, _ := reader.ReadString('\n')
|
||||
fmt.Print("Last Name: ")
|
||||
lastname, _ := reader.ReadString('\n')
|
||||
fmt.Print("Email: ")
|
||||
email, _ := reader.ReadString('\n')
|
||||
fmt.Print("Password: ")
|
||||
password, _ := gopass.GetPasswd()
|
||||
|
||||
var admin models.Admin
|
||||
admin.FirstName = strings.TrimSuffix(firstname, "\n")
|
||||
admin.LastName = strings.TrimSuffix(lastname, "\n")
|
||||
admin.Email = strings.TrimSuffix(email, "\n")
|
||||
|
||||
admin.SchoolEmail = admin.GenerateSchoolEmail()
|
||||
|
||||
pass := strings.TrimSuffix(string(password), "\n")
|
||||
admin.Password = admin.HashPassword(pass)
|
||||
admin.TempPassword = false
|
||||
|
||||
var aid string
|
||||
for {
|
||||
aid = GenerateID(6)
|
||||
if ValidateID(aid) == true {
|
||||
defaultAdmin := CreateDefaultAdmin()
|
||||
|
||||
if confirm("Are the above credentials correct?") {
|
||||
_, insertErr := adminCollection.InsertOne(context.Background(), defaultAdmin)
|
||||
if insertErr != nil {
|
||||
log.Printf("Failed to create an admin\n")
|
||||
}
|
||||
|
||||
log.Printf("Successfully created default admin")
|
||||
log.Printf("Your default admin ID is %s", defaultAdmin.AID)
|
||||
break
|
||||
}
|
||||
}
|
||||
admin.AID = aid
|
||||
|
||||
admin.Created_at, _ = time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
admin.Updated_at, _ = time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
admin.ID = primitive.NewObjectID()
|
||||
|
||||
_, insertErr := adminCollection.InsertOne(context.Background(), admin)
|
||||
if insertErr != nil {
|
||||
fmt.Print("Failed to create admin")
|
||||
}
|
||||
|
||||
fmt.Println("Successfully created system admin")
|
||||
fmt.Println("Your admin ID is ", aid)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,29 +118,11 @@ var SecretKey = os.Getenv("secret")
|
||||
var systemEmail string = os.Getenv("SYSTEM_EMAIL")
|
||||
var systemPassword string = os.Getenv("SYSTEM_PASSWORD")
|
||||
|
||||
func AuthAdmin(c *fiber.Ctx) bool {
|
||||
cookie := c.Cookies("jwt")
|
||||
|
||||
token, err := jwt.ParseWithClaims(cookie, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(SecretKey), nil
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
func AuthenticateUser(c *fiber.Ctx, userType int) (bool, string) {
|
||||
if userType < 1 || userType > 3 {
|
||||
log.Fatal("Invalid userType")
|
||||
}
|
||||
|
||||
claims := token.Claims.(*jwt.StandardClaims)
|
||||
|
||||
// Though admin is not used, it's required to prevent findErr
|
||||
var admin models.Admin
|
||||
findErr := adminCollection.FindOne(context.TODO(), bson.M{"aid": claims.Issuer}).Decode(&admin)
|
||||
if findErr != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func AuthStudent(c *fiber.Ctx) (verified bool, sid string) {
|
||||
cookie := c.Cookies("jwt")
|
||||
|
||||
token, err := jwt.ParseWithClaims(cookie, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
@@ -118,14 +134,17 @@ func AuthStudent(c *fiber.Ctx) (verified bool, sid string) {
|
||||
|
||||
claims := token.Claims.(*jwt.StandardClaims)
|
||||
|
||||
// Though student is not used, it's required to prevent findErr
|
||||
var student models.Student
|
||||
findErr := studentCollection.FindOne(context.TODO(), bson.M{"sid": claims.Issuer}).Decode(&student)
|
||||
var userID models.Id
|
||||
findErr := idCollection.FindOne(context.TODO(), bson.M{"cid": claims.Issuer}).Decode(&userID)
|
||||
if findErr != nil {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
return true, claims.Issuer
|
||||
if userID.ParentType != userType {
|
||||
return false, ""
|
||||
}
|
||||
|
||||
return true, userID.CID
|
||||
}
|
||||
|
||||
func Enroll(c *fiber.Ctx) error {
|
||||
@@ -142,7 +161,7 @@ func Enroll(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -199,6 +218,7 @@ func Enroll(c *fiber.Ctx) error {
|
||||
|
||||
// Disable login block
|
||||
student.AccountData.AccountDisabled = false
|
||||
student.AccountData.Alerted = false
|
||||
student.AccountData.Attempts = 0
|
||||
|
||||
// Generate temporary password
|
||||
@@ -207,23 +227,22 @@ func Enroll(c *fiber.Ctx) error {
|
||||
student.AccountData.TempPassword = true
|
||||
|
||||
// Send student personal email temp password
|
||||
message := []byte("Your temporary password is " + tempPass)
|
||||
auth := smtp.PlainAuth("", systemEmail, systemPassword, "smtp.gmail.com")
|
||||
subject := "Password Changed"
|
||||
receiver := student.PersonalData.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
err := smtp.SendMail("smtp.gmail.com:587", auth, systemEmail, []string{student.PersonalData.Email}, message)
|
||||
if err != nil {
|
||||
if sent := r.Send("./templates/passwordChanged.html", map[string]string{"username": student.PersonalData.FirstName, "password": tempPass}); !sent {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Could not send password to students email",
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
|
||||
var sid string
|
||||
for {
|
||||
sid = GenerateID(6)
|
||||
if ValidateID(sid) == true {
|
||||
if ValidateID(sid, 1) == true {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -283,7 +302,7 @@ func RegisterTeacher(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -342,16 +361,15 @@ func RegisterTeacher(c *fiber.Ctx) error {
|
||||
teacher.AccountData.TempPassword = true
|
||||
|
||||
// Send teacher personal email temp password
|
||||
message := []byte("Your temporary password is " + tempPass)
|
||||
auth := smtp.PlainAuth("", systemEmail, systemPassword, "smtp.gmail.com")
|
||||
subject := "Password Changed"
|
||||
receiver := teacher.PersonalData.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
err := smtp.SendMail("smtp.gmail.com:587", auth, systemEmail, []string{teacher.PersonalData.Email}, message)
|
||||
if err != nil {
|
||||
if sent := r.Send("./templates/passwordChanged.html", map[string]string{"username": teacher.PersonalData.FirstName, "password": tempPass}); !sent {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Could not send password to teacners email",
|
||||
"error": err,
|
||||
"message": "Could not send password to teachers email",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -359,7 +377,7 @@ func RegisterTeacher(c *fiber.Ctx) error {
|
||||
// For the unlikely event that an ID is already in use this will simply try again till it gets a id not in use
|
||||
for {
|
||||
tid = GenerateID(6)
|
||||
isValid := ValidateID(tid)
|
||||
isValid := ValidateID(tid, 2)
|
||||
if isValid == true {
|
||||
break
|
||||
}
|
||||
@@ -401,7 +419,7 @@ func CreateAdmin(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -430,23 +448,22 @@ func CreateAdmin(c *fiber.Ctx) error {
|
||||
admin.TempPassword = true
|
||||
|
||||
// Send admin personal email temp password
|
||||
message := []byte("Your temporary password is " + tempPass)
|
||||
auth := smtp.PlainAuth("", systemEmail, systemPassword, "smtp.gmail.com")
|
||||
subject := "Password Changed"
|
||||
receiver := admin.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
err := smtp.SendMail("smtp.gmail.com:587", auth, systemEmail, []string{admin.Email}, message)
|
||||
if err != nil {
|
||||
if sent := r.Send("./templates/passwordChanged.html", map[string]string{"username": admin.FirstName, "password": tempPass}); !sent {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Could not send password to admins email",
|
||||
"error": err,
|
||||
"message": "Could not send password to students email",
|
||||
})
|
||||
}
|
||||
|
||||
var aid string
|
||||
for {
|
||||
aid = GenerateID(6)
|
||||
if ValidateID(aid) == true {
|
||||
if ValidateID(aid, 3) == true {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -497,7 +514,6 @@ func StudentLogin(c *fiber.Ctx) error {
|
||||
|
||||
var student models.Student
|
||||
err := studentCollection.FindOne(ctx, bson.M{"schooldata.sid": data["sid"]}).Decode(&student)
|
||||
defer cancel()
|
||||
|
||||
if err != nil {
|
||||
cancel()
|
||||
@@ -508,21 +524,29 @@ func StudentLogin(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
var localAccountDisabled = false
|
||||
if student.AccountData.Attempts >= 5 {
|
||||
var verified bool = student.ComparePasswords(data["password"])
|
||||
var localAccountDisabled bool = false
|
||||
var localAttempts int = student.AccountData.Attempts
|
||||
|
||||
if !verified {
|
||||
localAttempts += 1
|
||||
}
|
||||
|
||||
if student.AccountData.Attempts >= 5 || localAttempts >= 5 {
|
||||
localAccountDisabled = true // Catches newly disbaled account before student obj is updated
|
||||
update_time, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"AccountData.accountdisabled": true,
|
||||
"AccountData.attempts": 0,
|
||||
"accountdata.accountdisabled": true,
|
||||
"accountdata.alerted": true,
|
||||
"accountdata.attempts": 0,
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
|
||||
_, updateErr := studentCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"sid": data["sid"]},
|
||||
bson.M{"schooldata.sid": data["sid"]},
|
||||
update,
|
||||
)
|
||||
if updateErr != nil {
|
||||
@@ -536,26 +560,42 @@ func StudentLogin(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
if localAccountDisabled || student.AccountData.AccountDisabled {
|
||||
|
||||
if !student.AccountData.Alerted {
|
||||
// Send student email warning of disabled account
|
||||
subject := "Account Disabled"
|
||||
receiver := student.PersonalData.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
if sent := r.Send("./templates/accountDisabled.html", map[string]string{"username": student.PersonalData.FirstName}); !sent {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Could not send password to students email",
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
}
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Account is Disabled, contact an Admin",
|
||||
})
|
||||
}
|
||||
|
||||
var verified bool = student.ComparePasswords(data["password"])
|
||||
if verified == false {
|
||||
if !verified {
|
||||
update_time, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"AccountData.attempts": student.AccountData.Attempts + 1,
|
||||
"accountdata.attempts": (student.AccountData.Attempts + 1),
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
|
||||
_, updateErr := studentCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"sid": data["sid"]},
|
||||
bson.M{"schooldata.sid": data["sid"]},
|
||||
update,
|
||||
)
|
||||
cancel()
|
||||
@@ -566,10 +606,33 @@ func StudentLogin(c *fiber.Ctx) error {
|
||||
"error": updateErr,
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "incorrect password",
|
||||
})
|
||||
} else {
|
||||
update_time, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"accountdata.attempts": 0,
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
|
||||
_, updateErr := studentCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.sid": data["sid"]},
|
||||
update,
|
||||
)
|
||||
if updateErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "the student could not be updated",
|
||||
"error": updateErr,
|
||||
})
|
||||
}
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
@@ -741,7 +804,7 @@ func AdminLogin(c *fiber.Ctx) error {
|
||||
|
||||
func Student(c *fiber.Ctx) error {
|
||||
var sid string
|
||||
if AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); verified {
|
||||
var data map[string]string
|
||||
|
||||
if err := c.BodyParser(&data); err != nil {
|
||||
@@ -793,6 +856,13 @@ func Student(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
if student.AccountData.AccountDisabled {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Student Accound Disabled, Contact and Admin",
|
||||
})
|
||||
}
|
||||
|
||||
responseData["student"] = student
|
||||
|
||||
var locker models.Locker
|
||||
@@ -919,7 +989,7 @@ func CreateContact(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1004,7 +1074,7 @@ func DeleteContact(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/SowinskiBraeden/school-management-api/database"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
var courseCollection *mongo.Collection = database.OpenCollection(database.Client, "courses")
|
||||
|
||||
func CreateCourse(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusNotImplemented).JSON(fiber.Map{
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteCourse(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusNotImplemented).JSON(fiber.Map{
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateCourseCode(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusNotImplemented).JSON(fiber.Map{
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateCourseName(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusNotImplemented).JSON(fiber.Map{
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateCourseCredit(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusNotImplemented).JSON(fiber.Map{
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateCourseGradelevel(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusNotImplemented).JSON(fiber.Map{
|
||||
"success": true,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/smtp"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server string
|
||||
Port int
|
||||
Email string
|
||||
Password string
|
||||
}
|
||||
|
||||
var config Config = Config{
|
||||
Server: "smtp.gmail.com",
|
||||
Port: 587,
|
||||
Email: os.Getenv("SYSTEM_EMAIL"),
|
||||
Password: os.Getenv("SYSTEM_PASSWORD"),
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
from string
|
||||
to []string
|
||||
subject string
|
||||
body string
|
||||
}
|
||||
|
||||
const (
|
||||
MIME = "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
|
||||
)
|
||||
|
||||
func NewRequest(to []string, subject string) *Request {
|
||||
return &Request{
|
||||
to: to,
|
||||
subject: subject,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Request) parseTemplate(fileName string, data interface{}) error {
|
||||
t, err := template.ParseFiles(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buffer := new(bytes.Buffer)
|
||||
if err = t.Execute(buffer, data); err != nil {
|
||||
return err
|
||||
}
|
||||
r.body = buffer.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Request) sendMail() bool {
|
||||
body := "To: " + r.to[0] + "\r\nSubject: " + r.subject + "\r\n" + MIME + "\r\n" + r.body
|
||||
SMTP := fmt.Sprintf("%s:%d", config.Server, config.Port)
|
||||
if err := smtp.SendMail(SMTP, smtp.PlainAuth("", config.Email, config.Password, config.Server), config.Email, r.to, []byte(body)); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Request) Send(templateName string, items interface{}) bool {
|
||||
err := r.parseTemplate(templateName, items)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return false
|
||||
}
|
||||
if ok := r.sendMail(); ok {
|
||||
log.Printf("Email has been sent to %s\n", r.to)
|
||||
return true
|
||||
} else {
|
||||
log.Printf("Failed to send the email to %s\n", r.to)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ var idCollection *mongo.Collection = database.OpenCollection(database.Client, "c
|
||||
|
||||
var table = [...]byte{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}
|
||||
|
||||
func ValidateID(id string) bool { // true: valid id, false: id already in use
|
||||
func ValidateID(id string, userType int) bool { // true: valid id, false: id already in use
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
var foundID models.Id
|
||||
err := idCollection.FindOne(ctx, bson.M{"cid": id}).Decode(&foundID)
|
||||
@@ -26,6 +26,7 @@ func ValidateID(id string) bool { // true: valid id, false: id already in use
|
||||
if err != nil { // If there is no id found create new ID object to be stored and return true (unless insert error then try again)
|
||||
var newID models.Id
|
||||
newID.CID = id
|
||||
newID.ParentType = userType
|
||||
newID.ID = primitive.NewObjectID()
|
||||
_, insertErr := idCollection.InsertOne(context.Background(), newID)
|
||||
if insertErr != nil {
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/smtp"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -13,11 +12,10 @@ import (
|
||||
"github.com/SowinskiBraeden/school-management-api/database"
|
||||
"github.com/SowinskiBraeden/school-management-api/models"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
@@ -42,7 +40,7 @@ func UpdateStudentName(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -122,7 +120,7 @@ func UpdateStudentGradeLevel(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authorized admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -194,7 +192,7 @@ func UpdateStudentHomeroom(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -339,6 +337,18 @@ func UpdateStudentPassword(c *fiber.Ctx) error {
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
// Alert email the password has changed
|
||||
subject := "Password Changed"
|
||||
receiver := student.PersonalData.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
if sent := r.Send("./templates/selfPasswordChanged.html", map[string]string{"username": student.PersonalData.FirstName}); !sent {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "failed to send email to student",
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated student password",
|
||||
@@ -413,16 +423,14 @@ func ResetStudentPassword(c *fiber.Ctx) error {
|
||||
defer cancel()
|
||||
|
||||
// Send student personal email temp password
|
||||
message := []byte("Your temporary password is " + tempPass)
|
||||
auth := smtp.PlainAuth("", systemEmail, systemPassword, "smtp.gmail.com")
|
||||
subject := "Password Changed"
|
||||
receiver := student.PersonalData.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
err := smtp.SendMail("smtp.gmail.com:587", auth, systemEmail, []string{student.PersonalData.Email}, message)
|
||||
if err != nil {
|
||||
cancel()
|
||||
if sent := r.Send("./templates/passwordChanged.html", map[string]string{"username": student.PersonalData.FirstName, "password": tempPass}); !sent {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Could not send password to students email",
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -447,7 +455,7 @@ func UpdateStudentLocker(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -519,7 +527,7 @@ func UpdateStudentAddress(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -584,7 +592,7 @@ func UpdateStudentYOG(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -655,7 +663,7 @@ func RemoveStudentContact(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -729,7 +737,7 @@ func AddStudentContact(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -793,7 +801,7 @@ func UpdateStudentPhoto(c *fiber.Ctx) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
|
||||
//Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -919,8 +927,8 @@ func UpdateStudentEmail(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
verifiedAdmin := AuthAdmin(c)
|
||||
verifiedStudent, sid := AuthStudent(c)
|
||||
verifiedAdmin, _ := AuthenticateUser(c, 3)
|
||||
verifiedStudent, sid := AuthenticateUser(c, 1)
|
||||
// Ensure Authenticated admin sent request
|
||||
if !verifiedAdmin && !verifiedStudent {
|
||||
cancel()
|
||||
@@ -983,7 +991,7 @@ func RemoveStudentsDisabled(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authorized admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1004,6 +1012,7 @@ func RemoveStudentsDisabled(c *fiber.Ctx) error {
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"accountdata.accountdisabled": false,
|
||||
"accountdata.alerted": false,
|
||||
"accountdata.attempts": 0,
|
||||
"updated_at": update_time,
|
||||
},
|
||||
@@ -1018,7 +1027,7 @@ func RemoveStudentsDisabled(c *fiber.Ctx) error {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "the student account could not be re-enabled",
|
||||
"message": "the student account could not be enabled",
|
||||
"error": updateErr,
|
||||
})
|
||||
}
|
||||
@@ -1045,7 +1054,7 @@ func RemoveTeachersDisabled(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authorized admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1118,7 +1127,7 @@ func UpdateTeacherHomeroom(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1263,6 +1272,17 @@ func UpdateTeacherPassword(c *fiber.Ctx) error {
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
subject := "Password Changed"
|
||||
receiver := teacher.PersonalData.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
if sent := r.Send("./templates/selfPasswordChanged.html", map[string]string{"username": teacher.PersonalData.FirstName}); !sent {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Could not send password to teachers email",
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher password",
|
||||
@@ -1335,17 +1355,15 @@ func ResetTeacherPassword(c *fiber.Ctx) error {
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
// Send student personal email temp password
|
||||
message := []byte("Your temporary password is " + tempPass)
|
||||
auth := smtp.PlainAuth("", systemEmail, systemPassword, "smtp.gmail.com")
|
||||
// Send teacher personal email temp password
|
||||
subject := "Password Changed"
|
||||
receiver := teacher.PersonalData.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
err := smtp.SendMail("smtp.gmail.com:587", auth, systemEmail, []string{teacher.PersonalData.Email}, message)
|
||||
if err != nil {
|
||||
cancel()
|
||||
if sent := r.Send("./templates/passwordChanged.html", map[string]string{"username": teacher.PersonalData.FirstName, "password": tempPass}); !sent {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Could not send password to teachers email",
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1370,7 +1388,7 @@ func UpdateTeacherAddress(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1424,7 +1442,7 @@ func UpdateTeacherPhoto(c *fiber.Ctx) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
|
||||
//Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1441,7 +1459,7 @@ func UpdateTeacherPhoto(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
// Get student
|
||||
// Get teacher
|
||||
var teacher models.Teacher
|
||||
findErr := teacherCollection.FindOne(context.TODO(), bson.M{"schooldata.tid": tid}).Decode(&teacher)
|
||||
if findErr != nil {
|
||||
@@ -1551,7 +1569,7 @@ func UpdateTeacherEmail(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1612,7 +1630,7 @@ func UpdateTeacherName(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1621,7 +1639,7 @@ func UpdateTeacherName(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Check id and names are included
|
||||
if data["_id"] == "" || data["firstname"] == "" || data["middlename"] == "" || data["lastname"] == "" {
|
||||
if data["tid"] == "" || data["firstname"] == "" || data["lastname"] == "" {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1629,15 +1647,18 @@ func UpdateTeacherName(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
teacherObjectId, idErr := primitive.ObjectIDFromHex(data["_id"])
|
||||
if idErr != nil {
|
||||
// Get teacher
|
||||
var teacher models.Teacher
|
||||
findErr := teacherCollection.FindOne(ctx, bson.M{"schooldata.tid": data["tid"]}).Decode(&teacher)
|
||||
if findErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "teacher not found",
|
||||
"error": idErr,
|
||||
"message": "the teacher could not be found",
|
||||
"error": findErr,
|
||||
})
|
||||
}
|
||||
|
||||
update_time, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
@@ -1650,7 +1671,7 @@ func UpdateTeacherName(c *fiber.Ctx) error {
|
||||
|
||||
result, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": teacherObjectId},
|
||||
bson.M{"schooldata.tid": data["tid"]},
|
||||
update,
|
||||
)
|
||||
if updateErr != nil {
|
||||
@@ -1684,7 +1705,7 @@ func UpdateContactName(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1747,7 +1768,7 @@ func UpdateContactAddress(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1811,7 +1832,7 @@ func UpdateContactHomePhone(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1872,7 +1893,7 @@ func UpdateContactWorkPhone(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1933,7 +1954,7 @@ func UpdateContactEmail(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -1994,7 +2015,7 @@ func UpdateContactPriority(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -2055,7 +2076,7 @@ func UpdateLockerCombo(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -2116,7 +2137,7 @@ func RemoveStudent(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -2175,7 +2196,7 @@ func RemoveTeacher(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
@@ -2234,7 +2255,7 @@ func RemoveAdmin(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// Ensure Authenticated admin sent request
|
||||
if !AuthAdmin(c) {
|
||||
if verified, _ := AuthenticateUser(c, 3); !verified {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
|
||||
@@ -3,18 +3,17 @@ module github.com/SowinskiBraeden/school-management-api
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/gofiber/fiber/v2 v2.26.0
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible
|
||||
github.com/google/go-cmp v0.5.6 // indirect
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
github.com/valyala/fasthttp v1.34.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.7.2
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
@@ -1,11 +1,10 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
|
||||
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||
@@ -34,6 +33,8 @@ github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/V
|
||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||
github.com/gofiber/fiber/v2 v2.26.0 h1:Awnfqp3fqbZzV3wZWMRJ6Xo2U8X0Ls68M7tXjx52NcM=
|
||||
github.com/gofiber/fiber/v2 v2.26.0/go.mod h1:7efVWcBOZi1PyMWznnbitjnARPA7nYZxmQXJVod0bo0=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -50,8 +51,9 @@ github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx
|
||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s=
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U=
|
||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@@ -86,8 +88,9 @@ github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.32.0 h1:keswgWzyKyNIIjz2a7JmCYHOOIkRp6HMx9oTV6QrZWY=
|
||||
github.com/valyala/fasthttp v1.32.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
|
||||
github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4=
|
||||
github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
@@ -105,12 +108,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -128,10 +133,12 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
)
|
||||
|
||||
const version string = "\nv0.8.8-Alpha"
|
||||
const version string = "\nv1.0.0-Beta"
|
||||
|
||||
func main() {
|
||||
fmt.Println(version)
|
||||
|
||||
+3
-2
@@ -15,6 +15,7 @@ import (
|
||||
*/
|
||||
|
||||
type Id struct {
|
||||
ID primitive.ObjectID `bson:"_id"`
|
||||
CID string `bson:"cid"` // custom id for admin, teahcer or student
|
||||
ID primitive.ObjectID `bson:"_id"`
|
||||
CID string `json:"cid"` // custom id for admin, teahcer or student
|
||||
ParentType int `json:"parenttype"` // A number representing the user (1: student, 2: teacher, 3: admin)
|
||||
}
|
||||
@@ -48,6 +48,7 @@ type Student struct {
|
||||
SchoolEmail string `json:"schoolemail"`
|
||||
Password string `json:"-" validate:"min=10,max=32"`
|
||||
AccountDisabled bool `bson:"accountdisabled"`
|
||||
Alerted bool `bson:"alerted"`
|
||||
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)
|
||||
|
||||
+2
-2
@@ -74,8 +74,8 @@ func Setup(app *fiber.App) {
|
||||
|
||||
// General Command Handling
|
||||
app.Post(routerPrefix+"/admin/updateLockerCombo", controllers.UpdateLockerCombo)
|
||||
app.Post(routerPrefix+"/admin/renableStudent", controllers.RemoveStudentsDisabled)
|
||||
app.Post(routerPrefix+"/admin/renableTeacher", controllers.RemoveTeachersDisabled)
|
||||
app.Post(routerPrefix+"/admin/enableStudent", controllers.RemoveStudentsDisabled)
|
||||
app.Post(routerPrefix+"/admin/enableTeacher", controllers.RemoveTeachersDisabled)
|
||||
|
||||
// Delete Handler
|
||||
app.Post(routerPrefix+"/remove/student", controllers.RemoveStudent)
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Account Disabled</title>
|
||||
<style type="text/css">
|
||||
body{
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
min-width: 100%;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
table{
|
||||
margin: 50px 0 50px 0;
|
||||
}
|
||||
.header{
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content{
|
||||
height: 100px;
|
||||
font-size: 18px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.subscribe{
|
||||
height: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
.button{
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
padding: 0 30px 0 30px;
|
||||
}
|
||||
.button a{
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
.buttonwrapper{
|
||||
margin: 0 auto;
|
||||
}
|
||||
.footer{
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
font-style: italic;
|
||||
}
|
||||
.footer a{
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-style: normal;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="#009587">
|
||||
<table bgcolor="#FFFFFF" width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr class="header">
|
||||
<td style="padding: 40px;">
|
||||
Uh Oh! Account Disabled!
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="content">
|
||||
<td style="padding:10px;">
|
||||
<p>
|
||||
Hi <b>{{ .username }}</b>, <br/>
|
||||
Your account has been disabled due to too many incorrect login attempts, please contact an admin to enable your account.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="footer">
|
||||
<td style="padding: 40px;">
|
||||
This is an automated system email // DO NOT REPLY
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,95 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Password has been changed</title>
|
||||
<style type="text/css">
|
||||
body{
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
min-width: 100%;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
table{
|
||||
margin: 50px 0 50px 0;
|
||||
}
|
||||
.header{
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content{
|
||||
height: 100px;
|
||||
font-size: 18px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.subscribe{
|
||||
height: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
.button{
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
padding: 0 30px 0 30px;
|
||||
}
|
||||
.button a{
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
.buttonwrapper{
|
||||
margin: 0 auto;
|
||||
}
|
||||
.footer{
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
font-style: italic;
|
||||
}
|
||||
.footer a{
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-style: normal;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="#009587">
|
||||
<table bgcolor="#FFFFFF" width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr class="header">
|
||||
<td style="padding: 40px;">
|
||||
Password Change!
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="content">
|
||||
<td style="padding:10px;">
|
||||
<p>
|
||||
Hi <b>{{ .username }}</b>, <br/>
|
||||
Your password has been changed by the system.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="subscribe">
|
||||
<td style="padding: 20px 0 0 0;">
|
||||
<h3>Your new password is:</h3>
|
||||
<table bgcolor="#009587" border="0" cellspacing="0" cellpadding="0" class="buttonwrapper">
|
||||
<tr>
|
||||
<td class="button" height="45">
|
||||
{{ .password }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="footer">
|
||||
<td style="padding: 40px;">
|
||||
This is an automated system email // DO NOT REPLY
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Password has been changed</title>
|
||||
<style type="text/css">
|
||||
body{
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
min-width: 100%;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
table{
|
||||
margin: 50px 0 50px 0;
|
||||
}
|
||||
.header{
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content{
|
||||
height: 100px;
|
||||
font-size: 18px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.subscribe{
|
||||
height: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
.button{
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
padding: 0 30px 0 30px;
|
||||
}
|
||||
.button a{
|
||||
color: #FFFFFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
.buttonwrapper{
|
||||
margin: 0 auto;
|
||||
}
|
||||
.footer{
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
font-style: italic;
|
||||
}
|
||||
.footer a{
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-style: normal;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body bgcolor="#009587">
|
||||
<table bgcolor="#FFFFFF" width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr class="header">
|
||||
<td style="padding: 40px;">
|
||||
Password Change!
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="content">
|
||||
<td style="padding:10px;">
|
||||
<p>
|
||||
Hi <b>{{ .username }}</b>, <br/>
|
||||
Your password has been changed by you. If you did not change your password, contact an admin immediatley!
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="footer">
|
||||
<td style="padding: 40px;">
|
||||
This is an automated system email // DO NOT REPLY
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
+1
-11
@@ -1,13 +1,3 @@
|
||||
# Testing
|
||||
|
||||
Hello there! If you are in this part of the codespace, I have cleaned it up compared to the
|
||||
original codespace. The algorithms have been moved out of `tinker.py` into their own python
|
||||
script from version 1 to 3. These are in the `/scheduleGenerator` folder. I suggest to look
|
||||
at the latest work in `v3.py` where the algorithm has come a long way. Using real 2018 course
|
||||
selection data from my school I am able to test the script to its full potential compared to
|
||||
V1 and V2.
|
||||
|
||||
V3 has a entirely different approach from V1 and V2, that you can read about at the top of
|
||||
the function in `v3.py`. The function is broken up into 6 steps, each step is labeled within
|
||||
the function with a comment, giving a brief explination of what that step contributes to the
|
||||
algorithm.
|
||||
If you would like to view this code more neatly, it has been moved to its own [repository](https://github.com/SowinskiBraeden/schedule-generator).
|
||||
Reference in new issue
Block a user