diff --git a/README.md b/README.md index fb46169..5f176ff 100644 --- a/README.md +++ b/README.md @@ -1 +1,14 @@ -# praromvik \ No newline at end of file +# praromvik + +The staring point, that will define your path on the DevOps journey ! + +## Contribution guidelines + +Want to help improve praromvik? Please read the design docs [here](https://github.com/Praromvik/praromvik/tree/master/docs). + +## Support + +To speak with us, please leave a message on our email `praromvik.hq@gmail.com`. +To receive product announcements, follow us on [Twitter](https://twitter.com/PraromvikHq), [LinkedIn](https://www.linkedin.com/company/praromvik/), [Facebook](https://www.facebook.com/profile.php?id=61557462003505). + +If you have found a bug with Praromvik or want to request for new features, please [file an issue](https://github.com/praromvik/praromvik/issues/new). diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..65d45fb --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,77 @@ +Description on each of the packages + +# cmd +Under the root command, there is only one subcommand named start_server. We use the routers package from it & start the server. + +# routes +We have these types of routes: + +`user_auth`: signUp, signIn, signOut + +`course`: +i) get/list -> general authenticated users can do it. +ii) create/update -> admin or moderators can do. +iii) delete -> only admin can do it. + +For get,update & delete calls(those work on a specific course uid), we utilize a context middleware for injecting context data. + +There is one special route for providing role to a user. It requires the admin access. + +# pkg +-`pkg.auth`: + +We store these fields in the redis session: +i) authenticated, ii) role, iii) userName, iv) userIP, v) user_agent +There are some getters implemented in the session.go file. + + + +-`pkg.error` + +-`pkg.middleware`: + +There are 4 types of middlewares in this package. +i) global middleware: For example logger, urlFormatter etc. + +ii) common security middleware: To check if a session is valid & authenticated. + +iii) access related middleware: To check if the role(in session) is matched. + +iv) context middleware: To append additional info to the context. + + +# handlers +`routes -> handlers -> models` + +Routes package will call functions from handlers package. And handlers package will call functions from models package. +We should be strict to this design principle to avoid implementation complexity & circular dependencies. + +In general, the handlers are pretty straight-forward. They contain functions like Create, Get, List, Update, Delete etc. + +# models +This is the actual working unit. The API & common constants are declared here. Also, it is responsible for all the database calls. + + +1) `models.db.client`: +A special package only to initialize the db clients thorough init(). + +2) `models.db`: +DB calls are implemented here. No one calls the DB directly except this package. + +3) `models.course`: +Dedicated package for course related methods. Intended to only be called from `handlers/course`. + +4) `models.user`: + Dedicated package for user related methods. Intended to only be called from `handlers/user`. + + +--- +There are some other non-code packages/files worth mentioning. + +`docs`: Holds the documentation files. + +`hack`: Holds the utility script files. + +`.env` file: Export the required ENVs to run this backend server. + +`req.http` file: Holds the curl request-response examples for the implemented http routes. diff --git a/docs/database_design.md b/docs/database_design.md new file mode 100644 index 0000000..de329ba --- /dev/null +++ b/docs/database_design.md @@ -0,0 +1,124 @@ +## API +``` +type Course struct { + CourseId string `json:"_id" bson:"_id"` + Title string `json:"title" bson:"title"` + Description string `json:"description" bson:"description"` + Instructors []string `json:"instructors" bson:"instructors"` + Moderators []string `json:"moderators" bson:"moderators"` + StartDate date.Date `json:"startDate" bson:"startDate"` + EndDate date.Date `json:"endDate" bson:"endDate"` + Duration int `json:"duration" bson:"duration"` // Duration in week + Capacity int `json:"capacity" bson:"capacity"` + Students []string `json:"students" bson:"students"` + Price int `json:"price" bson:"price"` + Image []byte `json:"image" bson:"-"` +} +``` + +``` +type Lesson struct { + LessonID string `json:"_id" bson:"_id"` + Title string `json:"title" bson:"title"` + Contents []ContentRef `json:"contents" bson:"contents"` +} + +type ContentRef struct { + ID string `json:"id" bson:"id"` + Title string `json:"title" bson:"title"` +} + +type Content struct { + ContentID string `json:"_id" bson:"_id"` + Title string `json:"title" bson:"title"` + Type string `json:"type" bson:"type"` // video, resource, quiz, lab + Data []byte `json:"data" bson:"data"` + LessonRef UUID `json:"lessonRef" bson:"lessonRef"` +} +``` + + +## A concrete Example +``` +Course name: Mastering golang +: +Introduction: + Why Go? + Installation + + +Concurrency in Go: + channels + mutex + + + go routines + +Conclusion + thank you +``` + +For the `lab1` under 'Concurrency in Go', url will be like: +http://praromvik.com/course/mastering_golang/concurrency_lab_1/ +Intentionally cutting off the lesson id part to keep the url shorter. + +--- + +We have divided a single course into 2 different databases. One for holding the metadata, & one for holding the actual information. +Again the actual information is divided into two collections. One will be called once, & the other one will be called several times (with specific contentID) from the frontend. +### `praromvik.courses` collection +This will hold the metadata information only. +``` +{ + "_id": "mastering_golang", + "title": "Mastering Golang", + "instructors": []string{}, + "students": []string{} +} +``` +Removed the lessons slice above to avoid multiple reference update on create/delete calls. + +### `mastering_golang.lessons` collection +The _id format is `<4_digit_serial_number>_` +``` +{ + "_id": "<0001_1715524983>", + "title": "Introduction", + "contents": []string{<_ids>} +}, +{ + "_id": "<0002_1715527643>", + "title": "Concurrency in Go", + "contents": []string{"channel", "concurrency_lab_1", "resouce_from_doc"} +} +``` + +### `mastering_golang.contents` collection +``` +{ + "_id": "channel", + "title": "Channel", + "type": "Video", + "lessonRef": "0002_1715527643" +}, +{ + "_id": "concurrency_lab_1", + "title": "Hands-on the Go channel", + "type": "Lab", + "lessonRef": "0002_1715527643" +}, +{ + "_id": "resouce_from_doc", + "title": "Additional learing resouces", + "type": "Written", + "lessonRef": "0002_1715527643" +}, +``` + +So the `RESTRICTIONS` are: + +i) course ids have to be unique. + +ii) content ids within a course have to be unique. + +iii) both course & content ids have to be <= 24 characters, as they will be used as _id in mongodb.