diff --git a/.env.dist b/.env.dist index c80a85a..ed2434d 100644 --- a/.env.dist +++ b/.env.dist @@ -23,9 +23,9 @@ DEBUG=1 # ------------------------------ # MariaDB values --------------- MYSQL_ROOT_PASSWORD=popcube_dev -MYSQL_DATABASE=popcube_test -MYSQL_USER=test_user -MYSQL_PASSWORD=test +MYSQL_DATABASE=${MYSQL_DATABASE:-popcube_dev} +MYSQL_USER=${MYSQL_USER:-dev_user} +MYSQL_PASSWORD=dev # ------------------------------ ################################ # RUNNING CONTAINER VARS ####### diff --git a/api/api.go b/api/api.go index b6e107f..7f67b23 100644 --- a/api/api.go +++ b/api/api.go @@ -8,6 +8,7 @@ import ( "log" "net/http" "os" + "regexp" jwt "github.com/dgrijalva/jwt-go" "github.com/jinzhu/gorm" @@ -40,6 +41,7 @@ type key string // } var ( + secret string hmacSampleSecret []byte tokenAuth *JwtAuth userToken *jwt.Token @@ -63,9 +65,23 @@ func newRandomString(length int) string { return b.String() } func initAuth() { - secret := newRandomString(100) hmacSampleSecret = []byte(secret) tokenAuth = New("HS256", hmacSampleSecret, hmacSampleSecret) + claims := jwt.MapClaims{ + "organisation_name": "PopCube", + "organisation_stack": 1, + "organisation_domain": "chat.popcube.xyz", + "public": false, + "owner": "TCMJJ", + "owner_mail": "owned@popcube.xyz", + "owner_password": "popcube", + "type": "neworganisation", + "authorise": "this token let you create new organisation and a new user in an iner DB", + } + unsignedToken := *jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + tokenString, _ := unsignedToken.SignedString(hmacSampleSecret) + log.Print("Tolken new organisation && role : ") + log.Print(tokenString) } // createUserToken create JWT auth token for current login user @@ -168,7 +184,19 @@ func basicRoutes(router *chi.Mux) { // 404: incorrectIds // 422: wrongEntity // 503: databaseError + // default: genericError router.Post("/login", loginMiddleware) + // swagger:route POST /initorganisation Init initOrganisation + // + // Try to log user in + // + // Login user with provided USERNAME && Password + // + // Responses: + // 200: initOk + // 503: databaseError + // default: genericError + router.Post("/initorganisation", initOrganisation) router.Route("/publicuser", func(r chi.Router) { // swagger:route POST /publicuser/new Users newPublicUser // @@ -258,16 +286,86 @@ func loginMiddleware(w http.ResponseWriter, r *http.Request) { } +func initOrganisation(w http.ResponseWriter, r *http.Request) { + // Verify token + ctx := r.Context() + if jwtErr, ok := ctx.Value(jwtErrorKey).(error); ok { + if jwtErr != nil { + render.JSON(w, 401, jwtErr) + return + } + } + jwtToken, ok := ctx.Value(jwtTokenKey).(*jwt.Token) + if !ok || jwtToken == nil || !jwtToken.Valid { + render.JSON(w, 401, "token is not valid or does not exist") + return + } + tokenType, ok := jwtToken.Claims.(jwt.MapClaims)["type"] + if !ok { + render.JSON(w, 401, "Token is not valid. Type is undifined") + return + } + if tokenType != "neworganisation" { + render.JSON(w, 401, "Token is not an init organisation one") + return + } + // Token passed. Initialising organisation + store := datastores.Store() + db := dbStore.db + organisation := models.Organisation{ + OrganisationName: jwtToken.Claims.(jwt.MapClaims)["organisation_name"].(string), + DockerStack: jwtToken.Claims.(jwt.MapClaims)["organisation_stack"].(int), + Domain: jwtToken.Claims.(jwt.MapClaims)["organisation_domain"].(string), + Public: jwtToken.Claims.(jwt.MapClaims)["public"].(bool), + } + user := models.User{ + Username: jwtToken.Claims.(jwt.MapClaims)["owner"].(string), + Email: jwtToken.Claims.(jwt.MapClaims)["owner_mail"].(string), + Password: jwtToken.Claims.(jwt.MapClaims)["owner_password"].(string), + // Owner role should always have ID 1 as it is the first one created into the DB. + IDRole: 1, + } + if err := db.DB().Ping(); err != nil { + render.JSON(w, error503.StatusCode, error503) + return + } + appErr := store.Organisation().Save(&organisation, db) + if appErr != nil { + render.JSON(w, appErr.StatusCode, appErr) + return + } + appErr = store.User().Save(&user, db) + if appErr != nil { + render.JSON(w, appErr.StatusCode, appErr) + return + } + res := initOk{ + Organisation: organisation, + Owner: user, + } + render.JSON(w, 201, res) +} + func newPublicUser(w http.ResponseWriter, r *http.Request) { var data struct { User *models.User OmitID interface{} `json:"id,omitempty"` } store := datastores.Store() - db := dbStore.db request := r.Body err := chiRender.Bind(request, &data) + organisation := store.Organisation().Get(db) + allowedWebMails := store.AllowedWebMails().GetAll(db) + isAuthorizedMail := false + for _, authorizedMail := range allowedWebMails { + filter := "*" + authorizedMail.Domain + ok, _ := regexp.MatchString(filter, data.User.Email) + isAuthorizedMail = isAuthorizedMail || ok + } + if !isAuthorizedMail && !organisation.Public { + render.JSON(w, 401, "You can't sign up if organisation is not public or your email domain was unauthorized.") + } if err != nil || data.User == nil { render.JSON(w, error422.StatusCode, error422) } else { @@ -287,6 +385,7 @@ func newPublicUser(w http.ResponseWriter, r *http.Request) { // StartAPI initialise the api with provided host and port. func StartAPI(hostname string, port string, DbConnectionInfo *configs.DbConnection) { router := newRouter() + _, _, secret = configs.InitConfig() // Init DB connection user := DbConnectionInfo.User db := DbConnectionInfo.Database diff --git a/api/api_parameters.go b/api/api_parameters.go index 07ac9fb..9c5605f 100644 --- a/api/api_parameters.go +++ b/api/api_parameters.go @@ -348,4 +348,11 @@ type inviteToken struct { Token string `json:"token"` } +// swagger:parameters newPublicUser +type initToken struct { + // Init token you got when creating new organisation. Pass it as Authentication: bearer {{token}} in the header + // in:body + Token string `json:"token"` +} + // <><><><><> <><><><><> <><><><><> <><><><><> // diff --git a/api/api_responses.go b/api/api_responses.go index 949c1c9..848e55f 100644 --- a/api/api_responses.go +++ b/api/api_responses.go @@ -38,6 +38,16 @@ type inviteOk struct { Token string `json:"token,omitempty"` } +// initOk when init correctly proceed, return the organisation object and its owner. +// +// swagger:response loginOk +type initOk struct { + // in:body + Organisation models.Organisation `json:"organisation,omitempty"` + // in:body + Owner models.User `json:"user,omitempty"` +} + // --------------------------------------------------- // Errors -------------------------------------------- diff --git a/configs/configs.go b/configs/configs.go index ce0be21..a8abd36 100644 --- a/configs/configs.go +++ b/configs/configs.go @@ -21,7 +21,7 @@ type APIServerInfo struct { } // InitConfig get configuration for project -func InitConfig() (DbConnection, APIServerInfo) { +func InitConfig() (DbConnection, APIServerInfo, string) { // Default configurations dbConnection := DbConnection{ User: "root", @@ -34,11 +34,18 @@ func InitConfig() (DbConnection, APIServerInfo) { Hostname: "", Port: "3000", } + // Dev secret + secret := "AAAAB3NzaC1yc2EAAAADAQABAAACAQCtdGt4uK8e1CEcTVZXSRJ9pRHxdeYBxq4oTh20DKH7exoikkEPbSAn34ZJPVVRdPMndg8Qg5xxHnwAtYvzYbxNWAxqYqvvvCKLJtjTS2dMeNLVz3FYD80MSJX3Tr5gpK7hHq9EEWB99onqMKDHlF3ZM3dBjwZH3mP7sWlqcdKc6lP9MGPsrpnXmBx3C4CSB7muMl8hF+4263gtS1oXHT0E16NFP3IgBNmvYavmOYSlqHs9NU7lZtNVbLbIZ2SCVrOJlcSKddvaMzIhXgRIK58VzbsqqaeVBTMrxrJopjLha2aTSe9luxOJZCf1foQKVf7eWPp4FK/zSSDMJbSX6+vsE1jFbuFF2dYmf8QW1UdDslZtQuCLzB4rqBmOiFx77DIyuZMMt5bjTi02nPYZL5Fo4vupcoV552QC6jyUG3nAoY28yPGmhKBb0EpbCd/qiroIAs5mXhaPGZriqq8DDRbqstHkubfXjDkZ6vWRDnCUfSioMky/bEC1X2KaMt/E0tpw8aWiIZXAble+CIWfo2HUj2GE/Y3Gf8f/A14Ec2E+Uz4xARcTL4UfopNU2P3Bxhz/KoIZFXYacKBphATsp+HB6sMKF5HJ+tn6mS0JFdgIpcClVMliap4zz6M92FOyyRW0wBHua6gOI+5nEMS2BDLBwTmw5otXOTFV8DaFNQzaiQ" // Default host for DB in Docker containers if os.Getenv("ENVTYPE") == "container" { log.Print("<><><><> Setting host to container default \n") dbConnection.Host = "database" } + + if newSecret := os.Getenv("POPCUBESECRET"); newSecret != "" { + secret = newSecret + } + // Get values set in env if apiPort := os.Getenv("API_PORT"); apiPort != "" { log.Print("<><><><> Setting api port \n") @@ -73,5 +80,5 @@ func InitConfig() (DbConnection, APIServerInfo) { } // Return new configs - return dbConnection, APIServer + return dbConnection, APIServer, secret } diff --git a/datastores/allowedWebMails_store.go b/datastores/allowedWebMails_store.go new file mode 100644 index 0000000..f83a2ec --- /dev/null +++ b/datastores/allowedWebMails_store.go @@ -0,0 +1,97 @@ +package datastores + +import ( + "github.com/jinzhu/gorm" + "github.com/titouanfreville/popcubeapi/models" + u "github.com/titouanfreville/popcubeapi/utils" +) + +// AllowedWebMailsStoreImpl Used to implement AllowedWebMailsStore interface +type AllowedWebMailsStoreImpl struct{} + +// AllowedWebMails Generate the struct for allowedWebMails store +func (s StoreImpl) AllowedWebMails() AllowedWebMailsStore { + return AllowedWebMailsStoreImpl{} +} + +// Save Use to save allowedWebMails in DB +func (asi AllowedWebMailsStoreImpl) Save(allowedWebMails *models.AllowedWebMails, db *gorm.DB) *u.AppError { + transaction := db.Begin() + if appError := allowedWebMails.IsValid(); appError != nil { + transaction.Rollback() + return u.NewAPIError(422, appError.ID, "Wrong data provided : \n ---- "+appError.Message+" ----") + } + if !transaction.NewRecord(&allowedWebMails) { + transaction.Rollback() + return u.NewAPIError(409, "duplicate entry", "You already authorized "+allowedWebMails.Domain+" mails to sign up.") + } + if err := transaction.Create(&allowedWebMails).Error; err != nil { + transaction.Rollback() + return u.NewAPIError(500, "unxepected error", "Unexpected error while adding entry. \n ---- "+err.Error()+"----") + } + transaction.Commit() + return nil +} + +// Update Used to update allowedWebMails in DB +func (asi AllowedWebMailsStoreImpl) Update(allowedWebMails *models.AllowedWebMails, newAllowedWebMails *models.AllowedWebMails, db *gorm.DB) *u.AppError { + transaction := db.Begin() + if appError := allowedWebMails.IsValid(); appError != nil { + transaction.Rollback() + return u.NewAPIError(422, appError.ID, "Wrong data provided : \n ---- "+appError.Message+" ----") + } + // if appError := newAllowedWebMails.IsValid(); appError != nil { + // transaction.Rollback() + // return u.NewLocAppError("allowedWebMailsStoreImpl.Update.allowedWebMailsNew.PreSave", appError.ID, nil, appError.DetailedError) + // } + if err := transaction.Model(&allowedWebMails).Updates(&newAllowedWebMails).Error; err != nil { + transaction.Rollback() + return u.NewAPIError(500, "unxepected error", "Unexpected error while adding entry. \n ---- "+err.Error()+"----") + } + transaction.Commit() + return nil +} + +// GetAll Used to get allowedWebMails from DB +func (asi AllowedWebMailsStoreImpl) GetAll(db *gorm.DB) []models.AllowedWebMails { + allowedWebMailss := []models.AllowedWebMails{} + db.Find(&allowedWebMailss) + return allowedWebMailss +} + +// GetByID Used to get allowedWebMails from DB +func (asi AllowedWebMailsStoreImpl) GetByID(ID uint64, db *gorm.DB) models.AllowedWebMails { + allowedWebMails := models.AllowedWebMails{} + db.Where("idAllowedWebMails = ?", ID).First(&allowedWebMails) + return allowedWebMails +} + +// GetByDomain Used to get allowedWebMails having providing domin +func (asi AllowedWebMailsStoreImpl) GetByDomain(domain string, db *gorm.DB) models.AllowedWebMails { + allowedWebMails := models.AllowedWebMails{} + db.Where("domain = ?", domain).First(&allowedWebMails) + return allowedWebMails +} + +// GetByProvider Used to get allowedWebMails provided by ... +func (asi AllowedWebMailsStoreImpl) GetByProvider(provider string, db *gorm.DB) []models.AllowedWebMails { + allowedWebMails := []models.AllowedWebMails{} + db.Where("provider = ?", provider).First(&allowedWebMails) + return allowedWebMails + +} + +// Delete Used to remove specified allowedWebMails from DB +func (asi AllowedWebMailsStoreImpl) Delete(allowedWebMails *models.AllowedWebMails, db *gorm.DB) *u.AppError { + transaction := db.Begin() + if appError := allowedWebMails.IsValid(); appError != nil { + transaction.Rollback() + return u.NewLocAppError("allowedWebMailsStoreImpl.Delete.allowedWebMails.PreSave", appError.ID, nil, appError.DetailedError) + } + if err := transaction.Delete(&allowedWebMails).Error; err != nil { + transaction.Rollback() + return u.NewLocAppError("allowedWebMailsStoreImpl.Delete", "update.transaction.delete.encounterError :"+err.Error(), nil, "") + } + transaction.Commit() + return nil +} diff --git a/datastores/allowedWebMails_store_test.go b/datastores/allowedWebMails_store_test.go new file mode 100644 index 0000000..810781b --- /dev/null +++ b/datastores/allowedWebMails_store_test.go @@ -0,0 +1,296 @@ +// This file is used to test if user model is working correctly. +// A user is always linked to an allowedWebMails +// He has basic channel to join +package datastores + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" + . "github.com/titouanfreville/popcubeapi/models" + u "github.com/titouanfreville/popcubeapi/utils" +) + +func genDbError(error string) *u.AppError { + return u.NewAPIError(500, "unxepected error", "Unexpected error while adding entry. \n ---- "+error+"----") +} + +func genDuplicateError(duplicateID string) *u.AppError { + return u.NewAPIError(409, "duplicate entry", "You already authorized "+duplicateID+" mails to sign up.") +} + +func genInvalidDataError(errorID string, errorMessage string) *u.AppError { + return u.NewAPIError(422, errorID, "Wrong data provided : \n ---- "+errorMessage+" ----") +} + +func TestAllowedWebMailsStore(t *testing.T) { + store := Store() + db := store.InitConnection("root", "popcube_test", "popcube_dev", "database", "3306") + asi := store.AllowedWebMails() + Convey("Testing save function", t, func() { + allowedWebMails := AllowedWebMails{ + Domain: "popcube.xyz", + Provider: "PopCube", + DefaultRights: "Master", + } + db.Delete(&allowedWebMails) + Convey("Given a correct allowedWebMails.", func() { + appError := asi.Save(&allowedWebMails, db) + Convey("Trying to add it for the first time, should be accepted", func() { + So(appError, ShouldBeNil) + So(appError, ShouldNotResemble, genDbError("nil")) + So(appError, ShouldNotResemble, genDuplicateError(allowedWebMails.Domain)) + So(appError, ShouldNotResemble, genInvalidDataError("test", "something")) + }) + Convey("Trying to add it a second time should return duplicate error", func() { + appError2 := asi.Save(&allowedWebMails, db) + So(appError2, ShouldNotBeNil) + So(appError2, ShouldNotResemble, genDbError("")) + So(appError2, ShouldResemble, genDuplicateError(allowedWebMails.Domain)) + So(appError2, ShouldNotResemble, genInvalidDataError("test", "something")) + }) + }) + db.Delete(&allowedWebMails) + }) + + Convey("Testing update function", t, func() { + allowedWebMails := AllowedWebMails{ + Domain: "popcube.xyz", + Provider: "PopCube", + DefaultRights: "Master", + } + allowedWebMailsNew := AllowedWebMails{ + Domain: "newpopcube.xyz", + Provider: "NewPopCube", + DefaultRights: "NewMaster", + } + + appError := asi.Save(&allowedWebMails, db) + So(appError, ShouldBeNil) + So(appError, ShouldNotResemble, genDbError("")) + So(appError, ShouldNotResemble, genDuplicateError(allowedWebMails.Domain)) + So(appError, ShouldNotResemble, genInvalidDataError("test", "something")) + + Convey("Provided correct AllowedWebMails to modify should not return errors", func() { + appError := asi.Update(&allowedWebMails, &allowedWebMailsNew, db) + So(appError, ShouldBeNil) + So(appError, ShouldNotResemble, genDbError("")) + So(appError, ShouldNotResemble, genDuplicateError(allowedWebMails.Domain)) + So(appError, ShouldNotResemble, genInvalidDataError("test", "something")) + }) + + // Convey("Provided wrong AllowedWebMails to modify should result in old_allowedWebMails error", func() { + // allowedWebMails.Name = "" + // Convey("Too long or empty Name should return name error", func() { + // appError := asi.Update(&allowedWebMails, &allowedWebMailsNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Update.allowedWebMailsOld.PreSave", "model.allowedWebMails.name.app_error", nil, "")) + // allowedWebMails.Name = "thishastobeatoolongname.For this, it need to be more than 64 char lenght .............. So long. Plus it should be alpha numeric. I'll add the test later on." + // appError = asi.Update(&allowedWebMails, &allowedWebMailsNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Update.allowedWebMailsOld.PreSave", "model.allowedWebMails.name.app_error", nil, "")) + // }) + + // allowedWebMails.Name = "Correct Name" + // allowedWebMails.Link = "" + + // Convey("Empty link should result in link error", func() { + // appError = asi.Update(&allowedWebMails, &allowedWebMailsNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Update.allowedWebMailsOld.PreSave", "model.allowedWebMails.link.app_error", nil, "")) + // }) + // }) + + // Convey("Provided wrong AllowedWebMails to modify should result in newAllowedWebMails error", func() { + // allowedWebMailsNew.Name = "" + // Convey("Too long or empty Name should return name error", func() { + // appError := asi.Update(&allowedWebMails, &allowedWebMailsNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Update.allowedWebMailsNew.PreSave", "model.allowedWebMails.name.app_error", nil, "")) + // allowedWebMailsNew.Name = "thishastobeatoolongname.For this, it need to be more than 64 char lenght .............. So long. Plus it should be alpha numeric. I'll add the test later on." + // appError = asi.Update(&allowedWebMails, &allowedWebMailsNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Update.allowedWebMailsNew.PreSave", "model.allowedWebMails.name.app_error", nil, "")) + // }) + + // allowedWebMailsNew.Name = "Correct Name" + // allowedWebMailsNew.Link = "" + + // Convey("Empty link should result in link error", func() { + // appError = asi.Update(&allowedWebMails, &allowedWebMailsNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Update.allowedWebMailsNew.PreSave", "model.allowedWebMails.link.app_error", nil, "")) + // }) + // }) + db.Delete(&allowedWebMails) + db.Delete(&allowedWebMailsNew) + }) + // Convey("Testing Getters", t, func() { + // allowedWebMails0 := AllowedWebMails{ + // Name: "Troll Face", + // Link: "allowedWebMailss/trollface.svg", + // } + // allowedWebMails1 := AllowedWebMails{ + // Name: "Face Palm Old", + // Link: "allowedWebMailss/facepalmold.svg", + // } + // allowedWebMails1New := AllowedWebMails{ + // Name: "Face Palm", + // Link: "allowedWebMailss/facepalm.svg", + // } + // allowedWebMails2 := AllowedWebMails{ + // Name: "God", + // Link: "allowedWebMailss/docker.svg", + // } + // allowedWebMails3 := AllowedWebMails{ + // Name: "nOOb", + // Link: "allowedWebMailss/sparadra.svg", + // } + // asi.Save(&allowedWebMails0, db) + // asi.Save(&allowedWebMails1, db) + // asi.Update(&allowedWebMails1, &allowedWebMails1New, db) + // asi.Save(&allowedWebMails2, db) + // asi.Save(&allowedWebMails3, db) + // // Have to be after save so ID are up to date :O + // allowedWebMailsList := []AllowedWebMails{ + // allowedWebMails0, + // allowedWebMails1, + // allowedWebMails2, + // allowedWebMails3, + // } + + // Convey("We have to be able to find all allowedWebMailss in the db", func() { + // allowedWebMailss := asi.GetAll(db) + // So(allowedWebMailss, ShouldNotResemble, []AllowedWebMails{}) + // So(allowedWebMailss, ShouldResemble, allowedWebMailsList) + // }) + + // Convey("We have to be able to find an allowedWebMails from is name", func() { + // allowedWebMails := asi.GetByName(allowedWebMails0.Name, db) + // So(allowedWebMails, ShouldNotResemble, AllowedWebMails{}) + // So(allowedWebMails, ShouldResemble, allowedWebMails0) + // allowedWebMails = asi.GetByName(allowedWebMails2.Name, db) + // So(allowedWebMails, ShouldNotResemble, AllowedWebMails{}) + // So(allowedWebMails, ShouldResemble, allowedWebMails2) + // allowedWebMails = asi.GetByName(allowedWebMails3.Name, db) + // So(allowedWebMails, ShouldNotResemble, AllowedWebMails{}) + // So(allowedWebMails, ShouldResemble, allowedWebMails3) + // Convey("Should also work from updated value", func() { + // allowedWebMails = asi.GetByName(allowedWebMails1.Name, db) + // So(allowedWebMails, ShouldNotResemble, AllowedWebMails{}) + // So(allowedWebMails, ShouldResemble, allowedWebMails1) + // }) + // }) + + // Convey("We have to be able to find an allowedWebMails from is link", func() { + // allowedWebMails := asi.GetByLink(allowedWebMails0.Link, db) + // So(allowedWebMails, ShouldNotResemble, AllowedWebMails{}) + // So(allowedWebMails, ShouldResemble, allowedWebMails0) + // allowedWebMails = asi.GetByLink(allowedWebMails2.Link, db) + // So(allowedWebMails, ShouldNotResemble, AllowedWebMails{}) + // So(allowedWebMails, ShouldResemble, allowedWebMails2) + // allowedWebMails = asi.GetByLink(allowedWebMails3.Link, db) + // So(allowedWebMails, ShouldNotResemble, AllowedWebMails{}) + // So(allowedWebMails, ShouldResemble, allowedWebMails3) + // Convey("Should also work from updated value", func() { + // allowedWebMails = asi.GetByLink(allowedWebMails1.Link, db) + // So(allowedWebMails, ShouldNotResemble, AllowedWebMails{}) + // So(allowedWebMails, ShouldResemble, allowedWebMails1) + // }) + // }) + + // Convey("Searching for non existent allowedWebMails should return empty", func() { + // allowedWebMails := asi.GetByLink("The Mask", db) + // So(allowedWebMails, ShouldResemble, AllowedWebMails{}) + // allowedWebMails = asi.GetByName("Fantôme", db) + // So(allowedWebMails, ShouldResemble, AllowedWebMails{}) + // }) + + // db.Delete(&allowedWebMails0) + // db.Delete(&allowedWebMails1) + // db.Delete(&allowedWebMails2) + // db.Delete(&allowedWebMails3) + + // Convey("Searching all in empty table should return empty", func() { + // allowedWebMailss := asi.GetAll(db) + // So(allowedWebMailss, ShouldResemble, []AllowedWebMails{}) + // }) + // }) + + // Convey("Testing delete allowedWebMails", t, func() { + // dberror := u.NewLocAppError("allowedWebMailsStoreImpl.Delete", "update.transaction.delete.encounterError", nil, "") + // allowedWebMails0 := AllowedWebMails{ + // Name: "Troll Face", + // Link: "allowedWebMailss/trollface.svg", + // } + // allowedWebMails1 := AllowedWebMails{ + // Name: "Face Palm", + // Link: "allowedWebMailss/facepal.svg", + // } + // allowedWebMails2 := AllowedWebMails{ + // Name: "God", + // Link: "allowedWebMailss/docker.svg", + // } + // allowedWebMails3 := AllowedWebMails{ + // Name: "nOOb", + // Link: "allowedWebMailss/sparadra.svg", + // } + // asi.Save(&allowedWebMails0, db) + // asi.Save(&allowedWebMails1, db) + // asi.Save(&allowedWebMails2, db) + // asi.Save(&allowedWebMails3, db) + // allowedWebMails3Old := allowedWebMails3 + // allowedWebMailsList1 := []AllowedWebMails{ + // allowedWebMails0, + // allowedWebMails1, + // allowedWebMails2, + // allowedWebMails3Old, + // } + + // Convey("Deleting a known allowedWebMails should work", func() { + // appError := asi.Delete(&allowedWebMails2, db) + // So(appError, ShouldBeNil) + // So(appError, ShouldNotResemble, dberror) + // So(asi.GetByName("God", db), ShouldResemble, AllowedWebMails{}) + // }) + + // Convey("Trying to delete from non conform allowedWebMails should return specific allowedWebMails error and should not delete allowedWebMailss.", func() { + // allowedWebMails3.Name = "" + // Convey("Too long or empty Name should return name error", func() { + // appError := asi.Delete(&allowedWebMails3, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dberror) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Delete.allowedWebMails.PreSave", "model.allowedWebMails.name.app_error", nil, "")) + // So(asi.GetAll(db), ShouldResemble, allowedWebMailsList1) + // allowedWebMails3.Name = "thishastobeatoolongname.For this, it need to be more than 64 char lenght .............. So long. Plus it should be alpha numeric. I'll add the test later on." + // appError = asi.Delete(&allowedWebMails3, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dberror) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Delete.allowedWebMails.PreSave", "model.allowedWebMails.name.app_error", nil, "")) + // So(asi.GetAll(db), ShouldResemble, allowedWebMailsList1) + // }) + + // allowedWebMails3.Name = "nOOb" + // allowedWebMails3.Link = "" + + // Convey("Empty link should result in link error", func() { + // appError := asi.Delete(&allowedWebMails3, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dberror) + // So(appError, ShouldResemble, u.NewLocAppError("allowedWebMailsStoreImpl.Delete.allowedWebMails.PreSave", "model.allowedWebMails.link.app_error", nil, "")) + // So(asi.GetAll(db), ShouldResemble, allowedWebMailsList1) + // }) + // }) + + // db.Delete(&allowedWebMails0) + // db.Delete(&allowedWebMails1) + // db.Delete(&allowedWebMails2) + // db.Delete(&allowedWebMails3) + // }) +} diff --git a/datastores/data_store.go b/datastores/data_store.go index a26cd72..c8884c0 100644 --- a/datastores/data_store.go +++ b/datastores/data_store.go @@ -29,6 +29,7 @@ import ( // StoreInterface interface the Stores and usefull DB functions type StoreInterface interface { + AllowedWebMails() AllowedWebMailsStore Avatar() AvatarStore Channel() ChannelStore Emoji() EmojiStore @@ -37,8 +38,10 @@ type StoreInterface interface { Message() MessageStore Organisation() OrganisationStore Parameter() ParameterStore - User() UserStore + Read() ReadStore Role() RoleStore + UserParameter() UserParameterStore + User() UserStore InitConnection(user string, dbname string, password string, host string, port string) *gorm.DB InitDatabase(user string, dbname string, password string, host string, port string) CloseConnection(*gorm.DB) @@ -126,6 +129,17 @@ func (store StoreImpl) CloseConnection(db *gorm.DB) { defer db.Close() } +/*AllowedWebMailsStore interface the allowedWebMails communication */ +type AllowedWebMailsStore interface { + Save(allowedWebMails *models.AllowedWebMails, db *gorm.DB) *u.AppError + Update(allowedWebMails *models.AllowedWebMails, newAllowedWebMails *models.AllowedWebMails, db *gorm.DB) *u.AppError + GetByDomain(domain string, db *gorm.DB) models.AllowedWebMails + GetByProvider(provider string, db *gorm.DB) []models.AllowedWebMails + GetByID(ID uint64, db *gorm.DB) models.AllowedWebMails + GetAll(db *gorm.DB) []models.AllowedWebMails + Delete(allowedWebMails *models.AllowedWebMails, db *gorm.DB) *u.AppError +} + /*AvatarStore interface the avatar communication */ type AvatarStore interface { Save(avatar *models.Avatar, db *gorm.DB) *u.AppError @@ -217,6 +231,19 @@ type ParameterStore interface { Get(db *gorm.DB) models.Parameter } +/*ReadStore interface communication with read table*/ +type ReadStore interface { + Save(read *models.Read, db *gorm.DB) *u.AppError + Update(read *models.Read, newRead *models.Read, db *gorm.DB) *u.AppError + GetByID(ID uint64, db *gorm.DB) models.Read + GetChannelRead(user *models.User, channel *models.Channel, db *gorm.DB) models.Read + GetByUser(user *models.User, db *gorm.DB) []models.Read + GetByChannel(channel *models.Channel, db *gorm.DB) []models.Read + GetByMessage(message *models.Message, db *gorm.DB) []models.Read + GetAll(db *gorm.DB) []models.Read + Delete(read *models.Read, db *gorm.DB) *u.AppError +} + /*RoleStore interface the role communication*/ type RoleStore interface { Save(role *models.Role, db *gorm.DB) *u.AppError @@ -245,3 +272,14 @@ type UserStore interface { Delete(user *models.User, db *gorm.DB) *u.AppError Login(userName string, pass string, db *gorm.DB) (models.User, *u.AppError) } + +/*UserParameterStore interface the userUserParameter communication*/ +type UserParameterStore interface { + Save(userUserParameter *models.UserParameter, db *gorm.DB) *u.AppError + Update(userUserParameter *models.UserParameter, newUserParameter *models.UserParameter, db *gorm.DB) *u.AppError + Delete(userParameter *models.UserParameter, db *gorm.DB) *u.AppError + GetAll(db *gorm.DB) []models.UserParameter + GetByUser(user *models.User, db *gorm.DB) []models.UserParameter + GetByName(parameterName string, db *gorm.DB) []models.UserParameter + GetByID(id uint64, db *gorm.DB) models.UserParameter +} diff --git a/datastores/emojis_store_test.go b/datastores/emojis_store_test.go index cb9cc87..5f350e6 100644 --- a/datastores/emojis_store_test.go +++ b/datastores/emojis_store_test.go @@ -23,6 +23,7 @@ func TestEmojiStore(t *testing.T) { Shortcut: ":troll-face:", Link: "emojis/trollface.svg", } + db.Delete(&emoji) Convey("Given a correct emoji.", func() { appError := esi.Save(&emoji, db) Convey("Trying to add it for the first time, should be accepted", func() { @@ -54,6 +55,7 @@ func TestEmojiStore(t *testing.T) { Link: "emojis/trollface2.svg", } + db.Delete(&emoji) appError := esi.Save(&emoji, db) So(appError, ShouldBeNil) So(appError, ShouldNotResemble, dbError) diff --git a/datastores/folder_store_test.go b/datastores/folder_store_test.go index 00ae53c..638e96f 100644 --- a/datastores/folder_store_test.go +++ b/datastores/folder_store_test.go @@ -22,7 +22,7 @@ func TestFolderStore(t *testing.T) { msi := store.Message() standartRole := Role{ - RoleName: "teststandartazd", + RoleName: "teststandart", CanUsePrivate: true, CanModerate: true, CanArchive: true, @@ -30,6 +30,7 @@ func TestFolderStore(t *testing.T) { CanManage: false, CanManageUser: false, } + db.Delete(&standartRole) rsi.Save(&standartRole, db) userTest := User{ @@ -41,6 +42,7 @@ func TestFolderStore(t *testing.T) { LastName: "L", IDRole: standartRole.IDRole, } + db.Delete(&userTest) usi.Save(&userTest, db) channelTest := Channel{ @@ -51,6 +53,7 @@ func TestFolderStore(t *testing.T) { Subject: "Sujet", Avatar: "jesuiscool.svg", } + db.Delete(&channelTest) csi.Save(&channelTest, db) messageTest := Message{ @@ -58,6 +61,7 @@ func TestFolderStore(t *testing.T) { IDUser: userTest.IDUser, IDChannel: channelTest.IDChannel, } + db.Delete(&messageTest) msi.Save(&messageTest, db) Convey("Testing save function", t, func() { @@ -106,7 +110,6 @@ func TestFolderStore(t *testing.T) { // NickName: "LL", // FirstName: "Luky", // LastName: "Luke", - // Locale: "vn_VN", // IDRole: adminRole.IDRole, // } @@ -239,7 +242,6 @@ func TestFolderStore(t *testing.T) { // NickName: "LL", // FirstName: "Luky", // LastName: "Luke", - // Locale: "en_EN", // IDRole: adminRole.IDRole, // } // folder1 := Folder{ @@ -249,7 +251,6 @@ func TestFolderStore(t *testing.T) { // NickName: "thebrothers", // FirstName: "Joe", // LastName: "Dalton", - // Locale: "en_EN", // IDRole: standartRole.IDRole, // } // folder2 := Folder{ @@ -259,7 +260,6 @@ func TestFolderStore(t *testing.T) { // NickName: "Moris", // FirstName: "Moris", // LastName: "Gossiny", - // Locale: "fr_FR", // IDRole: ownerRole.IDRole, // } // folder1New := Folder{ @@ -269,7 +269,6 @@ func TestFolderStore(t *testing.T) { // NickName: "thebrothers", // FirstName: "Joe, Jack, William, Avrell", // LastName: "Dalton", - // Locale: "en_EN", // IDRole: guestRole.IDRole, // } // folder3 := Folder{ @@ -279,7 +278,6 @@ func TestFolderStore(t *testing.T) { // NickName: "JJ", // FirstName: "Jolly", // LastName: "Jumper", - // Locale: "en_EN", // IDRole: standartRole.IDRole, // } // folder4 := Folder{ @@ -289,7 +287,6 @@ func TestFolderStore(t *testing.T) { // NickName: "Kid", // FirstName: "Billy", // LastName: "The Kid", - // Locale: "en_EN", // IDRole: guestRole.IDRole, // } @@ -389,7 +386,6 @@ func TestFolderStore(t *testing.T) { // NickName: "LL", // FirstName: "Luky", // LastName: "Luke", - // Locale: "en_EN", // IDRole: adminRole.IDRole, // } // folder1 := Folder{ @@ -399,7 +395,6 @@ func TestFolderStore(t *testing.T) { // NickName: "thebrothers", // FirstName: "Joe", // LastName: "Dalton", - // Locale: "en_EN", // IDRole: standartRole.IDRole, // } // folder2 := Folder{ @@ -409,7 +404,6 @@ func TestFolderStore(t *testing.T) { // NickName: "Moris", // FirstName: "Moris", // LastName: "Gossiny", - // Locale: "fr_FR", // IDRole: ownerRole.IDRole, // } // folder3 := Folder{ @@ -419,7 +413,6 @@ func TestFolderStore(t *testing.T) { // NickName: "JJ", // FirstName: "Jolly", // LastName: "Jumper", - // Locale: "en_EN", // IDRole: standartRole.IDRole, // } diff --git a/datastores/members_store_test.go b/datastores/members_store_test.go index 87d1d17..54825d4 100644 --- a/datastores/members_store_test.go +++ b/datastores/members_store_test.go @@ -108,7 +108,6 @@ func TestMemberStore(t *testing.T) { // NickName: "LL", // FirstName: "Luky", // LastName: "Luke", - // Locale: "vn_VN", // IDRole: adminRole.IDRole, // } @@ -241,7 +240,6 @@ func TestMemberStore(t *testing.T) { // NickName: "LL", // FirstName: "Luky", // LastName: "Luke", - // Locale: "en_EN", // IDRole: adminRole.IDRole, // } // member1 := Member{ @@ -251,7 +249,6 @@ func TestMemberStore(t *testing.T) { // NickName: "thebrothers", // FirstName: "Joe", // LastName: "Dalton", - // Locale: "en_EN", // IDRole: standartRole.IDRole, // } // member2 := Member{ @@ -261,7 +258,6 @@ func TestMemberStore(t *testing.T) { // NickName: "Moris", // FirstName: "Moris", // LastName: "Gossiny", - // Locale: "fr_FR", // IDRole: ownerRole.IDRole, // } // member1New := Member{ @@ -271,7 +267,6 @@ func TestMemberStore(t *testing.T) { // NickName: "thebrothers", // FirstName: "Joe, Jack, William, Avrell", // LastName: "Dalton", - // Locale: "en_EN", // IDRole: guestRole.IDRole, // } // member3 := Member{ @@ -281,7 +276,6 @@ func TestMemberStore(t *testing.T) { // NickName: "JJ", // FirstName: "Jolly", // LastName: "Jumper", - // Locale: "en_EN", // IDRole: standartRole.IDRole, // } // member4 := Member{ @@ -291,7 +285,6 @@ func TestMemberStore(t *testing.T) { // NickName: "Kid", // FirstName: "Billy", // LastName: "The Kid", - // Locale: "en_EN", // IDRole: guestRole.IDRole, // } @@ -391,7 +384,6 @@ func TestMemberStore(t *testing.T) { // NickName: "LL", // FirstName: "Luky", // LastName: "Luke", - // Locale: "en_EN", // IDRole: adminRole.IDRole, // } // member1 := Member{ @@ -401,7 +393,6 @@ func TestMemberStore(t *testing.T) { // NickName: "thebrothers", // FirstName: "Joe", // LastName: "Dalton", - // Locale: "en_EN", // IDRole: standartRole.IDRole, // } // member2 := Member{ @@ -411,7 +402,6 @@ func TestMemberStore(t *testing.T) { // NickName: "Moris", // FirstName: "Moris", // LastName: "Gossiny", - // Locale: "fr_FR", // IDRole: ownerRole.IDRole, // } // member3 := Member{ @@ -421,7 +411,6 @@ func TestMemberStore(t *testing.T) { // NickName: "JJ", // FirstName: "Jolly", // LastName: "Jumper", - // Locale: "en_EN", // IDRole: standartRole.IDRole, // } diff --git a/datastores/read_store.go b/datastores/read_store.go new file mode 100644 index 0000000..104276d --- /dev/null +++ b/datastores/read_store.go @@ -0,0 +1,110 @@ +package datastores + +import ( + "github.com/jinzhu/gorm" + "github.com/titouanfreville/popcubeapi/models" + u "github.com/titouanfreville/popcubeapi/utils" +) + +// ReadStoreImpl Used to implement ReadStore interface +type ReadStoreImpl struct{} + +// Read Generate the struct for read store +func (s StoreImpl) Read() ReadStore { + return ReadStoreImpl{} +} + +// Save Use to save read in BB +func (msi ReadStoreImpl) Save(read *models.Read, db *gorm.DB) *u.AppError { + transaction := db.Begin() + if appError := read.IsValid(); appError != nil { + transaction.Rollback() + return u.NewLocAppError("readStoreImpl.Save.read.PreSave", appError.ID, nil, appError.DetailedError) + } + if !transaction.NewRecord(read) { + transaction.Rollback() + return u.NewLocAppError("readStoreImpl.Save", "save.transaction.create.already_exist", nil, "") + } + if err := transaction.Create(&read).Error; err != nil { + transaction.Rollback() + return u.NewLocAppError("readStoreImpl.Save", "save.transaction.create.encounterError :"+err.Error(), nil, "") + } + transaction.Commit() + return nil +} + +// Update Used to update read in DB +func (msi ReadStoreImpl) Update(read *models.Read, newRead *models.Read, db *gorm.DB) *u.AppError { + transaction := db.Begin() + if appError := read.IsValid(); appError != nil { + transaction.Rollback() + return u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", appError.ID, nil, appError.DetailedError) + } + // if appError := newRead.IsValid(); appError != nil { + // transaction.Rollback() + // return u.NewLocAppError("readStoreImpl.Update.readNew.PreSave", appError.ID, nil, appError.DetailedError) + // } + if err := transaction.Model(&read).Updates(&newRead).Error; err != nil { + transaction.Rollback() + return u.NewLocAppError("readStoreImpl.Update", "update.transaction.updates.encounterError :"+err.Error(), nil, "") + } + transaction.Commit() + return nil +} + +// GetAll Used to get read from DB +func (msi ReadStoreImpl) GetAll(db *gorm.DB) []models.Read { + reads := []models.Read{} + db.Find(&reads) + return reads +} + +// GetByID Used to get read from DB +func (msi ReadStoreImpl) GetByID(ID uint64, db *gorm.DB) models.Read { + read := models.Read{} + db.Where("idRead = ?", ID).First(&read) + return read +} + +// GetChannelRead get specific user in specific channel +func (msi ReadStoreImpl) GetChannelRead(user *models.User, channel *models.Channel, db *gorm.DB) models.Read { + read := models.Read{} + db.Table("reads").Select("*").Joins("natural join users natural join channels").Where("users.idUser = ? and channels.idChannel = ?", user.IDUser, channel.IDChannel).Find(&read) + return read +} + +// GetByUser get read from user +func (msi ReadStoreImpl) GetByUser(user *models.User, db *gorm.DB) []models.Read { + reads := []models.Read{} + db.Table("reads").Select("*").Joins("natural join users").Where("users.idUser = ?", user.IDUser).Find(&reads) + return reads +} + +// GetByChannel get read from channel +func (msi ReadStoreImpl) GetByChannel(channel *models.Channel, db *gorm.DB) []models.Read { + reads := []models.Read{} + db.Table("reads").Select("*").Joins("natural join channels").Where("channels.idChannel = ?", channel.IDChannel).Find(&reads) + return reads +} + +// GetByMessage get read from message +func (msi ReadStoreImpl) GetByMessage(message *models.Message, db *gorm.DB) []models.Read { + reads := []models.Read{} + db.Table("reads").Select("*").Joins("natural join messages").Where("messages.idMessage = ?", message.IDMessage).Find(&reads) + return reads +} + +// Delete Used to get read from DB +func (msi ReadStoreImpl) Delete(read *models.Read, db *gorm.DB) *u.AppError { + transaction := db.Begin() + if appError := read.IsValid(); appError != nil { + transaction.Rollback() + return u.NewLocAppError("readStoreImpl.Delete.read.PreSave", appError.ID, nil, appError.DetailedError) + } + if err := transaction.Delete(&read).Error; err != nil { + transaction.Rollback() + return u.NewLocAppError("readStoreImpl.Delete", "update.transaction.delete.encounterError :"+err.Error(), nil, "") + } + transaction.Commit() + return nil +} diff --git a/datastores/read_store_test.go b/datastores/read_store_test.go new file mode 100644 index 0000000..97e9ca3 --- /dev/null +++ b/datastores/read_store_test.go @@ -0,0 +1,467 @@ +// This file is used to test if read model is working correctly. +// A read is always linked to a read +// He has basic read to join +package datastores + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" + . "github.com/titouanfreville/popcubeapi/models" + u "github.com/titouanfreville/popcubeapi/utils" +) + +func TestReadStore(t *testing.T) { + store := Store() + db := store.InitConnection("root", "popcube_test", "popcube_dev", "database", "3306") + + resi := store.Read() + msi := store.Message() + usi := store.User() + rsi := store.Role() + csi := store.Channel() + + standartRole := Role{ + RoleName: randStringBytes(10), + CanUsePrivate: true, + CanModerate: true, + CanArchive: true, + CanInvite: false, + CanManage: false, + CanManageUser: false, + } + rsi.Save(&standartRole, db) + + userTest := User{ + Username: randStringBytes(10), + Password: "test", + Email: "test@popcube.fr", + NickName: "NickName", + FirstName: "Test", + LastName: "L", + IDRole: standartRole.IDRole, + } + usi.Save(&userTest, db) + + channelTest := Channel{ + ChannelName: randStringBytes(10), + Type: "audio", + Private: false, + Description: "Testing channel description :O", + Subject: "Sujet", + Avatar: "jesuiscool.svg", + } + csi.Save(&channelTest, db) + + messageTest := Message{ + Content: "Message test", + IDUser: userTest.IDUser, + IDChannel: channelTest.IDChannel, + } + msi.Save(&messageTest, db) + + Convey("Testing save function", t, func() { + dbError := u.NewLocAppError("readStoreImpl.Save", "save.transaction.create.encounterError", nil, "") + alreadyExistError := u.NewLocAppError("readStoreImpl.Save", "save.transaction.create.already_exist", nil, "") + read := Read{ + IDUser: userTest.IDUser, + IDChannel: channelTest.IDChannel, + IDMessage: messageTest.IDMessage, + } + + Convey("Given a correct read.", func() { + appError := resi.Save(&read, db) + Convey("Trying to add it for the first time, should be accepted", func() { + So(appError, ShouldBeNil) + So(appError, ShouldNotResemble, dbError) + So(appError, ShouldNotResemble, alreadyExistError) + }) + Convey("Trying to add it a second time should return duplicate error", func() { + appError2 := resi.Save(&read, db) + So(appError2, ShouldNotBeNil) + // So(appError2, ShouldResemble, alreadyExistError) + So(appError2, ShouldNotResemble, dbError) + }) + }) + db.Delete(&read) + }) + + // Convey("Testing update function", t, func() { + // dbError := u.NewLocAppError("readStoreImpl.Save", "save.transaction.create.encounterError", nil, "") + // alreadyExistError := u.NewLocAppError("readStoreImpl.Save", "save.transaction.create.already_exist", nil, "Read Name: electras") + // read := Read{ + // Readname: "TesT2", + // Password: "test", + // Email: "test2@popcube.fr", + // NickName: "NickName", + // FirstName: "Test", + // LastName: "L", + // IDRole: ownerRole.IDRole, + // } + // readNew := Read{ + // Readname: "lucky", + // Password: "lucke", + // Email: "luckylucke@popcube.fr", + // NickName: "LL", + // FirstName: "Luky", + // LastName: "Luke", + // IDRole: adminRole.IDRole, + // } + + // appError := resi.Save(&read, db) + // So(appError, ShouldBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + + // Convey("Provided correct Read to modify should not return errors", func() { + // appError := resi.Update(&read, &readNew, db) + // readShouldResemble := readNew + // readShouldResemble.WebID = read.WebID + // readShouldResemble.IDRead = read.IDRead + // readShouldResemble.LastUpdate = read.LastUpdate + // So(appError, ShouldBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(read, ShouldResemble, readShouldResemble) + // }) + + // Convey("Provided wrong old Read to modify should result in old_read error", func() { + // read.WebID = "TesT" + // Convey("Incorrect ID read should return a read invalid id", func() { + // appError := resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", "model.read.is_valid.WebID.app_error", nil, "")) + // }) + // read.WebID = NewID() + // Convey("Incorrect readname read should return error Invalid readname", func() { + // read.Readname = "CeNomDevraitJelespereEtreBeaucoupTropLongPourLatrailleMaximaleDemandeParcequelaJeSuiunPoilFeneantEtDeboussouleSansnuldouteilnyavaitpersone" + // appError := resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+read.WebID)) + // read.Readname = "" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+read.WebID)) + // read.Readname = "xD/" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+read.WebID)) + // read.Readname = "xD\\" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+read.WebID)) + // read.Readname = "xD*" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+read.WebID)) + // read.Readname = "xD{" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+read.WebID)) + // }) + + // Convey("Password can]t be empty", func() { + // read.Password = "" + // appError := resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readOld.PreSave", "model.read.is_valid.auth_data_pwd.app_error", nil, "read_webID="+read.WebID)) + // }) + // }) + + // Convey("Provided wrong new Read to modify should result in old_read error", func() { + // Convey("Incorrect readname read should return error Invalid readname", func() { + // readNew.Readname = "CeNomDevraitJelespereEtreBeaucoupTropLongPourLatrailleMaximaleDemandeParcequelaJeSuiunPoilFeneantEtDeboussouleSansnuldouteilnyavaitpersone" + // appError := resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readNew.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+readNew.WebID)) + // readNew.Readname = "" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readNew.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+readNew.WebID)) + // readNew.Readname = "xD/" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readNew.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+readNew.WebID)) + // readNew.Readname = "xD\\" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readNew.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+readNew.WebID)) + // readNew.Readname = "xD*" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readNew.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+readNew.WebID)) + // readNew.Readname = "xD{" + // appError = resi.Update(&read, &readNew, db) + // So(appError, ShouldNotBeNil) + // So(appError, ShouldNotResemble, dbError) + // So(appError, ShouldNotResemble, alreadyExistError) + // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Update.readNew.PreSave", "model.read.is_valid.Readname.app_error", nil, "read_webID="+readNew.WebID)) + // }) + // }) + + // db.Delete(&read) + // db.Delete(&readNew) + // }) + + // Convey("Testing Getters", t, func() { + // read0 := Read{ + // Readname: "lucky", + // Password: "lucke", + // Email: "luckylucke@popcube.fr", + // NickName: "LL", + // FirstName: "Luky", + // LastName: "Luke", + // IDRole: adminRole.IDRole, + // } + // read1 := Read{ + // Readname: "daltons", + // Password: "dalton", + // Email: "daltonsbrothers@popcube.fr", + // NickName: "thebrothers", + // FirstName: "Joe", + // LastName: "Dalton", + // IDRole: standartRole.IDRole, + // } + // read2 := Read{ + // Readname: "moris", + // Password: "gossiny", + // Email: "moris&gossiny@popcube.fr", + // NickName: "Moris", + // FirstName: "Moris", + // LastName: "Gossiny", + // IDRole: ownerRole.IDRole, + // } + // read1New := Read{ + // Readname: "daltons", + // Password: "dalton", + // Email: "daltonsbrothers@popcube.fr", + // NickName: "thebrothers", + // FirstName: "Joe, Jack, William, Avrell", + // LastName: "Dalton", + // IDRole: guestRole.IDRole, + // } + // read3 := Read{ + // Readname: "jolly", + // Password: "jumper", + // Email: "jollyjumper@popcube.fr", + // NickName: "JJ", + // FirstName: "Jolly", + // LastName: "Jumper", + // IDRole: standartRole.IDRole, + // } + // read4 := Read{ + // Readname: "billythekid", + // Password: "chocolat", + // Email: "billythekid@popcube.fr", + // NickName: "Kid", + // FirstName: "Billy", + // LastName: "The Kid", + // IDRole: guestRole.IDRole, + // } + + // resi.Save(&read0, db) + // resi.Save(&read1, db) + // resi.Update(&read1, &read1New, db) + // resi.Save(&read2, db) + // resi.Save(&read3, db) + // resi.Save(&read4, db) + + // // Have to be after save so ID are up to date :O + // readList := []Read{ + // read0, + // read1, + // read2, + // read3, + // read4, + // } + + // admins := []Read{read0} + // guests := []Read{read1, read4} + // emptyList := []Read{} + + // Convey("We have to be able to find all reads in the db", func() { + // reads := resi.GetAll(db) + // So(reads, ShouldNotResemble, &emptyList) + // So(reads, ShouldResemble, &readList) + // }) + + // Convey("We have to be able to find a read from is name", func() { + // read := resi.GetByReadName(read0.Readname, db) + // So(read, ShouldNotResemble, &Read{}) + // So(read, ShouldResemble, &read0) + // read = resi.GetByReadName(read2.Readname, db) + // So(read, ShouldNotResemble, &Read{}) + // So(read, ShouldResemble, &read2) + // read = resi.GetByReadName(read3.Readname, db) + // So(read, ShouldNotResemble, &Read{}) + // So(read, ShouldResemble, &read3) + // read = resi.GetByReadName(read4.Readname, db) + // So(read, ShouldNotResemble, &Read{}) + // So(read, ShouldResemble, &read4) + // Convey("Should also work from updated value", func() { + // read = resi.GetByReadName(read1New.Readname, db) + // So(read, ShouldNotResemble, &Read{}) + // So(read, ShouldResemble, &read1) + // }) + // }) + + // Convey("We have to be able to find a read from his email", func() { + // read := resi.GetByEmail(read0.Email, db) + // So(read, ShouldNotResemble, &Read{}) + // So(read, ShouldResemble, &read0) + // read = resi.GetByEmail(read2.Email, db) + // So(read, ShouldNotResemble, &Read{}) + // So(read, ShouldResemble, &read2) + // read = resi.GetByEmail(read3.Email, db) + // So(read, ShouldResemble, &read3) + // read = resi.GetByEmail(read4.Email, db) + // So(read, ShouldNotResemble, &Read{}) + // So(read, ShouldResemble, &read4) + // }) + + // Convey("We have to be able to find an read from his Role", func() { + // reads := resi.GetByRole(&adminRole, db) + // So(reads, ShouldNotResemble, &Read{}) + // So(reads, ShouldResemble, &admins) + // reads = resi.GetByRole(&guestRole, db) + // So(reads, ShouldNotResemble, &Read{}) + // So(reads, ShouldResemble, &guests) + + // }) + + // Convey("Searching for non existent read should return empty", func() { + // read := resi.GetByReadName("fantome", db) + // So(read, ShouldResemble, &Read{}) + // }) + + // db.Delete(&read0) + // db.Delete(&read1) + // db.Delete(&read1New) + // db.Delete(&read2) + // db.Delete(&read3) + + // Convey("Searching all in empty table should return empty", func() { + // reads := resi.GetAll(db) + // So(reads, ShouldResemble, &[]Read{}) + // }) + // }) + + // Convey("Testing delete read", t, func() { + // dberror := u.NewLocAppError("readStoreImpl.Delete", "update.transaction.delete.encounterError", nil, "") + // read0 := Read{ + // Readname: "lucky", + // Password: "lucke", + // Email: "luckylucke@popcube.fr", + // NickName: "LL", + // FirstName: "Luky", + // LastName: "Luke", + // IDRole: adminRole.IDRole, + // } + // read1 := Read{ + // Readname: "daltons", + // Password: "dalton", + // Email: "daltonsbrothers@popcube.fr", + // NickName: "thebrothers", + // FirstName: "Joe", + // LastName: "Dalton", + // IDRole: standartRole.IDRole, + // } + // read2 := Read{ + // Readname: "moris", + // Password: "gossiny", + // Email: "moris&gossiny@popcube.fr", + // NickName: "Moris", + // FirstName: "Moris", + // LastName: "Gossiny", + // IDRole: ownerRole.IDRole, + // } + // read3 := Read{ + // Readname: "jolly", + // Password: "jumper", + // Email: "jollyjumper@popcube.fr", + // NickName: "JJ", + // FirstName: "Jolly", + // LastName: "Jumper", + // IDRole: standartRole.IDRole, + // } + + // resi.Save(&read0, db) + // resi.Save(&read1, db) + // resi.Save(&read2, db) + // resi.Save(&read3, db) + + // // Have to be after save so ID are up to date :O + // // read3Old := read3 + // // readList1 := []Read{ + // // read0, + // // read1, + // // read2, + // // read3Old, + // // } + + // Convey("Deleting a known read should work", func() { + // appError := resi.Delete(&read2, db) + // So(appError, ShouldBeNil) + // So(appError, ShouldNotResemble, dberror) + // So(resi.GetByReadName("moris", db), ShouldResemble, &Read{}) + // }) + + // // Convey("Trying to delete from non conform read should return specific read error and should not delete reads.", func() { + // // read3.ReadName = "Const" + // // Convey("Too long or empty Name should return name error", func() { + // // appError := resi.Delete(&read3, db) + // // So(appError, ShouldNotBeNil) + // // So(appError, ShouldNotResemble, dberror) + // // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Delete.read.PreSave", "model.read.readname.app_error", nil, "")) + // // So(resi.GetAll(db), ShouldResemble, &readList1) + // // read3.ReadName = "+alpha" + // // appError = resi.Delete(&read3, db) + // // So(appError, ShouldNotBeNil) + // // So(appError, ShouldNotResemble, dberror) + // // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Delete.read.PreSave", "model.read.readname.app_error", nil, "")) + // // So(resi.GetAll(db), ShouldResemble, &readList1) + // // read3.ReadName = "alpha-numerique" + // // appError = resi.Delete(&read3, db)standartRole + // // So(appError, ShouldNotBeNil) + // // So(appError, ShouldNotResemble, dberror) + // // So(appError, ShouldResemble, u.NewLocAppError("readStoreImpl.Delete.read.PreSave", "model.read.readname.app_error", nil, "")) + // // So(resi.GetAll(db), ShouldResemble, &readList1) + // // }) + // // }) + + // db.Delete(&read0) + // db.Delete(&read1) + // db.Delete(&read2) + // db.Delete(&read3) + // }) + db.Delete(&userTest) + db.Delete(&channelTest) + db.Delete(&standartRole) + db.Delete(&messageTest) +} diff --git a/datastores/user_parameter_store.go b/datastores/user_parameter_store.go new file mode 100644 index 0000000..787aadb --- /dev/null +++ b/datastores/user_parameter_store.go @@ -0,0 +1,97 @@ +package datastores + +import ( + "github.com/jinzhu/gorm" + "github.com/titouanfreville/popcubeapi/models" + u "github.com/titouanfreville/popcubeapi/utils" +) + +// UserParameterStoreImpl implement UserParameterStore interface +type UserParameterStoreImpl struct{} + +// UserParameter Generate the struct for userParameter store +func (s StoreImpl) UserParameter() UserParameterStore { + return &UserParameterStoreImpl{} +} + +// Save Use to save userParameter in BB +func (psi UserParameterStoreImpl) Save(userParameter *models.UserParameter, db *gorm.DB) *u.AppError { + transaction := db.Begin() + // userParameter.IsValid + if appError := userParameter.IsValid(); appError != nil { + transaction.Rollback() + return u.NewLocAppError("userParameterStoreImpl.Save", appError.ID, nil, appError.DetailedError) + } + if !transaction.NewRecord(userParameter) { + transaction.Rollback() + return u.NewLocAppError("userParameterStoreImpl.Save", "save.transaction.create.already_exist", nil, "") + } + if err := transaction.Create(&userParameter).Error; err != nil { + transaction.Rollback() + return u.NewLocAppError("userParameterStoreImpl.Save", "save.transaction.create.encounterError :"+err.Error(), nil, "") + } + transaction.Commit() + return nil +} + +// Update Used to update userParameter in DB +func (psi UserParameterStoreImpl) Update(userParameter *models.UserParameter, newUserParameter *models.UserParameter, db *gorm.DB) *u.AppError { + transaction := db.Begin() + if appError := userParameter.IsValid(); appError != nil { + transaction.Rollback() + return u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", appError.ID, nil, appError.DetailedError) + } + // if appError := newUserParameter.IsValid(); appError != nil { + // transaction.Rollback() + // return u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", appError.ID, nil, appError.DetailedError) + // } + if err := transaction.Model(&userParameter).Updates(&newUserParameter).Error; err != nil { + transaction.Rollback() + return u.NewLocAppError("userParameterStoreImpl.Update", "update.transaction.updates.encounterError :"+err.Error(), nil, "") + } + transaction.Commit() + return nil +} + +// Delete Used to get userParameter from DB +func (psi UserParameterStoreImpl) Delete(userParameter *models.UserParameter, db *gorm.DB) *u.AppError { + transaction := db.Begin() + if appError := userParameter.IsValid(); appError != nil { + transaction.Rollback() + return u.NewLocAppError("userStoreImpl.Delete.userParameter.PreSave", appError.ID, nil, appError.DetailedError) + } + if err := transaction.Delete(&userParameter).Error; err != nil { + transaction.Rollback() + return u.NewLocAppError("userStoreImpl.Delete", "update.transaction.delete.encounterError :"+err.Error(), nil, "") + } + transaction.Commit() + return nil +} + +// GetAll Used to get userParameter from DB +func (psi UserParameterStoreImpl) GetAll(db *gorm.DB) []models.UserParameter { + userParameters := []models.UserParameter{} + db.Find(&userParameters) + return userParameters +} + +// GetByUser get userParameter from user +func (psi UserParameterStoreImpl) GetByUser(user *models.User, db *gorm.DB) []models.UserParameter { + userParameters := []models.UserParameter{} + db.Table("user_parameters").Select("*").Joins("natural join users").Where("users.idUser = ?", user.IDUser).Find(&userParameters) + return userParameters +} + +// GetByName get userParameter from user +func (psi UserParameterStoreImpl) GetByName(parameterName string, db *gorm.DB) []models.UserParameter { + userParameters := []models.UserParameter{} + db.Where("parameterName = ?", parameterName).Find(&userParameters) + return userParameters +} + +// GetByID Used to get userParameter from DB +func (psi UserParameterStoreImpl) GetByID(ID uint64, db *gorm.DB) models.UserParameter { + userParameter := models.UserParameter{} + db.Where("idUserParameter = ?", ID).First(&userParameter) + return userParameter +} diff --git a/datastores/user_parameter_store_test.go b/datastores/user_parameter_store_test.go new file mode 100644 index 0000000..f1800f8 --- /dev/null +++ b/datastores/user_parameter_store_test.go @@ -0,0 +1,249 @@ +// This file is used to test if user model is working correctly. +// A user is always linked to an userParameter +// He has bpsic channel to join +package datastores + +import ( + "strconv" + "testing" + + . "github.com/smartystreets/goconvey/convey" + . "github.com/titouanfreville/popcubeapi/models" + u "github.com/titouanfreville/popcubeapi/utils" +) + +func genUPlocalError(locale string) *u.AppError { + return u.NewLocAppError("userParameterStoreImpl.Save", "too long local", nil, "The local : "+locale+" can not be manage. Max size for local is 5.") +} + +func genUPtimeZoneError(tz string) *u.AppError { + return u.NewLocAppError("userParameterStoreImpl.Save", "too long timeZone", nil, "The TimeZone : "+tz+" can not be manage. Max size for local is 4.") +} + +func genUPsleepError(part string, time int) *u.AppError { + return u.NewLocAppError("userParameterStoreImpl.Save", "invalid hour", nil, "The sleep "+part+" time: "+strconv.Itoa(time)+"ms is not valable. It has to be between 0 and 1440.") +} + +func TestUserParameterStore(t *testing.T) { + store := Store() + db := store.InitConnection("root", "popcube_test", "popcube_dev", "database", "3306") + psi := store.UserParameter() + usi := store.User() + rsi := store.Role() + + standartRole := Role{ + RoleName: randStringBytes(10), + CanUsePrivate: true, + CanModerate: true, + CanArchive: true, + CanInvite: false, + CanManage: false, + CanManageUser: false, + } + db.Delete(&standartRole) + rsi.Save(&standartRole, db) + + userTest := User{ + Username: randStringBytes(10), + Password: "test", + Email: "test@popcube.fr", + NickName: "NickName", + FirstName: "Test", + LastName: "L", + IDRole: standartRole.IDRole, + } + db.Delete(&userTest) + usi.Save(&userTest, db) + Convey("Testing save function", t, func() { + dbError := u.NewLocAppError("userParameterStoreImpl.Save", "save.transaction.create.encounterError", nil, "") + alreadyexistError := u.NewLocAppError("userParameterStoreImpl.Save", "save.transaction.create.already_exist", nil, "") + userParameter := UserParameter{ + IDUser: userTest.IDUser, + ParameterName: "test", + Local: "en_EN", + TimeZone: "UTC+2", + SleepStart: 280, + SleepEnd: 12, + } + db.Delete(userParameter) + Convey("Given a correct userParameter.", func() { + appError := psi.Save(&userParameter, db) + Convey("Trying to add it for the first time, should be accepted", func() { + So(appError, ShouldBeNil) + So(appError, ShouldNotResemble, dbError) + So(appError, ShouldNotResemble, alreadyexistError) + }) + // Convey("Trying to add it a second time should return duplicate error", func() { + // appError2 := psi.Save(&userParameter, db) + // So(appError2, ShouldNotBeNil) + // So(appError2, ShouldResemble, alreadyexistError) + // So(appError2, ShouldNotResemble, dbError) + // }) + }) + Convey("Given an incorrect userParameter.", func() { + userParameter.Local = "en_ENGA" + Convey("Given empty local or too long local should return Local error", func() { + appError := psi.Save(&userParameter, db) + So(appError, ShouldResemble, genUPlocalError(userParameter.Local)) + }) + userParameter.Local = "en_EN" + userParameter.TimeZone = "UTF+134" + Convey("Given empty time zone or too long time zone should return Time Zone error", func() { + appError := psi.Save(&userParameter, db) + So(appError, ShouldResemble, genUPtimeZoneError(userParameter.TimeZone)) + }) + userParameter.TimeZone = "UTF+12" + userParameter.SleepEnd = -1 + Convey("Given negative or too big Sleep timers should return sleep error", func() { + appError := psi.Save(&userParameter, db) + So(appError, ShouldResemble, genUPsleepError("end", userParameter.SleepEnd)) + userParameter.SleepEnd = 1441 + appError = psi.Save(&userParameter, db) + So(appError, ShouldResemble, genUPsleepError("end", userParameter.SleepEnd)) + userParameter.SleepEnd = 10 + userParameter.SleepStart = -10 + appError = psi.Save(&userParameter, db) + So(appError, ShouldResemble, genUPsleepError("start", userParameter.SleepStart)) + userParameter.SleepStart = 2000 + appError = psi.Save(&userParameter, db) + So(appError, ShouldResemble, genUPsleepError("start", userParameter.SleepStart)) + }) + }) + db.Delete(&userParameter) + }) + + Convey("Testing update function", t, func() { + userParameter := UserParameter{ + IDUser: userTest.IDUser, + ParameterName: "test", + Local: "en_EN", + TimeZone: "UTC+2", + SleepStart: 280, + SleepEnd: 12, + } + newUserParameter := UserParameter{ + IDUser: userTest.IDUser, + ParameterName: "test", + Local: "vn_VN", + TimeZone: "UTC+10", + SleepStart: 281, + SleepEnd: 13, + } + db.Delete(userParameter) + appError := psi.Save(&userParameter, db) + dbError := u.NewLocAppError("userParameterStoreImpl.Update", "update.transaction.updates.encounterError", nil, "") + So(appError, ShouldBeNil) + So(appError, ShouldNotResemble, dbError) + Convey("Providing a correct user to update", func() { + appError := psi.Update(&userParameter, &newUserParameter, db) + So(appError, ShouldBeNil) + So(appError, ShouldNotResemble, dbError) + }) + // Convey("Providing an incorrect user as new should result in errors", func() { + // empty := UserParameter{} + // Convey("Empty userParameter should return first error from is valid error", func() { + // appError := psi.Update(&userParameter, &empty, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_local.app_error", nil, "")) + // }) + // newUserParameter.Local = "en_ENG" + // Convey("Given empty local or too long local should return Local error", func() { + // appError := psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_local.app_error", nil, "")) + // newUserParameter.Local = "" + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_local.app_error", nil, "")) + // }) + // newUserParameter.Local = "en_EN" + // newUserParameter.TimeZone = "UTF+134" + // Convey("Given empty time zone or too long time zone should return Time Zone error", func() { + // appError := psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_timezone.app_error", nil, "")) + // newUserParameter.TimeZone = "" + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_timezone.app_error", nil, "")) + // }) + // newUserParameter.TimeZone = "UTF+12" + // newUserParameter.SleepEnd = -1 + // Convey("Given negative or too big Sleep timers should return sleep error", func() { + // appError := psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_sleep_end.app_error", nil, "")) + // newUserParameter.SleepEnd = 1441 + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_sleep_end.app_error", nil, "")) + // newUserParameter.SleepEnd = 10 + // newUserParameter.SleepStart = -10 + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_sleep_start.app_error", nil, "")) + // newUserParameter.SleepStart = 2000 + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterNew.PreSave", "model.userParameter.is_valid.userParameter_sleep_start.app_error", nil, "")) + // }) + // }) + + // Convey("Providing an incorrect user as old should result in errors", func() { + // empty := UserParameter{} + // Convey("Empty userParameter should return first error from is valid error", func() { + // appError := psi.Update(&empty, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_local.app_error", nil, "")) + // }) + // userParameter.Local = "en_ENG" + // Convey("Given empty local or too long local should return Local error", func() { + // appError := psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_local.app_error", nil, "")) + // userParameter.Local = "" + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_local.app_error", nil, "")) + // }) + // userParameter.Local = "en_EN" + // userParameter.TimeZone = "UTF+134" + // Convey("Given empty time zone or too long time zone should return Time Zone error", func() { + // appError := psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_timezone.app_error", nil, "")) + // userParameter.TimeZone = "" + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_timezone.app_error", nil, "")) + // }) + // userParameter.TimeZone = "UTF+12" + // userParameter.SleepEnd = -1 + // Convey("Given negative or too big Sleep timers should return sleep error", func() { + // appError := psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_sleep_end.app_error", nil, "")) + // userParameter.SleepEnd = 1441 + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_sleep_end.app_error", nil, "")) + // userParameter.SleepEnd = 10 + // userParameter.SleepStart = -10 + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_sleep_start.app_error", nil, "")) + // userParameter.SleepStart = 2000 + // appError = psi.Update(&userParameter, &newUserParameter, db) + // So(appError, ShouldResemble, u.NewLocAppError("userParameterStoreImpl.Update.userParameterOld.PreSave", "model.userParameter.is_valid.userParameter_sleep_start.app_error", nil, "")) + // }) + // }) + db.Delete(&userParameter) + db.Delete(&newUserParameter) + }) + + // Convey("Testing Get function", t, func() { + // userParameter := UserParameter{ + // Local: "vi_VI", + // TimeZone: "UTC+6", + // SleepStart: 260, + // SleepEnd: 24, + // } + // Convey("Trying to get userParameter from empty DB should return empty", func() { + // So(psi.GetAll(db), ShouldResemble, UserParameter{}) + // }) + // appError := psi.Save(&userParameter, db) + // So(appError, ShouldBeNil) + // Convey("Trying to get userParameter from non empty DB should return a correct userParameter object", func() { + // got := psi.GetAll(db) + // So(got, ShouldResemble, userParameter) + // // So(got.IsValid(), ShouldBeNil) + // }) + // db.Delete(&userParameter) + // }) + + db.Delete(&userTest) + db.Delete(&standartRole) +} diff --git a/datastores/user_store_test.go b/datastores/user_store_test.go index 1e002d7..c880b0b 100644 --- a/datastores/user_store_test.go +++ b/datastores/user_store_test.go @@ -109,7 +109,6 @@ func TestUserStore(t *testing.T) { NickName: "LL", FirstName: "Luky", LastName: "Luke", - Locale: "vn_VN", IDRole: adminRole.IDRole, } @@ -242,7 +241,6 @@ func TestUserStore(t *testing.T) { NickName: "LL", FirstName: "Luky", LastName: "Luke", - Locale: "en_EN", IDRole: adminRole.IDRole, } user1 := User{ @@ -252,7 +250,6 @@ func TestUserStore(t *testing.T) { NickName: "thebrothers", FirstName: "Joe", LastName: "Dalton", - Locale: "en_EN", IDRole: standartRole.IDRole, } user2 := User{ @@ -262,7 +259,6 @@ func TestUserStore(t *testing.T) { NickName: "Moris", FirstName: "Moris", LastName: "Gossiny", - Locale: "fr_FR", IDRole: ownerRole.IDRole, } user1New := User{ @@ -272,7 +268,6 @@ func TestUserStore(t *testing.T) { NickName: "thebrothers", FirstName: "Joe, Jack, William, Avrell", LastName: "Dalton", - Locale: "en_EN", IDRole: guestRole.IDRole, } user3 := User{ @@ -282,7 +277,6 @@ func TestUserStore(t *testing.T) { NickName: "JJ", FirstName: "Jolly", LastName: "Jumper", - Locale: "en_EN", IDRole: standartRole.IDRole, } user4 := User{ @@ -292,7 +286,6 @@ func TestUserStore(t *testing.T) { NickName: "Kid", FirstName: "Billy", LastName: "The Kid", - Locale: "en_EN", IDRole: guestRole.IDRole, } @@ -392,7 +385,6 @@ func TestUserStore(t *testing.T) { NickName: "LL", FirstName: "Luky", LastName: "Luke", - Locale: "en_EN", IDRole: adminRole.IDRole, } user1 := User{ @@ -402,7 +394,6 @@ func TestUserStore(t *testing.T) { NickName: "thebrothers", FirstName: "Joe", LastName: "Dalton", - Locale: "en_EN", IDRole: standartRole.IDRole, } user2 := User{ @@ -412,7 +403,6 @@ func TestUserStore(t *testing.T) { NickName: "Moris", FirstName: "Moris", LastName: "Gossiny", - Locale: "fr_FR", IDRole: ownerRole.IDRole, } user3 := User{ @@ -422,7 +412,6 @@ func TestUserStore(t *testing.T) { NickName: "JJ", FirstName: "Jolly", LastName: "Jumper", - Locale: "en_EN", IDRole: standartRole.IDRole, } diff --git a/docker/goconvey.Dockerfile b/docker/goconvey.Dockerfile index 8cbe0d2..590eea8 100644 --- a/docker/goconvey.Dockerfile +++ b/docker/goconvey.Dockerfile @@ -2,7 +2,7 @@ FROM registry.le-corre.eu:5000/go:base MAINTAINER Clement LE CORRE ENV TERM xterm-256color ENV GOCOPYPATH /go/src/github.com/titouanfreville/popcubeapi - +ENV MYSQL_DATABASE popcube_test EXPOSE 8080 WORKDIR $GOCOPYPATH diff --git a/main.go b/main.go index 47e6eac..b26a8f8 100644 --- a/main.go +++ b/main.go @@ -14,7 +14,7 @@ var ( ) func getConf(dbSettings *configs.DbConnection, serverSetting *configs.APIServerInfo) { - *dbSettings, *serverSetting = configs.InitConfig() + *dbSettings, *serverSetting, _ = configs.InitConfig() } func initAPI() { diff --git a/models/allowedWebMails.go b/models/allowedWebMails.go index 52f1eda..ebaffd4 100644 --- a/models/allowedWebMails.go +++ b/models/allowedWebMails.go @@ -21,13 +21,13 @@ type AllowedWebMails struct { // // min: 0 IDAllowedWebMails uint64 `gorm:"primary_key;column:idAllowedWebMails;AUTO_INCREMENT" json:"id,omitempty"` - // Mail provider - // required: true - Provider string `gorm:"column:provider;not null;" json:"provider,omitempty"` // Domain name of the allowedWebMails - Domain string `gorm:"column:domain" json:"domain,omitempty"` + // required: true + Domain string `gorm:"column:domain; unique; not null;" json:"domain,omitempty"` + // Mail provider + Provider string `gorm:"column:provider" json:"provider,omitempty"` // Rights that will automatically atributed to user created accound from the webmail - DefaultRights string `gorm:"column:description" json:"description,omitempty"` + DefaultRights string `gorm:"column:defaultRights" json:"defaultRights,omitempty"` } // IsValid check validity of object before saving in DB diff --git a/models/folders_test.go b/models/folders_test.go index 62900ac..1d80551 100644 --- a/models/folders_test.go +++ b/models/folders_test.go @@ -23,7 +23,6 @@ func TestFolderModel(t *testing.T) { Role: Owner, LastPasswordUpdate: 20, FailedAttempts: 1, - Locale: "vi", } channelTest := Channel{ diff --git a/models/message_test.go b/models/message_test.go index 98ce468..95a5940 100644 --- a/models/message_test.go +++ b/models/message_test.go @@ -23,7 +23,6 @@ func TestMessageModel(t *testing.T) { Role: Owner, LastPasswordUpdate: 20, FailedAttempts: 1, - Locale: "vi", } channelTest := Channel{ diff --git a/models/userParameter.go b/models/userParameter.go index bb23ff3..86d6c73 100644 --- a/models/userParameter.go +++ b/models/userParameter.go @@ -22,7 +22,7 @@ type UserParameter struct { // id of the user who parameter can be applied to IDUser uint64 `gorm:"column:idUser; not null" json:"id,omitempty"` // required true - ParameterName string `gorm:"column: parameterName" json:"parameter_name, omitempty"` + ParameterName string `gorm:"column:parameterName" json:"parameter_name, omitempty"` // Default langage // // required: true @@ -48,11 +48,11 @@ func (userParameter *UserParameter) IsValid() *u.AppError { } if len(userParameter.Local) > localMaxSize { - return u.NewLocAppError("UserParameter.IsValid", "too long local", nil, "The local :"+userParameter.Local+" can not be manage. Max size for local is 5") + return u.NewLocAppError("UserParameter.IsValid", "too long local", nil, "The local : "+userParameter.Local+" can not be manage. Max size for local is 5.") } if len(userParameter.TimeZone) > timeZoneMaxSize { - return u.NewLocAppError("UserParameter.IsValid", "too long timeZone", nil, "The TimeZone :"+userParameter.TimeZone+" can not be manage. Max size for local is 4") + return u.NewLocAppError("UserParameter.IsValid", "too long timeZone", nil, "The TimeZone : "+userParameter.TimeZone+" can not be manage. Max size for local is 4.") } if userParameter.SleepStart < 0 || userParameter.SleepStart > maxTime { diff --git a/models/userParameter_test.go b/models/userParameter_test.go index 9d4ee2e..bbd5fbb 100644 --- a/models/userParameter_test.go +++ b/models/userParameter_test.go @@ -8,6 +8,18 @@ import ( u "github.com/titouanfreville/popcubeapi/utils" ) +func genUPlocalError(locale string) *u.AppError { + return u.NewLocAppError("UserParameter.IsValid", "too long local", nil, "The local : "+locale+" can not be manage. Max size for local is 5.") +} + +func genUPtimeZoneError(tz string) *u.AppError { + return u.NewLocAppError("UserParameter.IsValid", "too long timeZone", nil, "The TimeZone : "+tz+" can not be manage. Max size for local is 4.") +} + +func genUPsleepError(part string, time int) *u.AppError { + return u.NewLocAppError("UserParameter.IsValid", "invalid hour", nil, "The sleep "+part+" time: "+strconv.Itoa(time)+"ms is not valable. It has to be between 0 and 1440.") +} + func TestUserParameterModel(t *testing.T) { Convey("Testing IsValid function", t, func() { userParameter := UserParameter{ @@ -19,88 +31,84 @@ func TestUserParameterModel(t *testing.T) { SleepEnd: 12, } nameError := u.NewLocAppError("UserParameter.IsValid", "parameter name Undefined", nil, "") - localError := u.NewLocAppError("UserParameter.IsValid", "too long local", nil, "The local :"+userParameter.Local+" can not be manage. Max size for local is 5") - timeZoneError := u.NewLocAppError("UserParameter.IsValid", "too long timeZone", nil, "The TimeZone :"+userParameter.TimeZone+" can not be manage. Max size for local is 4") - sleepStartError := u.NewLocAppError("UserParameter.IsValid", "invalid hour", nil, "The sleep start time: "+strconv.Itoa(userParameter.SleepStart)+"ms is not valable. It has to be between 0 and 1440.") - sleepEndError := u.NewLocAppError("UserParameter.IsValid", "invalid hour", nil, "The sleep end time: "+strconv.Itoa(userParameter.SleepEnd)+"ms is not valable. It has to be between 0 and 1440.") Convey("Given a correct userParameter. UserParameter should be validate", func() { So(userParameter.IsValid(), ShouldBeNil) So(userParameter.IsValid(), ShouldNotResemble, nameError) - So(userParameter.IsValid(), ShouldNotResemble, localError) - So(userParameter.IsValid(), ShouldNotResemble, timeZoneError) - So(userParameter.IsValid(), ShouldNotResemble, sleepStartError) - So(userParameter.IsValid(), ShouldNotResemble, sleepEndError) + So(userParameter.IsValid(), ShouldNotResemble, genUPlocalError(userParameter.Local)) + So(userParameter.IsValid(), ShouldNotResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("start", userParameter.SleepStart)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("end", userParameter.SleepEnd)) }) Convey("Given an incorrect userParameter. UserParameter should be refused", func() { empty := UserParameter{} userParameter.ParameterName = "" Convey("Empty userParameter should return first error from is valid error", func() { - So(userParameter.IsValid(), ShouldNotBeNil) - So(userParameter.IsValid(), ShouldResemble, nameError) - So(userParameter.IsValid(), ShouldNotResemble, localError) - So(userParameter.IsValid(), ShouldNotResemble, timeZoneError) - So(userParameter.IsValid(), ShouldNotResemble, sleepStartError) - So(userParameter.IsValid(), ShouldNotResemble, sleepEndError) + So(empty.IsValid(), ShouldNotBeNil) + So(empty.IsValid(), ShouldResemble, nameError) + So(empty.IsValid(), ShouldNotResemble, genUPlocalError(userParameter.Local)) + So(empty.IsValid(), ShouldNotResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(empty.IsValid(), ShouldNotResemble, genUPsleepError("start", userParameter.SleepStart)) + So(empty.IsValid(), ShouldNotResemble, genUPsleepError("end", userParameter.SleepEnd)) }) - Convey("Empty userParameter name should return local error", func() { + Convey("Empty userParameter name should return name error", func() { So(userParameter.IsValid(), ShouldNotBeNil) So(userParameter.IsValid(), ShouldResemble, nameError) - So(userParameter.IsValid(), ShouldNotResemble, localError) - So(userParameter.IsValid(), ShouldNotResemble, timeZoneError) - So(userParameter.IsValid(), ShouldNotResemble, sleepStartError) - So(userParameter.IsValid(), ShouldNotResemble, sleepEndError) + So(userParameter.IsValid(), ShouldNotResemble, genUPlocalError(userParameter.Local)) + So(userParameter.IsValid(), ShouldNotResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("start", userParameter.SleepStart)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("end", userParameter.SleepEnd)) }) + userParameter.ParameterName = "test" userParameter.Local = "en_ENG" Convey("Given too long local should return Local error", func() { So(userParameter.IsValid(), ShouldNotBeNil) So(userParameter.IsValid(), ShouldNotResemble, nameError) - So(userParameter.IsValid(), ShouldResemble, localError) - So(userParameter.IsValid(), ShouldNotResemble, timeZoneError) - So(userParameter.IsValid(), ShouldNotResemble, sleepStartError) - So(userParameter.IsValid(), ShouldNotResemble, sleepEndError) + So(userParameter.IsValid(), ShouldResemble, genUPlocalError(userParameter.Local)) + So(userParameter.IsValid(), ShouldNotResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("start", userParameter.SleepStart)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("end", userParameter.SleepEnd)) }) userParameter.Local = "en_EN" userParameter.TimeZone = "UTF+134" Convey("Given empty time zone or too long time zone should return Time Zone error", func() { So(userParameter.IsValid(), ShouldNotBeNil) So(userParameter.IsValid(), ShouldNotResemble, nameError) - So(userParameter.IsValid(), ShouldNotResemble, localError) - So(userParameter.IsValid(), ShouldResemble, timeZoneError) - So(userParameter.IsValid(), ShouldNotResemble, sleepStartError) - So(userParameter.IsValid(), ShouldNotResemble, sleepEndError) + So(userParameter.IsValid(), ShouldNotResemble, genUPlocalError(userParameter.Local)) + So(userParameter.IsValid(), ShouldResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("start", userParameter.SleepStart)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("end", userParameter.SleepEnd)) }) userParameter.TimeZone = "UTF+12" - userParameter.SleepEnd = -1 + userParameter.SleepStart = -1 Convey("Given negative or too big Sleep timers should return sleep error", func() { So(userParameter.IsValid(), ShouldNotBeNil) So(userParameter.IsValid(), ShouldNotResemble, nameError) - So(userParameter.IsValid(), ShouldNotResemble, localError) - So(userParameter.IsValid(), ShouldNotResemble, timeZoneError) - So(userParameter.IsValid(), ShouldResemble, sleepStartError) - So(userParameter.IsValid(), ShouldNotResemble, sleepEndError) - userParameter.SleepEnd = 1441 + So(userParameter.IsValid(), ShouldNotResemble, genUPlocalError(userParameter.Local)) + So(userParameter.IsValid(), ShouldNotResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(userParameter.IsValid(), ShouldResemble, genUPsleepError("start", userParameter.SleepStart)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("end", userParameter.SleepEnd)) + userParameter.SleepStart = 1441 So(userParameter.IsValid(), ShouldNotBeNil) So(userParameter.IsValid(), ShouldNotResemble, nameError) - So(userParameter.IsValid(), ShouldNotResemble, localError) - So(userParameter.IsValid(), ShouldNotResemble, timeZoneError) - So(userParameter.IsValid(), ShouldResemble, sleepStartError) - So(userParameter.IsValid(), ShouldNotResemble, sleepEndError) - userParameter.SleepEnd = 10 - userParameter.SleepStart = -10 + So(userParameter.IsValid(), ShouldNotResemble, genUPlocalError(userParameter.Local)) + So(userParameter.IsValid(), ShouldNotResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(userParameter.IsValid(), ShouldResemble, genUPsleepError("start", userParameter.SleepStart)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("end", userParameter.SleepEnd)) + userParameter.SleepStart = 10 + userParameter.SleepEnd = -10 So(userParameter.IsValid(), ShouldNotBeNil) So(userParameter.IsValid(), ShouldNotResemble, nameError) - So(userParameter.IsValid(), ShouldNotResemble, localError) - So(userParameter.IsValid(), ShouldNotResemble, timeZoneError) - So(userParameter.IsValid(), ShouldNotResemble, sleepStartError) - So(userParameter.IsValid(), ShouldResemble, sleepEndError) - userParameter.SleepStart = 2000 - So(userParameter.IsValid(), ShouldResemble, u.NewLocAppError("UserParameter.IsValid", "model.userParameter.is_valid.userParameter_sleep_start.app_error", nil, "")) + So(userParameter.IsValid(), ShouldNotResemble, genUPlocalError(userParameter.Local)) + So(userParameter.IsValid(), ShouldNotResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("start", userParameter.SleepStart)) + So(userParameter.IsValid(), ShouldResemble, genUPsleepError("end", userParameter.SleepEnd)) + userParameter.SleepEnd = 2000 So(userParameter.IsValid(), ShouldNotBeNil) So(userParameter.IsValid(), ShouldNotResemble, nameError) - So(userParameter.IsValid(), ShouldNotResemble, localError) - So(userParameter.IsValid(), ShouldNotResemble, timeZoneError) - So(userParameter.IsValid(), ShouldNotResemble, sleepStartError) - So(userParameter.IsValid(), ShouldResemble, sleepEndError) + So(userParameter.IsValid(), ShouldNotResemble, genUPlocalError(userParameter.Local)) + So(userParameter.IsValid(), ShouldNotResemble, genUPtimeZoneError(userParameter.TimeZone)) + So(userParameter.IsValid(), ShouldNotResemble, genUPsleepError("start", userParameter.SleepStart)) + So(userParameter.IsValid(), ShouldResemble, genUPsleepError("end", userParameter.SleepEnd)) }) }) }) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index ebf58d2..f28877e 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -53,7 +53,7 @@ curl -X POST --header 'Content-Type: application/json' \ \"MYSQL_PASSWORD=test\", \"MYSQL_ROOT_PASSWORD=popcube_dev\", \"MYSQL_USER=test_user\", - \"MYSQL_DATABASE=popcube_test\" + \"MYSQL_DATABASE=popcube_dev\" ], \"Hostname\": \"popcube_alpha_database\" }" \ http://${DEPLOY_URL}/deploy; diff --git a/scripts/init.sql b/scripts/init.sql index 13abe2a..3688dd4 100644 --- a/scripts/init.sql +++ b/scripts/init.sql @@ -1,5 +1,5 @@ -- MySQL Script generated by MySQL Workbench --- lun. 13 févr. 2017 21:37:59 CET +-- sam. 11 mars 2017 19:32:40 CET -- Model: New Model Version: 1.0 -- MySQL Workbench Forward Engineering @@ -8,105 +8,84 @@ SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES'; -- ----------------------------------------------------- --- Schema popcube_test +-- Schema popcube -- ----------------------------------------------------- -CREATE SCHEMA IF NOT EXISTS `popcube_test` DEFAULT CHARACTER SET utf8 ; -USE `popcube_test` ; -- ----------------------------------------------------- --- Table `popcube_test`.`roles` +-- Schema popcube -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`roles` ( - `idRole` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `roleName` VARCHAR(45) NOT NULL, - `canUsePrivate` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Can create private channels\n', - `canModerate` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can moderate channel\nuser did not create\n', - `canArchive` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can archive channel \nuser did not create\n', - `canInvite` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can invite new member\nin organisation', - `canManage` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can manage organisation\n(update information,\nadd bots, add plugins).\n', - `canManageUser` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Role name ~~', - PRIMARY KEY (`idRole`)) -ENGINE = InnoDB -COMMENT = 'Contain all roles within an organisation and their rights'; - -CREATE UNIQUE INDEX `idRoles_UNIQUE` ON `popcube_test`.`roles` (`idRole` ASC); - -CREATE UNIQUE INDEX `roleName_UNIQUE` ON `popcube_test`.`roles` (`roleName` ASC); - - +CREATE SCHEMA IF NOT EXISTS `popcube` DEFAULT CHARACTER SET utf8 ; -- ----------------------------------------------------- --- Table `popcube_test`.`users` +-- Schema popcube_test -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`users` ( - `idUser` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `webId` VARCHAR(26) NOT NULL COMMENT 'Used to generate web storage keys\n', - `userName` VARCHAR(64) NOT NULL COMMENT 'User Name. Can be used\nto login instead of mail adress\n', - `email` VARCHAR(128) NOT NULL COMMENT 'User email. Can be used\nto login instead of userName\n', - `emailVerified` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Store email verification state\n(default false)\n', - `lastUpdate` BIGINT(20) NOT NULL COMMENT 'Last known update (in MS)\n', - `deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'User deleted ? ', - `password` VARCHAR(200) NOT NULL COMMENT 'User password. Stored encrypted\n', - `lastPasswordUpdate` BIGINT(20) NOT NULL COMMENT 'Last time password was updated (in MS)\n', - `failedAttempts` INT NOT NULL DEFAULT 0 COMMENT 'Number of failed attempts for user login.\n', - `locale` VARCHAR(5) NOT NULL DEFAULT 'fr_FR' COMMENT 'Langage code (fr_FR, en_US, en_EN .... )\n', - `idRole` INT UNSIGNED NOT NULL, - `avatar` VARCHAR(45) NULL, - `nickName` VARCHAR(45) NULL, - `firstName` VARCHAR(45) NULL, - `lastName` VARCHAR(45) NULL, - PRIMARY KEY (`idUser`), - CONSTRAINT `fk_User_Roles` - FOREIGN KEY (`idRole`) - REFERENCES `popcube_test`.`roles` (`idRole`) - ON DELETE RESTRICT - ON UPDATE RESTRICT) -ENGINE = InnoDB -COMMENT = 'Table to store all user informations\n'; - -CREATE UNIQUE INDEX `webId_UNIQUE` ON `popcube_test`.`users` (`webId` ASC); - -CREATE UNIQUE INDEX `idUser_UNIQUE` ON `popcube_test`.`users` (`idUser` ASC); -CREATE UNIQUE INDEX `userName_UNIQUE` ON `popcube_test`.`users` (`userName` ASC); - -CREATE UNIQUE INDEX `email_UNIQUE` ON `popcube_test`.`users` (`email` ASC); - -CREATE INDEX `fk_User_Roles_idx` ON `popcube_test`.`users` (`idRole` ASC); - -CREATE UNIQUE INDEX `nickName_UNIQUE` ON `popcube_test`.`users` (`nickName` ASC); +-- ----------------------------------------------------- +-- Schema popcube_test +-- ----------------------------------------------------- +CREATE SCHEMA IF NOT EXISTS `popcube_test` ; +-- ----------------------------------------------------- +-- Schema popcube_dev +-- ----------------------------------------------------- +-- ----------------------------------------------------- +-- Schema popcube_dev +-- ----------------------------------------------------- +CREATE SCHEMA IF NOT EXISTS `popcube_dev` ; +USE `popcube` ; -- ----------------------------------------------------- --- Table `popcube_test`.`organisations` +-- Table `popcube`.`organisations` -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`organisations` ( +CREATE TABLE IF NOT EXISTS `popcube`.`organisations` ( `idOrganisation` INT UNSIGNED NOT NULL AUTO_INCREMENT, `dockerStack` INT UNSIGNED NOT NULL, `organisationName` VARCHAR(45) NOT NULL, - `description` VARCHAR(100) NULL, + `public` TINYINT(1) NOT NULL DEFAULT 0, + `description` VARCHAR(45) NULL, `avatar` VARCHAR(45) NULL, `domain` VARCHAR(45) NULL, PRIMARY KEY (`idOrganisation`)) ENGINE = InnoDB COMMENT = 'Table to store Organisation related informations\n'; -CREATE UNIQUE INDEX `idOrganisation_UNIQUE` ON `popcube_test`.`organisations` (`idOrganisation` ASC); +CREATE UNIQUE INDEX `idOrganisation_UNIQUE` ON `popcube`.`organisations` (`idOrganisation` ASC); -CREATE UNIQUE INDEX `dockerStack_UNIQUE` ON `popcube_test`.`organisations` (`dockerStack` ASC); +CREATE UNIQUE INDEX `dockerStack_UNIQUE` ON `popcube`.`organisations` (`dockerStack` ASC); -CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube_test`.`organisations` (`organisationName` ASC); +CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube`.`organisations` (`organisationName` ASC); -- ----------------------------------------------------- --- Table `popcube_test`.`channels` +-- Table `popcube`.`roles` -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`channels` ( +CREATE TABLE IF NOT EXISTS `popcube`.`roles` ( + `idRole` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `roleName` VARCHAR(45) NOT NULL, + `canUsePrivate` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Can create private channels\n', + `canModerate` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can moderate channel\nuser did not create\n', + `canArchive` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can archive channel \nuser did not create\n', + `canInvite` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can invite new member\nin organisation', + `canManage` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can manage organisation\n(update information,\nadd bots, add plugins).\n', + `canManageUser` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Role name ~~', + PRIMARY KEY (`idRole`)) +ENGINE = InnoDB +COMMENT = 'Contain all roles within an organisation and their rights'; + +CREATE UNIQUE INDEX `idRoles_UNIQUE` ON `popcube`.`roles` (`idRole` ASC); + +CREATE UNIQUE INDEX `roleName_UNIQUE` ON `popcube`.`roles` (`roleName` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube`.`channels` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube`.`channels` ( `idChannel` INT UNSIGNED NOT NULL AUTO_INCREMENT, `webId` VARCHAR(45) NOT NULL, `channelName` VARCHAR(45) NOT NULL, `type` VARCHAR(45) NOT NULL, `private` TINYINT(1) NOT NULL DEFAULT 0, - `lastUpdate` BIGINT(20) NOT NULL, + `lastUpdate` BIGINT NOT NULL, `description` VARCHAR(45) NULL, `avatar` VARCHAR(45) NULL, `subject` VARCHAR(45) NULL, @@ -114,71 +93,84 @@ CREATE TABLE IF NOT EXISTS `popcube_test`.`channels` ( ENGINE = InnoDB COMMENT = 'Channel Management'; -CREATE UNIQUE INDEX `idChannel_UNIQUE` ON `popcube_test`.`channels` (`idChannel` ASC); +CREATE UNIQUE INDEX `idChannel_UNIQUE` ON `popcube`.`channels` (`idChannel` ASC); -CREATE UNIQUE INDEX `channelName_UNIQUE` ON `popcube_test`.`channels` (`channelName` ASC); +CREATE UNIQUE INDEX `channelName_UNIQUE` ON `popcube`.`channels` (`channelName` ASC); -CREATE UNIQUE INDEX `WebId_UNIQUE` ON `popcube_test`.`channels` (`webId` ASC); +CREATE UNIQUE INDEX `WebId_UNIQUE` ON `popcube`.`channels` (`webId` ASC); -- ----------------------------------------------------- --- Table `popcube_test`.`members` +-- Table `popcube`.`users` -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`members` ( - `idUser` INT UNSIGNED NOT NULL, - `idChannel` INT UNSIGNED NOT NULL, - `idRole` INT UNSIGNED NULL, - PRIMARY KEY (`idUser`, `idChannel`), - CONSTRAINT `fk_Member_User` - FOREIGN KEY (`idUser`) - REFERENCES `popcube_test`.`users` (`idUser`) - ON DELETE RESTRICT - ON UPDATE RESTRICT, - CONSTRAINT `fk_Member_Role` +CREATE TABLE IF NOT EXISTS `popcube`.`users` ( + `idUser` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `webId` VARCHAR(26) NOT NULL COMMENT 'Used to generate web storage keys\n', + `userName` VARCHAR(64) NOT NULL COMMENT 'User Name. Can be used\nto login instead of mail adress\n', + `email` VARCHAR(128) NOT NULL COMMENT 'User email. Can be used\nto login instead of userName\n', + `emailVerified` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Store email verification state\n(default false)\n', + `lastUpdate` BIGINT UNSIGNED NOT NULL COMMENT 'Last known update (in MS)\n', + `deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'User deleted ? ', + `password` VARCHAR(200) NOT NULL COMMENT 'User password. Stored encrypted\n', + `lastPasswordUpdate` BIGINT NOT NULL COMMENT 'Last time password was updated (in MS)\n', + `failedAttempts` INT NOT NULL DEFAULT 0 COMMENT 'Number of failed attempts for user login.\n', + `idRole` INT UNSIGNED NOT NULL, + `avatar` VARCHAR(45) NULL, + `nickName` VARCHAR(45) NULL, + `firstName` VARCHAR(45) NULL, + `lastName` VARCHAR(45) NULL, + PRIMARY KEY (`idUser`), + CONSTRAINT `fk_User_Roles` FOREIGN KEY (`idRole`) - REFERENCES `popcube_test`.`roles` (`idRole`) - ON DELETE RESTRICT - ON UPDATE RESTRICT, - CONSTRAINT `fk_Member_Channel` - FOREIGN KEY (`idChannel`) - REFERENCES `popcube_test`.`channels` (`idChannel`) - ON DELETE RESTRICT - ON UPDATE RESTRICT) + REFERENCES `popcube`.`roles` (`idRole`) + ON DELETE CASCADE + ON UPDATE CASCADE) ENGINE = InnoDB -COMMENT = 'Store information about member of organisation.'; +COMMENT = 'Table to store all user informations\n'; + +CREATE UNIQUE INDEX `webId_UNIQUE` ON `popcube`.`users` (`webId` ASC); + +CREATE UNIQUE INDEX `idUser_UNIQUE` ON `popcube`.`users` (`idUser` ASC); + +CREATE UNIQUE INDEX `userName_UNIQUE` ON `popcube`.`users` (`userName` ASC); + +CREATE UNIQUE INDEX `email_UNIQUE` ON `popcube`.`users` (`email` ASC); + +CREATE INDEX `fk_User_Roles_idx` ON `popcube`.`users` (`idRole` ASC); + -- ----------------------------------------------------- --- Table `popcube_test`.`messages` +-- Table `popcube`.`messages` -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`messages` ( +CREATE TABLE IF NOT EXISTS `popcube`.`messages` ( `idMessage` INT UNSIGNED NOT NULL AUTO_INCREMENT, `idUser` INT UNSIGNED NOT NULL, - `idChannel` INT UNSIGNED NOT NULL COMMENT 'Channel FK', + `idChannel` INT UNSIGNED NOT NULL, `date` INT NOT NULL, `content` LONGTEXT NULL DEFAULT NULL, PRIMARY KEY (`idMessage`), - CONSTRAINT `fk_Message_User` - FOREIGN KEY (`idUser`) - REFERENCES `popcube_test`.`users` (`idUser`) - ON DELETE RESTRICT - ON UPDATE RESTRICT, CONSTRAINT `fk_Message_Channel` FOREIGN KEY (`idChannel`) - REFERENCES `popcube_test`.`channels` (`idChannel`) - ON DELETE RESTRICT - ON UPDATE RESTRICT) + REFERENCES `popcube`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_messages_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE) ENGINE = InnoDB COMMENT = 'Store message '; -CREATE INDEX `fk_Message_User_idx` ON `popcube_test`.`messages` (`idUser` ASC); +CREATE INDEX `fk_Message_Channel_idx` ON `popcube`.`messages` (`idChannel` ASC); -CREATE INDEX `fk_Message_Channel_idx` ON `popcube_test`.`messages` (`idChannel` ASC); +CREATE INDEX `fk_messages_User_idx` ON `popcube`.`messages` (`idUser` ASC); -- ----------------------------------------------------- --- Table `popcube_test`.`folders` +-- Table `popcube`.`folders` -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`folders` ( +CREATE TABLE IF NOT EXISTS `popcube`.`folders` ( `idFolder` INT UNSIGNED NOT NULL AUTO_INCREMENT, `idMessage` INT UNSIGNED NOT NULL, `type` VARCHAR(3) NOT NULL DEFAULT 'svg' COMMENT 'File extension\n', @@ -187,20 +179,20 @@ CREATE TABLE IF NOT EXISTS `popcube_test`.`folders` ( PRIMARY KEY (`idFolder`, `idMessage`), CONSTRAINT `fk_Fichier_Message` FOREIGN KEY (`idMessage`) - REFERENCES `popcube_test`.`messages` (`idMessage`) - ON DELETE RESTRICT - ON UPDATE RESTRICT) + REFERENCES `popcube`.`messages` (`idMessage`) + ON DELETE CASCADE + ON UPDATE CASCADE) ENGINE = InnoDB; -CREATE UNIQUE INDEX `idFichier_UNIQUE` ON `popcube_test`.`folders` (`idFolder` ASC); +CREATE UNIQUE INDEX `idFichier_UNIQUE` ON `popcube`.`folders` (`idFolder` ASC); -CREATE INDEX `fk_Fichier_Message_idx` ON `popcube_test`.`folders` (`idMessage` ASC); +CREATE INDEX `fk_Fichier_Message_idx` ON `popcube`.`folders` (`idMessage` ASC); -- ----------------------------------------------------- --- Table `popcube_test`.`parameters` +-- Table `popcube`.`parameters` -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`parameters` ( +CREATE TABLE IF NOT EXISTS `popcube`.`parameters` ( `idParameter` INT UNSIGNED NOT NULL AUTO_INCREMENT, `local` CHAR(5) NOT NULL DEFAULT 'fr_FR', `timeZone` CHAR(6) NOT NULL DEFAULT 'UTC-0', @@ -209,21 +201,21 @@ CREATE TABLE IF NOT EXISTS `popcube_test`.`parameters` ( PRIMARY KEY (`idParameter`)) ENGINE = InnoDB; -CREATE UNIQUE INDEX `idParameter_UNIQUE` ON `popcube_test`.`parameters` (`idParameter` ASC); +CREATE UNIQUE INDEX `idParameter_UNIQUE` ON `popcube`.`parameters` (`idParameter` ASC); -CREATE UNIQUE INDEX `local_UNIQUE` ON `popcube_test`.`parameters` (`local` ASC); +CREATE UNIQUE INDEX `local_UNIQUE` ON `popcube`.`parameters` (`local` ASC); -CREATE UNIQUE INDEX `timeZone_UNIQUE` ON `popcube_test`.`parameters` (`timeZone` ASC); +CREATE UNIQUE INDEX `timeZone_UNIQUE` ON `popcube`.`parameters` (`timeZone` ASC); -CREATE UNIQUE INDEX `sleepStart_UNIQUE` ON `popcube_test`.`parameters` (`sleepStart` ASC); +CREATE UNIQUE INDEX `sleepStart_UNIQUE` ON `popcube`.`parameters` (`sleepStart` ASC); -CREATE UNIQUE INDEX `sleepEnd_UNIQUE` ON `popcube_test`.`parameters` (`sleepEnd` ASC); +CREATE UNIQUE INDEX `sleepEnd_UNIQUE` ON `popcube`.`parameters` (`sleepEnd` ASC); -- ----------------------------------------------------- --- Table `popcube_test`.`emojis` +-- Table `popcube`.`emojis` -- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `popcube_test`.`emojis` ( +CREATE TABLE IF NOT EXISTS `popcube`.`emojis` ( `idEmoji` INT UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, `shortcut` VARCHAR(45) NOT NULL, @@ -232,13 +224,147 @@ CREATE TABLE IF NOT EXISTS `popcube_test`.`emojis` ( ENGINE = InnoDB COMMENT = 'What emoji can you use ;)'; -CREATE UNIQUE INDEX `idEmojis_UNIQUE` ON `popcube_test`.`emojis` (`idEmoji` ASC); +CREATE UNIQUE INDEX `idEmojis_UNIQUE` ON `popcube`.`emojis` (`idEmoji` ASC); -CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube_test`.`emojis` (`name` ASC); +CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube`.`emojis` (`name` ASC); -CREATE UNIQUE INDEX `raccourcie_UNIQUE` ON `popcube_test`.`emojis` (`shortcut` ASC); +CREATE UNIQUE INDEX `raccourcie_UNIQUE` ON `popcube`.`emojis` (`shortcut` ASC); -CREATE UNIQUE INDEX `lien_UNIQUE` ON `popcube_test`.`emojis` (`link` ASC); +CREATE UNIQUE INDEX `lien_UNIQUE` ON `popcube`.`emojis` (`link` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube`.`avatars` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube`.`avatars` ( + `idAvatar` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(45) NOT NULL, + `link` VARCHAR(45) NOT NULL, + PRIMARY KEY (`idAvatar`)) +ENGINE = InnoDB; + +CREATE UNIQUE INDEX `idAvatar_UNIQUE` ON `popcube`.`avatars` (`idAvatar` ASC); + +CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube`.`avatars` (`name` ASC); + +CREATE UNIQUE INDEX `lien_UNIQUE` ON `popcube`.`avatars` (`link` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube`.`reads` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube`.`reads` ( + `idUser` INT UNSIGNED NOT NULL, + `idChannel` INT UNSIGNED NOT NULL, + `idMessage` INT UNSIGNED NOT NULL, + PRIMARY KEY (`idUser`, `idChannel`, `idMessage`), + CONSTRAINT `fk_Read_Channel` + FOREIGN KEY (`idChannel`) + REFERENCES `popcube`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Read_Message` + FOREIGN KEY (`idMessage`) + REFERENCES `popcube`.`messages` (`idMessage`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_read_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE INDEX `fk_Read_Channel_idx` ON `popcube`.`reads` (`idChannel` ASC); + +CREATE INDEX `fk_Read_Message_idx` ON `popcube`.`reads` (`idMessage` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube`.`allowed_web_mails` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube`.`allowed_web_mails` ( + `idAllowedWebMails` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `domain` VARCHAR(45) NOT NULL, + `provider` VARCHAR(45) NULL, + `defaultRights` VARCHAR(45) NULL DEFAULT 'standard', + PRIMARY KEY (`idAllowedWebMails`)) +ENGINE = InnoDB +COMMENT = 'Table to manage webmail domain that can create an account on organisation without being invitated. '; + +CREATE UNIQUE INDEX `idAllowedWebMails_UNIQUE` ON `popcube`.`allowed_web_mails` (`idAllowedWebMails` ASC); + +CREATE UNIQUE INDEX `domain_UNIQUE` ON `popcube`.`allowed_web_mails` (`domain` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube`.`user_parameters` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube`.`user_parameters` ( + `idUser` INT UNSIGNED NOT NULL, + `parameterName` VARCHAR(45) NOT NULL, + `local` CHAR(5) NULL, + `timeZone` CHAR(4) NULL, + `sleepStart` INT NULL, + `sleepEnd` INT NULL, + PRIMARY KEY (`parameterName`, `idUser`), + CONSTRAINT `fk_userParameter_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE INDEX `fk_userParameter_User_idx` ON `popcube`.`user_parameters` (`idUser` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube`.`members` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube`.`members` ( + `idUser` INT UNSIGNED NOT NULL, + `idChannel` INT UNSIGNED NOT NULL, + `idRole` INT UNSIGNED NULL, + PRIMARY KEY (`idUser`, `idChannel`), + CONSTRAINT `fk_Member_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Member_Role` + FOREIGN KEY (`idRole`) + REFERENCES `popcube`.`roles` (`idRole`) + ON DELETE SET NULL + ON UPDATE CASCADE, + CONSTRAINT `fk_Member_Channel` + FOREIGN KEY (`idChannel`) + REFERENCES `popcube`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB +COMMENT = 'Store information about member of organisation.'; + +CREATE INDEX `fk_Member_Role_idx` ON `popcube`.`members` (`idRole` ASC); + +CREATE INDEX `fk_Member_Channel_idx` ON `popcube`.`members` (`idChannel` ASC); + +USE `popcube_test` ; + +-- ----------------------------------------------------- +-- Table `popcube_test`.`allowed_web_mails` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`allowed_web_mails` ( + `idAllowedWebMails` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `domain` VARCHAR(45) NOT NULL, + `provider` VARCHAR(45) NULL, + `defaultRights` VARCHAR(45) NULL DEFAULT 'standard', + PRIMARY KEY (`idAllowedWebMails`)) +ENGINE = InnoDB +COMMENT = 'Table to manage webmail domain that can create an account on organisation without being invitated. '; + +CREATE UNIQUE INDEX `idAllowedWebMails_UNIQUE` ON `popcube_test`.`allowed_web_mails` (`idAllowedWebMails` ASC); + +CREATE UNIQUE INDEX `domain_UNIQUE` ON `popcube_test`.`allowed_web_mails` (`domain` ASC); -- ----------------------------------------------------- @@ -258,6 +384,605 @@ CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube_test`.`avatars` (`name` ASC); CREATE UNIQUE INDEX `lien_UNIQUE` ON `popcube_test`.`avatars` (`link` ASC); +-- ----------------------------------------------------- +-- Table `popcube_test`.`channels` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`channels` ( + `idChannel` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `webId` VARCHAR(45) NOT NULL, + `channelName` VARCHAR(45) NOT NULL, + `type` VARCHAR(45) NOT NULL, + `private` TINYINT(1) NOT NULL DEFAULT 0, + `lastUpdate` BIGINT NOT NULL, + `description` VARCHAR(45) NULL, + `avatar` VARCHAR(45) NULL, + `subject` VARCHAR(45) NULL, + PRIMARY KEY (`idChannel`)) +ENGINE = InnoDB +COMMENT = 'Channel Management'; + +CREATE UNIQUE INDEX `idChannel_UNIQUE` ON `popcube_test`.`channels` (`idChannel` ASC); + +CREATE UNIQUE INDEX `channelName_UNIQUE` ON `popcube_test`.`channels` (`channelName` ASC); + +CREATE UNIQUE INDEX `WebId_UNIQUE` ON `popcube_test`.`channels` (`webId` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`emojis` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`emojis` ( + `idEmoji` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(45) NOT NULL, + `shortcut` VARCHAR(45) NOT NULL, + `link` VARCHAR(45) NOT NULL, + PRIMARY KEY (`idEmoji`)) +ENGINE = InnoDB +COMMENT = 'What emoji can you use ;)'; + +CREATE UNIQUE INDEX `idEmojis_UNIQUE` ON `popcube_test`.`emojis` (`idEmoji` ASC); + +CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube_test`.`emojis` (`name` ASC); + +CREATE UNIQUE INDEX `raccourcie_UNIQUE` ON `popcube_test`.`emojis` (`shortcut` ASC); + +CREATE UNIQUE INDEX `lien_UNIQUE` ON `popcube_test`.`emojis` (`link` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`roles` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`roles` ( + `idRole` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `roleName` VARCHAR(45) NOT NULL, + `canUsePrivate` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Can create private channels\n', + `canModerate` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can moderate channel\nuser did not create\n', + `canArchive` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can archive channel \nuser did not create\n', + `canInvite` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can invite new member\nin organisation', + `canManage` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can manage organisation\n(update information,\nadd bots, add plugins).\n', + `canManageUser` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Role name ~~', + PRIMARY KEY (`idRole`)) +ENGINE = InnoDB +COMMENT = 'Contain all roles within an organisation and their rights'; + +CREATE UNIQUE INDEX `idRoles_UNIQUE` ON `popcube_test`.`roles` (`idRole` ASC); + +CREATE UNIQUE INDEX `roleName_UNIQUE` ON `popcube_test`.`roles` (`roleName` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`users` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`users` ( + `idUser` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `webId` VARCHAR(26) NOT NULL COMMENT 'Used to generate web storage keys\n', + `userName` VARCHAR(64) NOT NULL COMMENT 'User Name. Can be used\nto login instead of mail adress\n', + `email` VARCHAR(128) NOT NULL COMMENT 'User email. Can be used\nto login instead of userName\n', + `emailVerified` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Store email verification state\n(default false)\n', + `lastUpdate` BIGINT UNSIGNED NOT NULL COMMENT 'Last known update (in MS)\n', + `deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'User deleted ? ', + `password` VARCHAR(200) NOT NULL COMMENT 'User password. Stored encrypted\n', + `lastPasswordUpdate` BIGINT NOT NULL COMMENT 'Last time password was updated (in MS)\n', + `failedAttempts` INT NOT NULL DEFAULT 0 COMMENT 'Number of failed attempts for user login.\n', + `idRole` INT UNSIGNED NOT NULL, + `avatar` VARCHAR(45) NULL, + `nickName` VARCHAR(45) NULL, + `firstName` VARCHAR(45) NULL, + `lastName` VARCHAR(45) NULL, + PRIMARY KEY (`idUser`), + CONSTRAINT `fk_User_Roles` + FOREIGN KEY (`idRole`) + REFERENCES `popcube_test`.`roles` (`idRole`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB +COMMENT = 'Table to store all user informations\n'; + +CREATE UNIQUE INDEX `webId_UNIQUE` ON `popcube_test`.`users` (`webId` ASC); + +CREATE UNIQUE INDEX `idUser_UNIQUE` ON `popcube_test`.`users` (`idUser` ASC); + +CREATE UNIQUE INDEX `userName_UNIQUE` ON `popcube_test`.`users` (`userName` ASC); + +CREATE UNIQUE INDEX `email_UNIQUE` ON `popcube_test`.`users` (`email` ASC); + +CREATE INDEX `fk_User_Roles_idx` ON `popcube_test`.`users` (`idRole` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`messages` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`messages` ( + `idMessage` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `idUser` INT UNSIGNED NOT NULL, + `idChannel` INT UNSIGNED NOT NULL, + `date` INT NOT NULL, + `content` LONGTEXT NULL DEFAULT NULL, + PRIMARY KEY (`idMessage`), + CONSTRAINT `fk_Message_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube_test`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Message_Channel` + FOREIGN KEY (`idChannel`) + REFERENCES `popcube_test`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB +COMMENT = 'Store message '; + +CREATE INDEX `fk_Message_Channel_idx` ON `popcube_test`.`messages` (`idChannel` ASC); + +CREATE INDEX `fk_Message_User_idx` ON `popcube_test`.`messages` (`idUser` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`folders` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`folders` ( + `idFolder` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `idMessage` INT UNSIGNED NOT NULL, + `type` VARCHAR(3) NOT NULL DEFAULT 'svg' COMMENT 'File extension\n', + `link` VARCHAR(45) NOT NULL DEFAULT '/downloads/', + `name` VARCHAR(45) NOT NULL DEFAULT 'file', + PRIMARY KEY (`idFolder`, `idMessage`), + CONSTRAINT `fk_Fichier_Message` + FOREIGN KEY (`idMessage`) + REFERENCES `popcube_test`.`messages` (`idMessage`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE UNIQUE INDEX `idFichier_UNIQUE` ON `popcube_test`.`folders` (`idFolder` ASC); + +CREATE INDEX `fk_Fichier_Message_idx` ON `popcube_test`.`folders` (`idMessage` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`members` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`members` ( + `idUser` INT UNSIGNED NOT NULL, + `idChannel` INT UNSIGNED NOT NULL, + `idRole` INT UNSIGNED NULL, + PRIMARY KEY (`idUser`, `idChannel`), + CONSTRAINT `fk_Member_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube_test`.`users` (`idUser`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Member_Role` + FOREIGN KEY (`idRole`) + REFERENCES `popcube_test`.`roles` (`idRole`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Member_Channel` + FOREIGN KEY (`idChannel`) + REFERENCES `popcube_test`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB +COMMENT = 'Store information about member of organisation.'; + +CREATE INDEX `fk_Member_Role_idx` ON `popcube_test`.`members` (`idRole` ASC); + +CREATE INDEX `fk_Member_Channel_idx` ON `popcube_test`.`members` (`idChannel` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`organisations` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`organisations` ( + `idOrganisation` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `dockerStack` INT UNSIGNED NOT NULL, + `organisationName` VARCHAR(45) NOT NULL, + `public` TINYINT(1) NOT NULL DEFAULT 0, + `description` VARCHAR(45) NULL, + `avatar` VARCHAR(45) NULL, + `domain` VARCHAR(45) NULL, + PRIMARY KEY (`idOrganisation`)) +ENGINE = InnoDB +COMMENT = 'Table to store Organisation related informations\n'; + +CREATE UNIQUE INDEX `idOrganisation_UNIQUE` ON `popcube_test`.`organisations` (`idOrganisation` ASC); + +CREATE UNIQUE INDEX `dockerStack_UNIQUE` ON `popcube_test`.`organisations` (`dockerStack` ASC); + +CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube_test`.`organisations` (`organisationName` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`parameters` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`parameters` ( + `idParameter` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `local` CHAR(5) NOT NULL DEFAULT 'fr_FR', + `timeZone` CHAR(6) NOT NULL DEFAULT 'UTC-0', + `sleepStart` INT NOT NULL DEFAULT '1200' COMMENT 'time in minute 24h format\n\n', + `sleepEnd` INT NOT NULL DEFAULT '240' COMMENT 'time in minute 24h fi\n', + PRIMARY KEY (`idParameter`)) +ENGINE = InnoDB; + +CREATE UNIQUE INDEX `idParameter_UNIQUE` ON `popcube_test`.`parameters` (`idParameter` ASC); + +CREATE UNIQUE INDEX `local_UNIQUE` ON `popcube_test`.`parameters` (`local` ASC); + +CREATE UNIQUE INDEX `timeZone_UNIQUE` ON `popcube_test`.`parameters` (`timeZone` ASC); + +CREATE UNIQUE INDEX `sleepStart_UNIQUE` ON `popcube_test`.`parameters` (`sleepStart` ASC); + +CREATE UNIQUE INDEX `sleepEnd_UNIQUE` ON `popcube_test`.`parameters` (`sleepEnd` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`reads` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`reads` ( + `idUser` INT UNSIGNED NOT NULL, + `idChannel` INT UNSIGNED NOT NULL, + `idMessage` INT UNSIGNED NOT NULL, + PRIMARY KEY (`idUser`, `idChannel`, `idMessage`), + CONSTRAINT `fk_Read_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube_test`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Read_Channel` + FOREIGN KEY (`idChannel`) + REFERENCES `popcube_test`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Read_Message` + FOREIGN KEY (`idMessage`) + REFERENCES `popcube_test`.`messages` (`idMessage`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE INDEX `fk_Read_Channel_idx` ON `popcube_test`.`reads` (`idChannel` ASC); + +CREATE INDEX `fk_Read_Message_idx` ON `popcube_test`.`reads` (`idMessage` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_test`.`user_parameters` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_test`.`user_parameters` ( + `idUser` INT UNSIGNED NOT NULL, + `parameterName` VARCHAR(45) NOT NULL, + `local` CHAR(5) NULL, + `timeZone` CHAR(4) NULL, + `sleepStart` INT NULL, + `sleepEnd` INT NULL, + PRIMARY KEY (`parameterName`, `idUser`), + CONSTRAINT `fk_userParameter_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube_test`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE INDEX `fk_userParameter_User_idx` ON `popcube_test`.`user_parameters` (`idUser` ASC); + +USE `popcube_dev` ; + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`allowed_web_mails` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`allowed_web_mails` ( + `idAllowedWebMails` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `domain` VARCHAR(45) NOT NULL, + `provider` VARCHAR(45) NULL, + `defaultRights` VARCHAR(45) NULL DEFAULT 'standard', + PRIMARY KEY (`idAllowedWebMails`)) +ENGINE = InnoDB +COMMENT = 'Table to manage webmail domain that can create an account on organisation without being invitated. '; + +CREATE UNIQUE INDEX `idAllowedWebMails_UNIQUE` ON `popcube_dev`.`allowed_web_mails` (`idAllowedWebMails` ASC); + +CREATE UNIQUE INDEX `domain_UNIQUE` ON `popcube_dev`.`allowed_web_mails` (`domain` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`avatars` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`avatars` ( + `idAvatar` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(45) NOT NULL, + `link` VARCHAR(45) NOT NULL, + PRIMARY KEY (`idAvatar`)) +ENGINE = InnoDB; + +CREATE UNIQUE INDEX `idAvatar_UNIQUE` ON `popcube_dev`.`avatars` (`idAvatar` ASC); + +CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube_dev`.`avatars` (`name` ASC); + +CREATE UNIQUE INDEX `lien_UNIQUE` ON `popcube_dev`.`avatars` (`link` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`channels` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`channels` ( + `idChannel` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `webId` VARCHAR(45) NOT NULL, + `channelName` VARCHAR(45) NOT NULL, + `type` VARCHAR(45) NOT NULL, + `private` TINYINT(1) NOT NULL DEFAULT 0, + `lastUpdate` BIGINT NOT NULL, + `description` VARCHAR(45) NULL, + `avatar` VARCHAR(45) NULL, + `subject` VARCHAR(45) NULL, + PRIMARY KEY (`idChannel`)) +ENGINE = InnoDB +COMMENT = 'Channel Management'; + +CREATE UNIQUE INDEX `idChannel_UNIQUE` ON `popcube_dev`.`channels` (`idChannel` ASC); + +CREATE UNIQUE INDEX `channelName_UNIQUE` ON `popcube_dev`.`channels` (`channelName` ASC); + +CREATE UNIQUE INDEX `WebId_UNIQUE` ON `popcube_dev`.`channels` (`webId` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`emojis` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`emojis` ( + `idEmoji` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(45) NOT NULL, + `shortcut` VARCHAR(45) NOT NULL, + `link` VARCHAR(45) NOT NULL, + PRIMARY KEY (`idEmoji`)) +ENGINE = InnoDB +COMMENT = 'What emoji can you use ;)'; + +CREATE UNIQUE INDEX `idEmojis_UNIQUE` ON `popcube_dev`.`emojis` (`idEmoji` ASC); + +CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube_dev`.`emojis` (`name` ASC); + +CREATE UNIQUE INDEX `raccourcie_UNIQUE` ON `popcube_dev`.`emojis` (`shortcut` ASC); + +CREATE UNIQUE INDEX `lien_UNIQUE` ON `popcube_dev`.`emojis` (`link` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`roles` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`roles` ( + `idRole` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `roleName` VARCHAR(45) NOT NULL, + `canUsePrivate` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Can create private channels\n', + `canModerate` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can moderate channel\nuser did not create\n', + `canArchive` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can archive channel \nuser did not create\n', + `canInvite` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can invite new member\nin organisation', + `canManage` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Can manage organisation\n(update information,\nadd bots, add plugins).\n', + `canManageUser` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Role name ~~', + PRIMARY KEY (`idRole`)) +ENGINE = InnoDB +COMMENT = 'Contain all roles within an organisation and their rights'; + +CREATE UNIQUE INDEX `idRoles_UNIQUE` ON `popcube_dev`.`roles` (`idRole` ASC); + +CREATE UNIQUE INDEX `roleName_UNIQUE` ON `popcube_dev`.`roles` (`roleName` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`users` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`users` ( + `idUser` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `webId` VARCHAR(26) NOT NULL COMMENT 'Used to generate web storage keys\n', + `userName` VARCHAR(64) NOT NULL COMMENT 'User Name. Can be used\nto login instead of mail adress\n', + `email` VARCHAR(128) NOT NULL COMMENT 'User email. Can be used\nto login instead of userName\n', + `emailVerified` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Store email verification state\n(default false)\n', + `lastUpdate` BIGINT UNSIGNED NOT NULL COMMENT 'Last known update (in MS)\n', + `deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'User deleted ? ', + `password` VARCHAR(200) NOT NULL COMMENT 'User password. Stored encrypted\n', + `lastPasswordUpdate` BIGINT NOT NULL COMMENT 'Last time password was updated (in MS)\n', + `failedAttempts` INT NOT NULL DEFAULT 0 COMMENT 'Number of failed attempts for user login.\n', + `idRole` INT UNSIGNED NOT NULL, + `avatar` VARCHAR(45) NULL, + `nickName` VARCHAR(45) NULL, + `firstName` VARCHAR(45) NULL, + `lastName` VARCHAR(45) NULL, + PRIMARY KEY (`idUser`), + CONSTRAINT `fk_User_Roles` + FOREIGN KEY (`idRole`) + REFERENCES `popcube_dev`.`roles` (`idRole`) + ON DELETE RESTRICT + ON UPDATE CASCADE) +ENGINE = InnoDB +COMMENT = 'Table to store all user informations\n'; + +CREATE UNIQUE INDEX `webId_UNIQUE` ON `popcube_dev`.`users` (`webId` ASC); + +CREATE UNIQUE INDEX `idUser_UNIQUE` ON `popcube_dev`.`users` (`idUser` ASC); + +CREATE UNIQUE INDEX `userName_UNIQUE` ON `popcube_dev`.`users` (`userName` ASC); + +CREATE UNIQUE INDEX `email_UNIQUE` ON `popcube_dev`.`users` (`email` ASC); + +CREATE INDEX `fk_User_Roles_idx` ON `popcube_dev`.`users` (`idRole` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`messages` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`messages` ( + `idMessage` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `idUser` INT UNSIGNED NOT NULL, + `idChannel` INT UNSIGNED NOT NULL, + `date` INT NOT NULL, + `content` LONGTEXT NULL DEFAULT NULL, + PRIMARY KEY (`idMessage`), + CONSTRAINT `fk_Message_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube_dev`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Message_Channel` + FOREIGN KEY (`idChannel`) + REFERENCES `popcube_dev`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB +COMMENT = 'Store message '; + +CREATE INDEX `fk_Message_User_idx` ON `popcube_dev`.`messages` (`idUser` ASC); + +CREATE INDEX `fk_Message_Channel_idx` ON `popcube_dev`.`messages` (`idChannel` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`folders` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`folders` ( + `idFolder` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `idMessage` INT UNSIGNED NOT NULL, + `type` VARCHAR(3) NOT NULL DEFAULT 'svg' COMMENT 'File extension\n', + `link` VARCHAR(45) NOT NULL DEFAULT '/downloads/', + `name` VARCHAR(45) NOT NULL DEFAULT 'file', + PRIMARY KEY (`idFolder`, `idMessage`), + CONSTRAINT `fk_Fichier_Message` + FOREIGN KEY (`idMessage`) + REFERENCES `popcube_dev`.`messages` (`idMessage`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE UNIQUE INDEX `idFichier_UNIQUE` ON `popcube_dev`.`folders` (`idFolder` ASC); + +CREATE INDEX `fk_Fichier_Message_idx` ON `popcube_dev`.`folders` (`idMessage` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`members` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`members` ( + `idUser` INT UNSIGNED NOT NULL, + `idChannel` INT UNSIGNED NOT NULL, + `idRole` INT UNSIGNED NULL, + PRIMARY KEY (`idUser`, `idChannel`), + CONSTRAINT `fk_Member_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube_dev`.`users` (`idUser`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT `fk_Member_Role` + FOREIGN KEY (`idRole`) + REFERENCES `popcube_dev`.`roles` (`idRole`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Member_Channel` + FOREIGN KEY (`idChannel`) + REFERENCES `popcube_dev`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB +COMMENT = 'Store information about member of organisation.'; + +CREATE INDEX `fk_Member_Role_idx` ON `popcube_dev`.`members` (`idRole` ASC); + +CREATE INDEX `fk_Member_Channel_idx` ON `popcube_dev`.`members` (`idChannel` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`organisations` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`organisations` ( + `idOrganisation` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `dockerStack` INT UNSIGNED NOT NULL, + `organisationName` VARCHAR(45) NOT NULL, + `public` TINYINT(1) NOT NULL DEFAULT 0, + `description` VARCHAR(45) NULL, + `avatar` VARCHAR(45) NULL, + `domain` VARCHAR(45) NULL, + PRIMARY KEY (`idOrganisation`)) +ENGINE = InnoDB +COMMENT = 'Table to store Organisation related informations\n'; + +CREATE UNIQUE INDEX `idOrganisation_UNIQUE` ON `popcube_dev`.`organisations` (`idOrganisation` ASC); + +CREATE UNIQUE INDEX `dockerStack_UNIQUE` ON `popcube_dev`.`organisations` (`dockerStack` ASC); + +CREATE UNIQUE INDEX `name_UNIQUE` ON `popcube_dev`.`organisations` (`organisationName` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`parameters` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`parameters` ( + `idParameter` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `local` CHAR(5) NOT NULL DEFAULT 'fr_FR', + `timeZone` CHAR(6) NOT NULL DEFAULT 'UTC-0', + `sleepStart` INT NOT NULL DEFAULT '1200' COMMENT 'time in minute 24h format\n\n', + `sleepEnd` INT NOT NULL DEFAULT '240' COMMENT 'time in minute 24h fi\n', + PRIMARY KEY (`idParameter`)) +ENGINE = InnoDB; + +CREATE UNIQUE INDEX `idParameter_UNIQUE` ON `popcube_dev`.`parameters` (`idParameter` ASC); + +CREATE UNIQUE INDEX `local_UNIQUE` ON `popcube_dev`.`parameters` (`local` ASC); + +CREATE UNIQUE INDEX `timeZone_UNIQUE` ON `popcube_dev`.`parameters` (`timeZone` ASC); + +CREATE UNIQUE INDEX `sleepStart_UNIQUE` ON `popcube_dev`.`parameters` (`sleepStart` ASC); + +CREATE UNIQUE INDEX `sleepEnd_UNIQUE` ON `popcube_dev`.`parameters` (`sleepEnd` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`reads` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`reads` ( + `idUser` INT UNSIGNED NOT NULL, + `idChannel` INT UNSIGNED NOT NULL, + `idMessage` INT UNSIGNED NOT NULL, + PRIMARY KEY (`idUser`, `idChannel`, `idMessage`), + CONSTRAINT `fk_Read_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube_dev`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Read_Channel` + FOREIGN KEY (`idChannel`) + REFERENCES `popcube_dev`.`channels` (`idChannel`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fk_Read_Message` + FOREIGN KEY (`idMessage`) + REFERENCES `popcube_dev`.`messages` (`idMessage`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE INDEX `fk_Read_Channel_idx` ON `popcube_dev`.`reads` (`idChannel` ASC); + +CREATE INDEX `fk_Read_Message_idx` ON `popcube_dev`.`reads` (`idMessage` ASC); + + +-- ----------------------------------------------------- +-- Table `popcube_dev`.`user_parameters` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `popcube_dev`.`user_parameters` ( + `idUser` INT UNSIGNED NOT NULL, + `parameterName` VARCHAR(45) NOT NULL, + `local` CHAR(5) NULL, + `timeZone` CHAR(4) NULL, + `sleepStart` INT NULL, + `sleepEnd` INT NULL, + PRIMARY KEY (`parameterName`, `idUser`), + CONSTRAINT `fk_userParameter_User` + FOREIGN KEY (`idUser`) + REFERENCES `popcube_dev`.`users` (`idUser`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE INDEX `fk_userParameter_User_idx` ON `popcube_dev`.`user_parameters` (`idUser` ASC); + + SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; diff --git a/scripts/init_values.sql b/scripts/init_values.sql index aac6042..cc26e80 100644 --- a/scripts/init_values.sql +++ b/scripts/init_values.sql @@ -36,86 +36,122 @@ VALUES ("en_EN", "UTC-1"); -- UNCOMMENT THE FOLLOWINGS FOR LOCAL DEV TEST --------------------------------------------------- +-- ROLE INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-- INSERT INTO `popcube_dev`.`roles` (roleName, canUsePrivate, canModerate, canArchive, canInvite, canManage, canManageUser) +-- VALUES ("owner", true, true, true, true, true, true); + +-- INSERT INTO `popcube_dev`.`roles` (roleName, canUsePrivate, canModerate, canArchive, canInvite, canManage, canManageUser) +-- VALUES ("admin", true, true, true, true, true, true); + +-- INSERT INTO `popcube_dev`.`roles` (roleName, canUsePrivate, canModerate, canArchive, canInvite, canManage, canManageUser) +-- VALUES ("standard", true, true, true, false, false, false); + +-- INSERT INTO `popcube_dev`.`roles` (roleName, canUsePrivate, canModerate, canArchive, canInvite, canManage, canManageUser) +-- VALUES ("guest", false, false, false, false, false, false); + +-- SELECT * FROM `popcube_dev`.`roles`; + +-- CHANNEL INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-- INSERT INTO `popcube_dev`.`channels` (webId, channelName, type, lastUpdate, private, avatar, description, subject) +-- VALUES ("generaltextchannel", "general", "text", 1, false, "defaultAvatar", "Speak on general subjects", "General"); + +-- INSERT INTO `popcube_dev`.`channels` (webId, channelName, type, lastUpdate, private, avatar,description) +-- VALUES ("randomtextchannel", "random", "text", 1, false, "defaultAvatar","Speak about any thing"); + +-- INSERT INTO `popcube_dev`.`channels` (webId, channelName, type, lastUpdate, private, avatar) +-- VALUES ("generalvocchannel", "general - voc", "audio", 1, false, "defaultAvatar"); + +-- INSERT INTO `popcube_dev`.`channels` (webId, channelName, type, lastUpdate, private, avatar) +-- VALUES ("randomvocchannel", "random - voc", "audio", 1, false, "defaultAvatar"); + +-- INSERT INTO `popcube_dev`.`channels` (webId, channelName, type, lastUpdate, private, avatar) +-- VALUES ("generalvidchannel", "general - vid", "video", 1, false, "defaultAvatar"); + +-- INSERT INTO `popcube_dev`.`channels` (webId, channelName, type, lastUpdate, private, avatar) +-- VALUES ("randomvidchannel", "random - vid", "video", 1, false, "defaultAvatar"); +-- PARMETER INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-- INSERT INTO `popcube_dev`.`parameters` (local, timeZone) +-- VALUES ("en_EN", "UTC-1"); + -- USER INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> -INSERT INTO users (webId, userName, email, lastUpdate, password, idRole, avatar, nickName, firstName, lastName) +INSERT INTO `popcube_dev`.`users` (webId, userName, email, lastUpdate, password, idRole, avatar, nickName, firstName, lastName) VALUES ("TestUserOwner", "devowner", "devowner@popcube.xyz", 1105154015461, "$2a$10$IU8oU9dseYZytHcr54VXj.H9tX78hS2xUuPrzMeVN6rFG7k89i6EW", 1, "user/owned.svg", "owner", "owner", "dev"); -INSERT INTO users (webId, userName, email, lastUpdate, password, idRole, avatar, nickName, firstName, lastName) +INSERT INTO `popcube_dev`.`users` (webId, userName, email, lastUpdate, password, idRole, avatar, nickName, firstName, lastName) VALUES ("TestUserAdmin", "devadmin", "devadmin@popcube.xyz", 1105154015461, "$2a$10$IU8oU9dseYZytHcr54VXj.H9tX78hS2xUuPrzMeVN6rFG7k89i6EW", 2, "user/avatar.svg", "admin", "admin", "dev"); -INSERT INTO users (webId, userName, email, lastUpdate, password, idRole, avatar, nickName, firstName, lastName) +INSERT INTO `popcube_dev`.`users` (webId, userName, email, lastUpdate, password, idRole, avatar, nickName, firstName, lastName) VALUES ("TestUserStandard", "devstandard", "devstandard@popcube.xyz", 1105154015461, "$2a$10$IU8oU9dseYZytHcr54VXj.H9tX78hS2xUuPrzMeVN6rFG7k89i6EW", 3, "user/avatar.svg", "standard", "standard", "dev"); -INSERT INTO users (webId, userName, email, lastUpdate, password, idRole, avatar, nickName, firstName, lastName) +INSERT INTO `popcube_dev`.`users` (webId, userName, email, lastUpdate, password, idRole, avatar, nickName, firstName, lastName) VALUES ("TestUserGuest", "devguest", "devguest@popcube.xyz", 1105154015461, "$2a$10$IU8oU9dseYZytHcr54VXj.H9tX78hS2xUuPrzMeVN6rFG7k89i6EW", 4, "user/avatar.svg", "guest", "guest", "dev"); - -- ORGANISATION INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> -INSERT INTO organisations (dockerStack, organisationName, description, avatar, domain) +INSERT INTO `popcube_dev`.`organisations` (dockerStack, organisationName, description, avatar, domain) VALUES (1, "Popcube Dev", "Test for popcube", "popcube.svg", "popcubedev.popbcube.xyz"); -- MEMBERS INITITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (1, 1); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (2, 1); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (3, 1); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (4, 1); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (1, 2); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (2, 2); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (3, 2); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (4, 2); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (1, 3); -INSERT INTO members (idUser, idChannel, idRole) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel, idRole) VALUES (2, 3,3); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (3, 3); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (4, 3); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (1, 4); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (2, 4); -INSERT INTO members (idUser, idChannel, idRole) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel, idRole) VALUES (3, 4, 2); -INSERT INTO members (idUser, idChannel) +INSERT INTO `popcube_dev`.`members` (idUser, idChannel) VALUES (4, 4); -- MESSAGE INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> -INSERT INTO messages (idUser, idChannel, date, content) +INSERT INTO `popcube_dev`.`messages` (idUser, idChannel, date, content) VALUES (1, 1, 10210541, "Test message."); -INSERT INTO messages (idUser, idChannel, date, content) +INSERT INTO `popcube_dev`.`messages` (idUser, idChannel, date, content) VALUES (1, 1, 10210542, ""); -INSERT INTO messages (idUser, idChannel, date, content) +INSERT INTO `popcube_dev`.`messages` (idUser, idChannel, date, content) VALUES (1, 1, 10210543, "Test message with folder."); -- FOLDER INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> -INSERT INTO folders (idMessage, type, link, name) +INSERT INTO `popcube_dev`.`folders` (idMessage, type, link, name) VALUES (2, "txt", "folders/text.txt", "text"); -INSERT INTO folders (idMessage) +INSERT INTO `popcube_dev`.`folders` (idMessage) VALUES (3); -- EMOJIS INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> -INSERT INTO emojis (name, shortcut, link) +INSERT INTO `popcube_dev`.`emojis` (name, shortcut, link) VALUE ("troll face", ":troll:", "emojis/troll.svg"); -INSERT INTO emojis (name, shortcut, link) +INSERT INTO `popcube_dev`.`emojis` (name, shortcut, link) VALUE ("love", "<3", "emojis/love.svg"); -- AVATARS INITIALISATION <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> -INSERT INTO avatars (name, link) +INSERT INTO `popcube_dev`.`avatars` (name, link) VALUE ("troll face", "emojis/troll.svg"); -INSERT INTO avatars (name, link) +INSERT INTO `popcube_dev`.`avatars` (name, link) VALUE ("Strawberrie", "emojis/straw.svg"); \ No newline at end of file diff --git a/swagger.yaml b/swagger.yaml index 635e9e1..a5f51e2 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -1313,6 +1313,28 @@ paths: description: "genericError general error when unexpected errors occured" schema: $ref: "#/definitions/genericErrorModel" + /initorganisation: + post: + tags: + - "Init" + summary: "Try to log user in" + description: "Login user with provided USERNAME && Password" + operationId: "initOrganisation" + parameters: [] + responses: + 200: + description: "initOk" + schema: + $ref: "#/definitions/initOk" + 503: + description: "databaseError is an error object to tell what is happening\ + \ when we encounter issue with database" + schema: + $ref: "#/definitions/genericErrorModel" + default: + description: "genericError general error when unexpected errors occured" + schema: + $ref: "#/definitions/genericErrorModel" /login: post: tags: @@ -1330,8 +1352,8 @@ paths: x-go-name: "Login" responses: 200: - description: "inviteOk when invite correctly proceed, return the invite\ - \ token information and the JWT token." + description: "initOk when init correctly proceed, return the organisation\ + \ object and its owner." schema: $ref: "#/definitions/User" 404: @@ -1348,6 +1370,10 @@ paths: \ when we encounter issue with database" schema: $ref: "#/definitions/genericErrorModel" + default: + description: "genericError general error when unexpected errors occured" + schema: + $ref: "#/definitions/genericErrorModel" /member: get: tags: @@ -2146,7 +2172,15 @@ paths: description: "This will create an user for organisation if organisation is Public\ \ OR Email match parametetered emails" operationId: "newPublicUser" - parameters: [] + parameters: + - in: "body" + name: "token" + description: "Init token you got when creating new organisation. Pass it as\ + \ Authentication: bearer {{token}} in the header" + required: false + schema: + type: "string" + x-go-name: "Token" responses: 201: description: "userObjectSuccess list of users" @@ -2908,9 +2942,9 @@ definitions: AllowedWebMails: type: "object" required: - - "provider" + - "domain" properties: - description: + defaultRights: type: "string" description: "Rights that will automatically atributed to user created accound\ \ from the webmail" @@ -3715,6 +3749,27 @@ definitions: $ref: "#/definitions/genericErrorModel" description: "incorrectIds return error login message" x-go-package: "github.com/titouanfreville/popcubeapi/api" + initOk: + type: "object" + properties: + organisation: + description: "in:body" + $ref: "#/definitions/Organisation" + user: + description: "in:body" + $ref: "#/definitions/User" + title: "initOk when init correctly proceed, return the organisation object and\ + \ its owner." + x-go-package: "github.com/titouanfreville/popcubeapi/api" + initToken: + type: "object" + properties: + token: + type: "string" + description: "Init token you got when creating new organisation. Pass it as\ + \ Authentication: bearer {{token}} in the header\nin:body" + x-go-name: "Token" + x-go-package: "github.com/titouanfreville/popcubeapi/api" inviteOk: type: "object" properties: @@ -4115,8 +4170,8 @@ responses: schema: $ref: "#/definitions/genericErrorModel" loginOk: - description: "inviteOk when invite correctly proceed, return the invite token\ - \ information and the JWT token." + description: "initOk when init correctly proceed, return the organisation object\ + \ and its owner." schema: $ref: "#/definitions/User" memberArraySuccess: