diff --git a/main.go b/main.go index e7031814..f33c3bac 100644 --- a/main.go +++ b/main.go @@ -18,7 +18,7 @@ type UserLogin struct { } // Version sets the version to be printed to the user. Gets overwritten by "make release" or "make build" with last git commit or tag. -var Version = "1.0" +var Version = "0.1" func main() { diff --git a/models/crudable.go b/models/crudable.go index 4defc7f5..6d2a77f2 100644 --- a/models/crudable.go +++ b/models/crudable.go @@ -7,4 +7,8 @@ type CRUDable interface { ReadAll(*User) (interface{}, error) Update(int64) error Delete(int64) error + + // This method is needed, because old values would otherwise remain in the struct. + // TODO find a way of not needing an extra function + Empty() } diff --git a/models/error.go b/models/error.go index 902f52cb..a8b22a14 100644 --- a/models/error.go +++ b/models/error.go @@ -353,3 +353,22 @@ func IsErrNeedToBeNamespaceAdmin(err error) bool { func (err ErrNeedToBeNamespaceAdmin) Error() string { return fmt.Sprintf("You need to be namespace owner to do that [NamespaceID: %d, UserID: %d]", err.NamespaceID, err.UserID) } + +// ============ +// Team errors +// ============ + +// ErrTeamNameCannotBeEmpty represents an error, where a namespace owner is empty. +type ErrTeamNameCannotBeEmpty struct { + TeamID int64 +} + +// IsErrTeamNameCannotBeEmpty checks if an error is a ErrNamespaceDoesNotExist. +func IsErrTeamNameCannotBeEmpty(err error) bool { + _, ok := err.(ErrTeamNameCannotBeEmpty) + return ok +} + +func (err ErrTeamNameCannotBeEmpty) Error() string { + return fmt.Sprintf("Team name cannot be empty [Team ID: %d]", err.TeamID) +} diff --git a/models/teams.go b/models/teams.go index 83404c00..80c32517 100644 --- a/models/teams.go +++ b/models/teams.go @@ -2,16 +2,19 @@ package models // Team holds a team object type Team struct { - ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"` - Name string `xorm:"varchar(250) not null" json:"name"` - Description string `xorm:"varchar(250)" json:"description"` - Rights []int64 `xorm:"varchar(250)" json:"rights"` - CreatedByID int64 `xorm:"int(11) not null" json:"-"` + ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"` + Name string `xorm:"varchar(250) not null" json:"name"` + Description string `xorm:"varchar(250)" json:"description"` + CreatedByID int64 `xorm:"int(11) not null" json:"-"` + + CreatedBy *User `xorm:"-" json:"created_by"` + Members []*User `xorm:"-" json:"members"` Created int64 `xorm:"created" json:"created"` Updated int64 `xorm:"updated" json:"updated"` - CreatedBy User `json:"created_by"` + CRUDable `xorm:"-" json:"-"` + Rights `xorm:"-" json:"-"` } // TableName makes beautiful table names @@ -19,14 +22,19 @@ func (Team) TableName() string { return "teams" } +func (t *Team) AfterLoad() { + // Get the owner + *t.CreatedBy, _, _ = GetUserByID(t.CreatedByID) +} + // TeamMember defines the relationship between a user and a team type TeamMember struct { - ID int64 `xorm:"int(11) autoincr not null unique pk"` - TeamID int64 `xorm:"int(11) autoincr not null"` - UserID int64 `xorm:"int(11) autoincr not null"` + ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"` + TeamID int64 `xorm:"int(11) not null" json:"team_id"` + UserID int64 `xorm:"int(11) not null" json:"user_id"` - Created int64 `xorm:"created"` - Updated int64 `xorm:"updated"` + Created int64 `xorm:"created" json:"created"` + Updated int64 `xorm:"updated" json:"updated"` } // TableName makes beautiful table names @@ -36,12 +44,13 @@ func (TeamMember) TableName() string { // TeamNamespace defines the relationship between a Team and a Namespace type TeamNamespace struct { - ID int64 `xorm:"int(11) autoincr not null unique pk"` - TeamID int64 `xorm:"int(11) autoincr not null"` - NamespaceID int64 `xorm:"int(11) autoincr not null"` + ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"` + TeamID int64 `xorm:"int(11) not null" json:"team_id"` + NamespaceID int64 `xorm:"int(11) not null" json:"namespace_id"` + Rights []int64 `xorm:"varchar(250)" json:"rights"` - Created int64 `xorm:"created"` - Updated int64 `xorm:"updated"` + Created int64 `xorm:"created" json:"created"` + Updated int64 `xorm:"updated" json:"updated"` } // TableName makes beautiful table names @@ -51,12 +60,13 @@ func (TeamNamespace) TableName() string { // TeamList defines the relation between a team and a list type TeamList struct { - ID int64 `xorm:"int(11) autoincr not null unique pk"` - TeamID int64 `xorm:"int(11) autoincr not null"` - ListID int64 `xorm:"int(11) autoincr not null"` + ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"` + TeamID int64 `xorm:"int(11) not null" json:"team_id"` + ListID int64 `xorm:"int(11) not null" json:"list_id"` + Rights []int64 `xorm:"varchar(250)" json:"rights"` - Created int64 `xorm:"created"` - Updated int64 `xorm:"updated"` + Created int64 `xorm:"created" json:"created"` + Updated int64 `xorm:"updated" json:"updated"` } // TableName makes beautiful table names @@ -73,3 +83,15 @@ func GetAllTeamsByNamespaceID(id int64) (teams []*Team, err error) { return } + +// Empty empties a struct. Because we heavily use pointers, the old values remain in the struct. +// If you then update by not providing evrything, you have i.e. the old description still in the +// newly created team, but you didn't provided one. +func (t *Team) Empty() { + t.ID = 0 + t.CreatedByID = 0 + t.CreatedBy = &User{} + t.Name = "" + t.Description = "" + t.Members = []*User{} +} \ No newline at end of file diff --git a/models/teams_create.go b/models/teams_create.go new file mode 100644 index 00000000..b8cacccf --- /dev/null +++ b/models/teams_create.go @@ -0,0 +1,19 @@ +package models + +func (t *Team) Create(doer *User, _ int64) (err error) { + // Check if we have a name + if t.Name == "" { + return ErrTeamNameCannotBeEmpty{} + } + + // Set the id to 0, otherwise the creation fails because of double keys + t.CreatedByID = doer.ID + t.CreatedBy = doer + + _, err = x.Insert(t) + if err != nil { + return + } + + return +} diff --git a/models/teams_rights.go b/models/teams_rights.go new file mode 100644 index 00000000..3de722ee --- /dev/null +++ b/models/teams_rights.go @@ -0,0 +1,7 @@ +package models + +// CanCreate checks if the user can create a new team +func (n *Team) CanCreate(user *User, id int64) bool { + // This is currently a dummy function, later on we could imagine global limits etc. + return true +} \ No newline at end of file diff --git a/routes/crud/create.go b/routes/crud/create.go index 2f4851fb..cf4c751e 100644 --- a/routes/crud/create.go +++ b/routes/crud/create.go @@ -4,10 +4,14 @@ import ( "git.kolaente.de/konrad/list/models" "github.com/labstack/echo" "net/http" + "fmt" ) // CreateWeb is the handler to create an object func (c *WebHandler) CreateWeb(ctx echo.Context) error { + // Re-initialize our model + c.CObject.Empty() + // Get the object if err := ctx.Bind(&c.CObject); err != nil { return echo.NewHTTPError(http.StatusBadRequest, "No or invalid model provided.") @@ -53,6 +57,8 @@ func (c *WebHandler) CreateWeb(ctx echo.Context) error { return echo.NewHTTPError(http.StatusNotFound, "The namespace name cannot be empty.") } + fmt.Println(err) + return echo.NewHTTPError(http.StatusInternalServerError) } diff --git a/routes/routes.go b/routes/routes.go index f2fd0be0..b6109f6c 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -112,4 +112,13 @@ func RegisterRoutes(e *echo.Echo) { a.POST("/namespaces/:id", namespaceHandler.UpdateWeb) a.DELETE("/namespaces/:id", namespaceHandler.DeleteWeb) a.GET("/namespaces/:id/lists", apiv1.GetListsByNamespaceID) + + teamHandler := &crud.WebHandler{ + CObject: &models.Team{}, + } + a.GET("/teams", teamHandler.ReadAllWeb) + a.GET("/teams/:id", teamHandler.ReadOneWeb) + a.PUT("/teams", teamHandler.CreateWeb) + a.POST("/teams/:id", teamHandler.UpdateWeb) + a.POST("/teams/:id", teamHandler.DeleteWeb) }