Compare commits
39
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50e672849b | ||
|
|
956fe306e5 | ||
|
|
dcabacdc8c | ||
|
|
8032b79989 | ||
|
|
255ea25edf | ||
|
|
7e85215fcc | ||
|
|
84b8c1ae5e | ||
|
|
ca4020f0ee | ||
|
|
596533753c | ||
|
|
e97f185e22 | ||
|
|
fdd489345d | ||
|
|
724b61cc2e | ||
|
|
b456a02178 | ||
|
|
41e7ca4f87 | ||
|
|
ae88f5d149 | ||
|
|
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,940 @@
|
||||
# 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)
|
||||
* [Creating Administrators](#creating-administrators)
|
||||
* [Registering a Teacher](#registering-a-teacher)
|
||||
* [Enrolling a Student](#enrolling-a-student)
|
||||
* [Additional Info](#additional-information-after-creating-an-account)
|
||||
* [Log into Accounts](#log-into-accounts)
|
||||
* [Logging Into Admin](#logging-into-admin)
|
||||
* [Logging Into Teacher](#logging-into-teacher)
|
||||
* [Logging Into Student](#logging-into-student)
|
||||
* [Get Account](#get-account)
|
||||
* [Get Admin Account](#get-admin-account)
|
||||
* [Get Teacher Account](#get-teacher-account)
|
||||
* [Get Student Account](#get-student-account)
|
||||
* [Updating Account information](#updating-accounts)
|
||||
* **Update Student...**
|
||||
* [Name](#update-student-name)
|
||||
* [Grade Level](#update-student-grade-level)
|
||||
* [Homeroom](#update-student-homeroom)
|
||||
* [Locker](#update-student-locker)
|
||||
* [YOG](#update-student-year-of-graduation)
|
||||
* [Password](#update-student-password)
|
||||
* [Email](#update-student-email)
|
||||
* [Address](#update-student-address)
|
||||
* [Photo](#update-student-photo)
|
||||
<br></br>
|
||||
* **Update Teacher...**
|
||||
* [Name](#update-teacher-name)
|
||||
* [Homeroom](#update-teacher-homeroom)
|
||||
* [Password](#update-teacher-password)
|
||||
* [Email](#update-teacher-email)
|
||||
* [Address](#update-teacher-address)
|
||||
* [Photo](#update-teacher-photo)
|
||||
<br></br>
|
||||
* **Update Admin...**
|
||||
* [Name](#update-admin-name) - **(Coming Soon)**
|
||||
* [Password](#update-admin-password) - **(Coming Soon)**
|
||||
* [Email](#update-admin-email) - **(Coming Soon)**
|
||||
* [Photo](#update-admin-photo) - **(Coming Soon)**
|
||||
* [Managing Contacts](#managing-contacts) - **(Not Documented)**
|
||||
* [Create Contact](#create-contact) - **(Not Documented)**
|
||||
* [Update Contact Name](#update-contact-name) - **(Not Documented)**
|
||||
* [Update Contact Address](#update-contact-address) - **(Not Documented)**
|
||||
* [Update Contact Home Phone](#update-contact-home-phone) - **(Not Documented)**
|
||||
* [Update Contact Work Phone](#update-contact-work-phone) - **(Not Documented)**
|
||||
* [Update Contact Email](#update-contact-email) - **(Not Documented)**
|
||||
* [Update Contact Priority](#update-contact-priority) - **(Not Documented)**
|
||||
* [Delete Contact](#delete-contact) - **(Not Documented)**
|
||||
|
||||
<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
|
||||
```bash
|
||||
$ 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`
|
||||
```bash
|
||||
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
|
||||
```bash
|
||||
$ go run main.go
|
||||
```
|
||||
|
||||
Or...
|
||||
|
||||
5. Build and compile the system into an executable
|
||||
```bash
|
||||
$ 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:
|
||||
```jsonc
|
||||
{
|
||||
"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 Administrates- 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>/api/v1/admin/create
|
||||
```
|
||||
|
||||
**Required:**
|
||||
+ Logged into an existing Admin account
|
||||
+ JSON:
|
||||
```jsonc
|
||||
{
|
||||
"firstname": "John",
|
||||
"lastname": "Doe",
|
||||
"dob": "01-01-1999",
|
||||
"email": "john_doe@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
+ Status 200: `OK`
|
||||
+ JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully inserted admin"
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
+ ### Registering a Teacher
|
||||
Obviously a school management system will require teachers to manage and teach students. Teachers have an important role for the system.
|
||||
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/teacher/register
|
||||
```
|
||||
|
||||
**Required:**
|
||||
+ Logged into an existing Admin account
|
||||
+ JSON:
|
||||
```jsonc
|
||||
{
|
||||
"firstname": "Homer",
|
||||
"middlename": "Jay",
|
||||
"lastname": "Simson",
|
||||
"dob": "12-05-1956",
|
||||
"email": "homerdog_simpson@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
+ Status 200: `OK`
|
||||
+ JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully inserted teacher"
|
||||
}
|
||||
```
|
||||
|
||||
+ ### Enrolling a Student
|
||||
What is a school without 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>/api/v1/student/enroll
|
||||
```
|
||||
|
||||
**Required:**
|
||||
+ Logged into an existing Admin account
|
||||
+ JSON:
|
||||
```jsonc
|
||||
{
|
||||
"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:
|
||||
```jsonc
|
||||
{
|
||||
"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 formatted 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 default profile image. This can be updated in the future.
|
||||
|
||||
**(Coming Soon)**
|
||||
5. All new users, once have verified their email, will receive and email containing their ID.
|
||||
|
||||
**(Currently No verified email required)**
|
||||
6. All new users, once have verified their email, will receive and email containing their temporary password.
|
||||
|
||||
<br>
|
||||
|
||||
## Log Into Accounts
|
||||
|
||||
+ ### Logging into Admin
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/admin/login
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"tid": "123456",
|
||||
"password": "myawesomepassword123"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```
|
||||
{
|
||||
"success": true,
|
||||
"message": "correct password"
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
+ ### Logging into Teacher
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/teacher/login
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"tid": "123456",
|
||||
"password": "myawesomepassword123"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "correct password"
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
+ ### Logging into Student
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/login
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"sid": "123456",
|
||||
"password": "myawesomepassword123"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "correct password"
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Get Account
|
||||
|
||||
+ ### Get Admin Account
|
||||
**Method:** `GET`
|
||||
```
|
||||
<API_URL>/api/v1/admin
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully logged into admin",
|
||||
"admin:" <admin object>
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
+ ### Get Teacher Account
|
||||
**Method:** `GET`
|
||||
```
|
||||
<API_URL>/api/v1/teacher
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an teacher account
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully logged into teacher",
|
||||
"teacher:" <teacher object>
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
+ ### Get Student Account
|
||||
**Method:** `GET`
|
||||
```
|
||||
<API_URL>/api/v1/student
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully logged into teacher",
|
||||
"student:" <student object>
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Updating Account Information
|
||||
|
||||
+ ### Update Student Name
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updateName
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"sid": "123456",
|
||||
"firstname": "Lisa",
|
||||
"middlename": "Marie", // (OPTIONAL)
|
||||
"lastname": "Simpson"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated student"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Student Grade Level
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updateGradeLevel
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON":
|
||||
```jsonc
|
||||
{
|
||||
"sid": "123456",
|
||||
"gradelevel": 11
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated student"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Student Homeroom
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updateHomeroom
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"sid": "123456",
|
||||
"homeroom": "A123"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated student"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Student Locker
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updateLocker
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"sid": "123456",
|
||||
"lockernumber": "B123"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated student"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Student Year of Graduation
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updateYOG
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"sid": "123456",
|
||||
"yog": 2020
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated student"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Student Password
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updatePassword
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into students account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"password": "myOldPassword",
|
||||
"newpassword1": "myNewPassword",
|
||||
"newpassword2": "myNewPassword"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated student password"
|
||||
}
|
||||
```
|
||||
* Emails student an alert of password change
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Student Email
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updateEmail
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
__or__
|
||||
* Logged into students account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"sid": "123456", // (Only required if signed in as admin)
|
||||
"email": "BartSimpsonsCoolEmail@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Student Address
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updateAddress
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"sid": "123456",
|
||||
"address": "742 Evergreen Terrace",
|
||||
"city": "Springfield",
|
||||
"province": "...",
|
||||
"postal": "..."
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated student"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Student Photo
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/student/updatePhoto
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* Form Submission:
|
||||
```
|
||||
sid: "123456"
|
||||
image: newStudentPhoto.png
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated student photo"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Teacher Name
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/teacher/updateName
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"tid": "123456",
|
||||
"firstname": "Marjorie",
|
||||
"middlename": "Jacqueline", // (Optional)
|
||||
"lastname": "Simpson"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Teacher Homeroom
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/teacher/updateHomeroom
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON:
|
||||
```
|
||||
{
|
||||
"tid": "123456",
|
||||
"homeroom": "A123"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Teacher Password
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/teacher/updatePassword
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into teacher account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"password": "myOldPassword",
|
||||
"newpassword1": "myNewPassword",
|
||||
"newpassword2": "myNewPassword"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher password"
|
||||
}
|
||||
```
|
||||
* Emails teacher an alert of password change
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Teacher Email
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/teacher/updateEmail
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
**or**
|
||||
* Logged into teachers account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"tid": "123456", // (Only required if igned in as admin)
|
||||
"email": "MargeSimpson@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Teacher Address
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/teacher/updateAddress
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin account
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"tid": "123456",
|
||||
"address": "742 Evergreen Terrace",
|
||||
"city": "Springfield",
|
||||
"province": "...",
|
||||
"postal": "..."
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Teacher Photo
|
||||
**Method:** `POST`
|
||||
```
|
||||
<API_URL>/api/v1/teacher/updatePhoto
|
||||
```
|
||||
|
||||
**Required:**
|
||||
* Logged into an admin
|
||||
* Form Submission:
|
||||
```
|
||||
tid: "123456"
|
||||
image: newTeacherPhoto.png
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
* Status 200: `OK`
|
||||
* JSON:
|
||||
```jsonc
|
||||
{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher photo"
|
||||
}
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Admin Name
|
||||
**Coming Soon...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Admin Password
|
||||
**Coming Soon...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Admin Email
|
||||
**Coming Soon...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Admin Photo
|
||||
**Coming Soon...**
|
||||
|
||||
<br></br>
|
||||
|
||||
## Managing Conacts
|
||||
**To be Documented...**
|
||||
|
||||
+ ### Creating Contact
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Contact Name
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Contact Address
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Contact Home Phone
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Contact Work Phone
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Contact Email
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Update Contact Priority
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Delete Conotact
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
## Remove Users
|
||||
**To be Documented...**
|
||||
|
||||
+ ### Remove Admin
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Remove Teacher
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Remove Student
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
### Admin Commands
|
||||
Administrators play a very important role in managing a school, they do much work behind the scenes to make sure that everything is correctly organized and working.
|
||||
|
||||
+ ### Update Locker Combination
|
||||
**To be Documented...**
|
||||
|
||||
<br></br>
|
||||
|
||||
+ ### Enable Student Account
|
||||
In the case a students acount has been disabled, an admin would require to enable the account.
|
||||
|
||||
**To be Documented...**
|
||||
<br></br>
|
||||
|
||||
+ ### Enable Teacher Account
|
||||
In the case a teachers acount has been disabled, an admin would require to enable the account.
|
||||
|
||||
**To be Documented...**
|
||||
<br></br>
|
||||
@@ -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
|
||||
|
||||
+169
-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,65 @@ 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
|
||||
|
||||
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, 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 +93,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 +116,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 +132,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 +159,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 +216,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 +225,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 +300,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 +359,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 +375,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 +417,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 +446,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 +512,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 +522,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 +558,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 +604,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 +802,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 +854,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 +987,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 +1072,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,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 {
|
||||
+368
-98
@@ -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,
|
||||
@@ -147,7 +145,7 @@ func UpdateStudentGradeLevel(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := studentCollection.UpdateOne(
|
||||
_, updateErr := studentCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.sid": data["sid"].(string)},
|
||||
update,
|
||||
@@ -165,7 +163,6 @@ func UpdateStudentGradeLevel(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated student",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -194,7 +191,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,
|
||||
@@ -219,7 +216,7 @@ func UpdateStudentHomeroom(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := studentCollection.UpdateOne(
|
||||
_, updateErr := studentCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.sid": data["sid"]},
|
||||
update,
|
||||
@@ -237,7 +234,6 @@ func UpdateStudentHomeroom(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated student",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -324,7 +320,7 @@ func UpdateStudentPassword(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := studentCollection.UpdateOne(
|
||||
_, updateErr := studentCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.sid": claims.Issuer},
|
||||
update,
|
||||
@@ -339,10 +335,21 @@ 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",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -413,16 +420,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 +452,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,
|
||||
@@ -483,7 +488,7 @@ func UpdateStudentLocker(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := studentCollection.UpdateOne(
|
||||
_, updateErr := studentCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.sid": data["sid"]},
|
||||
update,
|
||||
@@ -501,7 +506,6 @@ func UpdateStudentLocker(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated student",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -519,7 +523,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,
|
||||
@@ -547,7 +551,7 @@ func UpdateStudentAddress(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := studentCollection.UpdateOne(
|
||||
_, updateErr := studentCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"sid": data["sid"]},
|
||||
update,
|
||||
@@ -565,7 +569,6 @@ func UpdateStudentAddress(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated student",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -584,7 +587,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 +658,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 +732,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 +796,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,
|
||||
@@ -881,7 +884,7 @@ func UpdateStudentPhoto(c *fiber.Ctx) error {
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
result, updateErr := imageCollection.UpdateOne(
|
||||
_, updateErr := imageCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": photo.ID},
|
||||
update,
|
||||
@@ -902,7 +905,6 @@ func UpdateStudentPhoto(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated student photo",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -919,8 +921,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()
|
||||
@@ -930,6 +932,14 @@ func UpdateStudentEmail(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
if verifiedAdmin && data["sid"] == "" {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "missing required fields",
|
||||
})
|
||||
}
|
||||
|
||||
// Check required fields are included
|
||||
if data["email"] == "" {
|
||||
cancel()
|
||||
@@ -983,7 +993,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 +1014,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 +1029,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 +1056,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 +1129,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,
|
||||
@@ -1143,7 +1154,7 @@ func UpdateTeacherHomeroom(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := teacherCollection.UpdateOne(
|
||||
_, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.tid": data["tid"]},
|
||||
update,
|
||||
@@ -1161,7 +1172,6 @@ func UpdateTeacherHomeroom(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1194,7 +1204,7 @@ func UpdateTeacherPassword(c *fiber.Ctx) error {
|
||||
claims := token.Claims.(*jwt.StandardClaims)
|
||||
|
||||
var teacher models.Teacher
|
||||
findErr := studentCollection.FindOne(ctx, bson.M{"schooldata.tid": claims.Issuer}).Decode(&teacher)
|
||||
findErr := teacherCollection.FindOne(ctx, bson.M{"schooldata.tid": claims.Issuer}).Decode(&teacher)
|
||||
if findErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
@@ -1248,7 +1258,7 @@ func UpdateTeacherPassword(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := teacherCollection.UpdateOne(
|
||||
_, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.tid": claims.Issuer},
|
||||
update,
|
||||
@@ -1263,10 +1273,20 @@ 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",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -1398,7 +1416,7 @@ func UpdateTeacherAddress(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := teacherCollection.UpdateOne(
|
||||
_, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.tid": data["tid"]},
|
||||
update,
|
||||
@@ -1416,7 +1434,6 @@ func UpdateTeacherAddress(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1424,7 +1441,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 +1458,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 {
|
||||
@@ -1512,7 +1529,7 @@ func UpdateTeacherPhoto(c *fiber.Ctx) error {
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
result, updateErr := imageCollection.UpdateOne(
|
||||
_, updateErr := imageCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": photo.ID},
|
||||
update,
|
||||
@@ -1533,7 +1550,6 @@ func UpdateTeacherPhoto(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher photo",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1551,7 +1567,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,
|
||||
@@ -1576,7 +1592,7 @@ func UpdateTeacherEmail(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := teacherCollection.UpdateOne(
|
||||
_, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"schooldata.tid": data["tid"]},
|
||||
update,
|
||||
@@ -1594,7 +1610,6 @@ func UpdateTeacherEmail(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1612,7 +1627,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 +1636,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,28 +1644,37 @@ 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,
|
||||
})
|
||||
}
|
||||
|
||||
var middlename string = ""
|
||||
|
||||
if data["middlename"] != "" {
|
||||
middlename = data["middlename"]
|
||||
}
|
||||
|
||||
update_time, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"personaldata.firstname": data["firstname"],
|
||||
"personaldata.middlename": data["middlename"],
|
||||
"personaldata.middlename": middlename,
|
||||
"personaldata.lastname": data["lastname"],
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := teacherCollection.UpdateOne(
|
||||
_, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": teacherObjectId},
|
||||
bson.M{"schooldata.tid": data["tid"]},
|
||||
update,
|
||||
)
|
||||
if updateErr != nil {
|
||||
@@ -1666,7 +1690,6 @@ func UpdateTeacherName(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated teacher",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1684,7 +1707,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,
|
||||
@@ -1711,7 +1734,7 @@ func UpdateContactName(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := contactCollection.UpdateOne(
|
||||
_, updateErr := contactCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": data["_id"]},
|
||||
update,
|
||||
@@ -1729,7 +1752,6 @@ func UpdateContactName(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated contact",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1747,7 +1769,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,
|
||||
@@ -1775,7 +1797,7 @@ func UpdateContactAddress(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := contactCollection.UpdateOne(
|
||||
_, updateErr := contactCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": data["_id"]},
|
||||
update,
|
||||
@@ -1793,7 +1815,6 @@ func UpdateContactAddress(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated contact",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -1836,7 +1857,7 @@ func UpdateContactHomePhone(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := contactCollection.UpdateOne(
|
||||
_, updateErr := contactCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": data["_id"]},
|
||||
update,
|
||||
@@ -1854,7 +1875,6 @@ func UpdateContactHomePhone(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated contact",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1872,7 +1892,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,
|
||||
@@ -1897,7 +1917,7 @@ func UpdateContactWorkPhone(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := contactCollection.UpdateOne(
|
||||
_, updateErr := contactCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": data["_id"]},
|
||||
update,
|
||||
@@ -1915,7 +1935,6 @@ func UpdateContactWorkPhone(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated contact",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1933,7 +1952,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,
|
||||
@@ -1958,7 +1977,7 @@ func UpdateContactEmail(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := contactCollection.UpdateOne(
|
||||
_, updateErr := contactCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": data["_id"]},
|
||||
update,
|
||||
@@ -1976,7 +1995,6 @@ func UpdateContactEmail(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated contact",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1994,7 +2012,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,
|
||||
@@ -2019,7 +2037,7 @@ func UpdateContactPriority(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := contactCollection.UpdateOne(
|
||||
_, updateErr := contactCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"_id": data["_id"]},
|
||||
update,
|
||||
@@ -2037,7 +2055,6 @@ func UpdateContactPriority(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated contact",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2055,7 +2072,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,
|
||||
@@ -2080,7 +2097,7 @@ func UpdateLockerCombo(c *fiber.Ctx) error {
|
||||
},
|
||||
}
|
||||
|
||||
result, updateErr := lockerCollection.UpdateOne(
|
||||
_, updateErr := lockerCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"lockernumber": data["lockernumber"]},
|
||||
update,
|
||||
@@ -2098,7 +2115,6 @@ func UpdateLockerCombo(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated locker",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2116,7 +2132,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,
|
||||
@@ -2143,7 +2159,7 @@ func RemoveStudent(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
result, deleteErr := studentCollection.DeleteOne(ctx, bson.M{"schooldata.sid": data["sid"]})
|
||||
_, deleteErr = studentCollection.DeleteOne(ctx, bson.M{"schooldata.sid": data["sid"]})
|
||||
if deleteErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
@@ -2157,7 +2173,6 @@ func RemoveStudent(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully deleted student",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2175,7 +2190,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,
|
||||
@@ -2202,7 +2217,7 @@ func RemoveTeacher(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
result, deleteErr := teacherCollection.DeleteOne(ctx, bson.M{"schooldata.tid": data["tid"]})
|
||||
_, deleteErr = teacherCollection.DeleteOne(ctx, bson.M{"schooldata.tid": data["tid"]})
|
||||
if deleteErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
@@ -2216,7 +2231,6 @@ func RemoveTeacher(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully deleted teacher",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2234,7 +2248,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,
|
||||
@@ -2261,7 +2275,7 @@ func RemoveAdmin(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
result, deleteErr := adminCollection.DeleteOne(ctx, bson.M{"aid": data["aid"]})
|
||||
_, deleteErr = adminCollection.DeleteOne(ctx, bson.M{"aid": data["aid"]})
|
||||
if deleteErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
@@ -2275,6 +2289,262 @@ func RemoveAdmin(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully deleted admin",
|
||||
"result": result,
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateAdminName(c *fiber.Ctx) error {
|
||||
var data map[string]string
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
|
||||
if err := c.BodyParser(&data); err != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Failed to parse body",
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
|
||||
cookie := c.Cookies("jwt")
|
||||
|
||||
token, err := jwt.ParseWithClaims(cookie, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(SecretKey), nil
|
||||
})
|
||||
if err != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "not authorized",
|
||||
})
|
||||
}
|
||||
|
||||
claims := token.Claims.(*jwt.StandardClaims)
|
||||
|
||||
var admin models.Admin
|
||||
findErr := adminCollection.FindOne(ctx, bson.M{"aid": claims.Issuer}).Decode(&admin)
|
||||
if findErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "admin not found",
|
||||
})
|
||||
}
|
||||
|
||||
// Check required fields are included
|
||||
if data["firstname"] == "" || data["lastname"] == "" {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "missing required fields",
|
||||
})
|
||||
}
|
||||
|
||||
update_time, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"firstname": data["firstname"],
|
||||
"lastname": data["lastname"],
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
|
||||
_, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"aid": claims.Issuer},
|
||||
update,
|
||||
)
|
||||
if updateErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "the admin password could not be updated",
|
||||
"error": updateErr,
|
||||
})
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated admin",
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateAdminEmail(c *fiber.Ctx) error {
|
||||
var data map[string]string
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
|
||||
if err := c.BodyParser(&data); err != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Failed to parse body",
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
|
||||
cookie := c.Cookies("jwt")
|
||||
|
||||
token, err := jwt.ParseWithClaims(cookie, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(SecretKey), nil
|
||||
})
|
||||
if err != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "not authorized",
|
||||
})
|
||||
}
|
||||
|
||||
claims := token.Claims.(*jwt.StandardClaims)
|
||||
|
||||
var admin models.Admin
|
||||
findErr := adminCollection.FindOne(ctx, bson.M{"aid": claims.Issuer}).Decode(&admin)
|
||||
if findErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "admin not found",
|
||||
})
|
||||
}
|
||||
|
||||
// Check required fields are included
|
||||
if data["email"] == "" {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "missing required fields",
|
||||
})
|
||||
}
|
||||
|
||||
update_time, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"email": data["email"],
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
|
||||
_, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"aid": claims.Issuer},
|
||||
update,
|
||||
)
|
||||
if updateErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "the admin password could not be updated",
|
||||
"error": updateErr,
|
||||
})
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated admin",
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateAdminPassword(c *fiber.Ctx) error {
|
||||
var data map[string]string
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
|
||||
if err := c.BodyParser(&data); err != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Failed to parse body",
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
|
||||
cookie := c.Cookies("jwt")
|
||||
|
||||
token, err := jwt.ParseWithClaims(cookie, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(SecretKey), nil
|
||||
})
|
||||
if err != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "not authorized",
|
||||
})
|
||||
}
|
||||
|
||||
claims := token.Claims.(*jwt.StandardClaims)
|
||||
|
||||
var admin models.Admin
|
||||
findErr := adminCollection.FindOne(ctx, bson.M{"aid": claims.Issuer}).Decode(&admin)
|
||||
if findErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "admin not found",
|
||||
})
|
||||
}
|
||||
|
||||
// Check required fields are included
|
||||
if data["password"] == "" || data["newpassword1"] == "" || data["newpassword2"] == "" {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "missing required fields",
|
||||
})
|
||||
}
|
||||
|
||||
if !admin.ComparePasswords(data["password"]) {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Your password is incorrect",
|
||||
})
|
||||
}
|
||||
|
||||
if data["newpassword1"] != data["newpassword2"] {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Your new passwords must match",
|
||||
})
|
||||
}
|
||||
|
||||
update_time, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339))
|
||||
update := bson.M{
|
||||
"$set": bson.M{
|
||||
"password": admin.HashPassword(data["newpassword1"]),
|
||||
"temppassword": false, // If it were a temp password, its not now
|
||||
"updated_at": update_time,
|
||||
},
|
||||
}
|
||||
|
||||
_, updateErr := teacherCollection.UpdateOne(
|
||||
ctx,
|
||||
bson.M{"aid": claims.Issuer},
|
||||
update,
|
||||
)
|
||||
if updateErr != nil {
|
||||
cancel()
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "the admin password could not be updated",
|
||||
"error": updateErr,
|
||||
})
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
subject := "Password Changed"
|
||||
receiver := admin.Email
|
||||
r := NewRequest([]string{receiver}, subject)
|
||||
|
||||
if sent := r.Send("./templates/selfPasswordChanged.html", map[string]string{"username": admin.FirstName}); !sent {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"success": false,
|
||||
"message": "Could not send password to admins email",
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"success": true,
|
||||
"message": "successfully updated admin password",
|
||||
})
|
||||
}
|
||||
@@ -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 = "\nv0.9.2-Alpha"
|
||||
|
||||
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)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
+7
-2
@@ -72,10 +72,15 @@ func Setup(app *fiber.App) {
|
||||
app.Post(routerPrefix+"/admin/create", controllers.CreateAdmin)
|
||||
app.Post(routerPrefix+"/admin/login", controllers.AdminLogin)
|
||||
|
||||
// Admin Update Handler
|
||||
app.Post(routerPrefix+"/admin/updateName", controllers.UpdateAdminName)
|
||||
app.Post(routerPrefix+"/admin/updateEmail", controllers.UpdateAdminEmail)
|
||||
app.Post(routerPrefix+"/admin/updatePassword", controllers.UpdateAdminPassword)
|
||||
|
||||
// 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