feat: rename lists to projects
This commit is contained in:
File diff suppressed because one or more lines are too long
@ -31,7 +31,7 @@ import (
|
||||
type LinkShareToken struct {
|
||||
auth.Token
|
||||
*models.LinkSharing
|
||||
ListID int64 `json:"list_id"`
|
||||
ProjectID int64 `json:"project_id"`
|
||||
}
|
||||
|
||||
// LinkShareAuth represents everything required to authenticate a link share
|
||||
@ -42,7 +42,7 @@ type LinkShareAuth struct {
|
||||
|
||||
// AuthenticateLinkShare gives a jwt auth token for valid share hashes
|
||||
// @Summary Get an auth token for a share
|
||||
// @Description Get a jwt auth token for a shared list from a share hash.
|
||||
// @Description Get a jwt auth token for a shared project from a share hash.
|
||||
// @tags sharing
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
@ -84,6 +84,6 @@ func AuthenticateLinkShare(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, LinkShareToken{
|
||||
Token: auth.Token{Token: t},
|
||||
LinkSharing: share,
|
||||
ListID: share.ListID,
|
||||
ProjectID: share.ProjectID,
|
||||
})
|
||||
}
|
||||
|
@ -29,21 +29,21 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// GetListsByNamespaceID is the web handler to delete a namespace
|
||||
// TODO: depricate this in favour of namespace.ReadOne() <-- should also return the lists
|
||||
// @Summary Get all lists in a namespace
|
||||
// @Description Returns all lists inside of a namespace.
|
||||
// GetProjectsByNamespaceID is the web handler to delete a namespace
|
||||
// TODO: depricate this in favour of namespace.ReadOne() <-- should also return the projects
|
||||
// @Summary Get all projects in a namespace
|
||||
// @Description Returns all projects inside of a namespace.
|
||||
// @tags namespace
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Namespace ID"
|
||||
// @Security JWTKeyAuth
|
||||
// @Success 200 {array} models.List "The lists."
|
||||
// @Success 200 {array} models.Project "The projects."
|
||||
// @Failure 403 {object} models.Message "No access to that namespace."
|
||||
// @Failure 404 {object} models.Message "The namespace does not exist."
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /namespaces/{id}/lists [get]
|
||||
func GetListsByNamespaceID(c echo.Context) error {
|
||||
// @Router /namespaces/{id}/projects [get]
|
||||
func GetProjectsByNamespaceID(c echo.Context) error {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
@ -53,17 +53,17 @@ func GetListsByNamespaceID(c echo.Context) error {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
// Get the lists
|
||||
// Get the projects
|
||||
doer, err := user.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
lists, err := models.GetListsByNamespaceID(s, namespace.ID, doer)
|
||||
projects, err := models.GetProjectsByNamespaceID(s, namespace.ID, doer)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
return c.JSON(http.StatusOK, lists)
|
||||
return c.JSON(http.StatusOK, projects)
|
||||
}
|
||||
|
||||
func getNamespace(s *xorm.Session, c echo.Context) (namespace *models.Namespace, err error) {
|
||||
@ -76,7 +76,7 @@ func getNamespace(s *xorm.Session, c echo.Context) (namespace *models.Namespace,
|
||||
}
|
||||
|
||||
if namespaceID == -1 {
|
||||
namespace = &models.SharedListsPseudoNamespace
|
||||
namespace = &models.SharedProjectsPseudoNamespace
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ func GenerateCaldavToken(c echo.Context) (err error) {
|
||||
return c.JSON(http.StatusCreated, token)
|
||||
}
|
||||
|
||||
// GetCaldavTokens is the handler to return a list of all caldav tokens for the current user
|
||||
// GetCaldavTokens is the handler to return a project of all caldav tokens for the current user
|
||||
// @Summary Returns the caldav tokens for the current user
|
||||
// @Description Return the IDs and created dates of all caldav tokens for the current user.
|
||||
// @tags user
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// UserList gets all information about a user
|
||||
// UserProject gets all information about a user
|
||||
// @Summary Get users
|
||||
// @Description Search for a user by its username, name or full email. Name (not username) or email require that the user has enabled this in their settings.
|
||||
// @tags user
|
||||
@ -41,13 +41,13 @@ import (
|
||||
// @Failure 400 {object} web.HTTPError "Something's invalid."
|
||||
// @Failure 500 {object} models.Message "Internal server error."
|
||||
// @Router /users [get]
|
||||
func UserList(c echo.Context) error {
|
||||
func UserProject(c echo.Context) error {
|
||||
search := c.QueryParam("s")
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
users, err := user.ListUsers(s, search, nil)
|
||||
users, err := user.ProjectUsers(s, search, nil)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
@ -66,27 +66,27 @@ func UserList(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, users)
|
||||
}
|
||||
|
||||
// ListUsersForList returns a list with all users who have access to a list, regardless of the method the list was shared with them.
|
||||
// ProjectUsersForProject returns a project with all users who have access to a project, regardless of the method the project was shared with them.
|
||||
// @Summary Get users
|
||||
// @Description Lists all users (without emailadresses). Also possible to search for a specific user.
|
||||
// @tags list
|
||||
// @Description Projects all users (without emailadresses). Also possible to search for a specific user.
|
||||
// @tags project
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param s query string false "Search for a user by its name."
|
||||
// @Security JWTKeyAuth
|
||||
// @Param id path int true "List ID"
|
||||
// @Param id path int true "Project ID"
|
||||
// @Success 200 {array} user.User "All (found) users."
|
||||
// @Failure 400 {object} web.HTTPError "Something's invalid."
|
||||
// @Failure 401 {object} web.HTTPError "The user does not have the right to see the list."
|
||||
// @Failure 401 {object} web.HTTPError "The user does not have the right to see the project."
|
||||
// @Failure 500 {object} models.Message "Internal server error."
|
||||
// @Router /lists/{id}/listusers [get]
|
||||
func ListUsersForList(c echo.Context) error {
|
||||
listID, err := strconv.ParseInt(c.Param("list"), 10, 64)
|
||||
// @Router /projects/{id}/projectusers [get]
|
||||
func ProjectUsersForProject(c echo.Context) error {
|
||||
projectID, err := strconv.ParseInt(c.Param("project"), 10, 64)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
list := models.List{ID: listID}
|
||||
project := models.Project{ID: projectID}
|
||||
auth, err := auth2.GetAuthFromClaims(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
@ -95,7 +95,7 @@ func ListUsersForList(c echo.Context) error {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
canRead, _, err := list.CanRead(s, auth)
|
||||
canRead, _, err := project.CanRead(s, auth)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
@ -105,7 +105,7 @@ func ListUsersForList(c echo.Context) error {
|
||||
}
|
||||
|
||||
search := c.QueryParam("s")
|
||||
users, err := models.ListUsersFromList(s, &list, search)
|
||||
users, err := models.ProjectUsersFromProject(s, &project, search)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return handler.HandleHTTPError(err, c)
|
||||
|
@ -50,9 +50,9 @@ type UserSettings struct {
|
||||
OverdueTasksRemindersEnabled bool `json:"overdue_tasks_reminders_enabled"`
|
||||
// The time when the daily summary of overdue tasks will be sent via email.
|
||||
OverdueTasksRemindersTime string `json:"overdue_tasks_reminders_time" valid:"time,required"`
|
||||
// If a task is created without a specified list this value should be used. Applies
|
||||
// If a task is created without a specified project this value should be used. Applies
|
||||
// to tasks made directly in API and from clients.
|
||||
DefaultListID int64 `json:"default_list_id"`
|
||||
DefaultProjectID int64 `json:"default_project_id"`
|
||||
// The day when the week starts for this user. 0 = sunday, 1 = monday, etc.
|
||||
WeekStart int `json:"week_start" valid:"range(0|7)"`
|
||||
// The user's language
|
||||
@ -193,7 +193,7 @@ func UpdateGeneralUserSettings(c echo.Context) error {
|
||||
user.DiscoverableByEmail = us.DiscoverableByEmail
|
||||
user.DiscoverableByName = us.DiscoverableByName
|
||||
user.OverdueTasksRemindersEnabled = us.OverdueTasksRemindersEnabled
|
||||
user.DefaultListID = us.DefaultListID
|
||||
user.DefaultProjectID = us.DefaultProjectID
|
||||
user.WeekStart = us.WeekStart
|
||||
user.Language = us.Language
|
||||
user.Timezone = us.Timezone
|
||||
@ -215,7 +215,7 @@ func UpdateGeneralUserSettings(c echo.Context) error {
|
||||
|
||||
// GetAvailableTimezones
|
||||
// @Summary Get all available time zones on this vikunja instance
|
||||
// @Description Because available time zones depend on the system Vikunja is running on, this endpoint returns a list of all valid time zones this particular Vikunja instance can handle. The list of time zones is not sorted, you should sort it on the client.
|
||||
// @Description Because available time zones depend on the system Vikunja is running on, this endpoint returns a project of all valid time zones this particular Vikunja instance can handle. The project of time zones is not sorted, you should sort it on the client.
|
||||
// @tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
|
@ -71,7 +71,7 @@ func UserShow(c echo.Context) error {
|
||||
DiscoverableByName: u.DiscoverableByName,
|
||||
DiscoverableByEmail: u.DiscoverableByEmail,
|
||||
OverdueTasksRemindersEnabled: u.OverdueTasksRemindersEnabled,
|
||||
DefaultListID: u.DefaultListID,
|
||||
DefaultProjectID: u.DefaultProjectID,
|
||||
WeekStart: u.WeekStart,
|
||||
Language: u.Language,
|
||||
Timezone: u.Timezone,
|
||||
|
@ -42,9 +42,9 @@ func getBasicAuthUserFromContext(c echo.Context) (*user.User, error) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// ListHandler returns all tasks from a list
|
||||
func ListHandler(c echo.Context) error {
|
||||
listID, err := getIntParam(c, "list")
|
||||
// ProjectHandler returns all tasks from a project
|
||||
func ProjectHandler(c echo.Context) error {
|
||||
projectID, err := getIntParam(c, "project")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -55,9 +55,9 @@ func ListHandler(c echo.Context) error {
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
|
||||
storage := &VikunjaCaldavListStorage{
|
||||
list: &models.ListWithTasksAndBuckets{List: models.List{ID: listID}},
|
||||
user: u,
|
||||
storage := &VikunjaCaldavProjectStorage{
|
||||
project: &models.ProjectWithTasksAndBuckets{Project: models.Project{ID: projectID}},
|
||||
user: u,
|
||||
}
|
||||
|
||||
// Try to parse a task from the request payload
|
||||
@ -78,7 +78,7 @@ func ListHandler(c echo.Context) error {
|
||||
log.Debugf("[CALDAV] Request Headers: %v\n", c.Request().Header)
|
||||
|
||||
caldav.SetupStorage(storage)
|
||||
caldav.SetupUser("dav/lists")
|
||||
caldav.SetupUser("dav/projects")
|
||||
caldav.SetupSupportedComponents([]string{lib.VCALENDAR, lib.VTODO})
|
||||
response := caldav.HandleRequest(c.Request())
|
||||
response.Write(c.Response())
|
||||
@ -87,7 +87,7 @@ func ListHandler(c echo.Context) error {
|
||||
|
||||
// TaskHandler is the handler which manages updating/deleting a single task
|
||||
func TaskHandler(c echo.Context) error {
|
||||
listID, err := getIntParam(c, "list")
|
||||
projectID, err := getIntParam(c, "project")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -101,10 +101,10 @@ func TaskHandler(c echo.Context) error {
|
||||
// Get the task uid
|
||||
taskUID := strings.TrimSuffix(c.Param("task"), ".ics")
|
||||
|
||||
storage := &VikunjaCaldavListStorage{
|
||||
list: &models.ListWithTasksAndBuckets{List: models.List{ID: listID}},
|
||||
task: &models.Task{UID: taskUID},
|
||||
user: u,
|
||||
storage := &VikunjaCaldavProjectStorage{
|
||||
project: &models.ProjectWithTasksAndBuckets{Project: models.Project{ID: projectID}},
|
||||
task: &models.Task{UID: taskUID},
|
||||
user: u,
|
||||
}
|
||||
|
||||
caldav.SetupStorage(storage)
|
||||
@ -121,7 +121,7 @@ func PrincipalHandler(c echo.Context) error {
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
|
||||
storage := &VikunjaCaldavListStorage{
|
||||
storage := &VikunjaCaldavProjectStorage{
|
||||
user: u,
|
||||
isPrincipal: true,
|
||||
}
|
||||
@ -151,7 +151,7 @@ func EntryHandler(c echo.Context) error {
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
|
||||
storage := &VikunjaCaldavListStorage{
|
||||
storage := &VikunjaCaldavProjectStorage{
|
||||
user: u,
|
||||
isEntry: true,
|
||||
}
|
||||
|
@ -35,13 +35,13 @@ import (
|
||||
// DavBasePath is the base url path
|
||||
const DavBasePath = `/dav/`
|
||||
|
||||
// ListBasePath is the base path for all lists resources
|
||||
const ListBasePath = DavBasePath + `lists`
|
||||
// ProjectBasePath is the base path for all projects resources
|
||||
const ProjectBasePath = DavBasePath + `projects`
|
||||
|
||||
// VikunjaCaldavListStorage represents a list storage
|
||||
type VikunjaCaldavListStorage struct {
|
||||
// Used when handling a list
|
||||
list *models.ListWithTasksAndBuckets
|
||||
// VikunjaCaldavProjectStorage represents a project storage
|
||||
type VikunjaCaldavProjectStorage struct {
|
||||
// Used when handling a project
|
||||
project *models.ProjectWithTasksAndBuckets
|
||||
// Used when handling a single task, like updating
|
||||
task *models.Task
|
||||
// The current user
|
||||
@ -50,8 +50,8 @@ type VikunjaCaldavListStorage struct {
|
||||
isEntry bool // Entry level handling should only return a link to the principal url
|
||||
}
|
||||
|
||||
// GetResources returns either all lists, links to the principal, or only one list, depending on the request
|
||||
func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bool) ([]data.Resource, error) {
|
||||
// GetResources returns either all projects, links to the principal, or only one project, depending on the request
|
||||
func (vcls *VikunjaCaldavProjectStorage) GetResources(rpath string, withChildren bool) ([]data.Resource, error) {
|
||||
|
||||
// It looks like we need to have the same handler for returning both the calendar home set and the user principal
|
||||
// Since the client seems to ignore the whatever is being returned in the first request and just makes a second one
|
||||
@ -61,12 +61,12 @@ func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bo
|
||||
// the home or principal url. Ough.
|
||||
|
||||
// Ok, maybe the problem is more the client making a request to /dav/ and getting a response which says
|
||||
// something like "hey, for /dav/lists, the calendar home is /dav/lists", but the client expects a
|
||||
// response to go something like "hey, for /dav/, the calendar home is /dav/lists" since it requested /dav/
|
||||
// and not /dav/lists. I'm not sure if thats a bug in the client or in caldav-go.
|
||||
// something like "hey, for /dav/projects, the calendar home is /dav/projects", but the client expects a
|
||||
// response to go something like "hey, for /dav/, the calendar home is /dav/projects" since it requested /dav/
|
||||
// and not /dav/projects. I'm not sure if thats a bug in the client or in caldav-go.
|
||||
|
||||
if vcls.isEntry {
|
||||
r := data.NewResource(rpath, &VikunjaListResourceAdapter{
|
||||
r := data.NewResource(rpath, &VikunjaProjectResourceAdapter{
|
||||
isPrincipal: true,
|
||||
isCollection: true,
|
||||
})
|
||||
@ -75,30 +75,30 @@ func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bo
|
||||
|
||||
// If the request wants the principal url, we'll return that and nothing else
|
||||
if vcls.isPrincipal {
|
||||
r := data.NewResource(DavBasePath+`/lists/`, &VikunjaListResourceAdapter{
|
||||
r := data.NewResource(DavBasePath+`/projects/`, &VikunjaProjectResourceAdapter{
|
||||
isPrincipal: true,
|
||||
isCollection: true,
|
||||
})
|
||||
return []data.Resource{r}, nil
|
||||
}
|
||||
|
||||
// If vcls.list.ID is != 0, this means the user is doing a PROPFIND request to /lists/:list
|
||||
// Which means we need to get only one list
|
||||
if vcls.list != nil && vcls.list.ID != 0 {
|
||||
rr, err := vcls.getListRessource(true)
|
||||
// If vcls.project.ID is != 0, this means the user is doing a PROPFIND request to /projects/:project
|
||||
// Which means we need to get only one project
|
||||
if vcls.project != nil && vcls.project.ID != 0 {
|
||||
rr, err := vcls.getProjectRessource(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := data.NewResource(rpath, &rr)
|
||||
r.Name = vcls.list.Title
|
||||
r.Name = vcls.project.Title
|
||||
return []data.Resource{r}, nil
|
||||
}
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// Otherwise get all lists
|
||||
thelists, _, _, err := vcls.list.ReadAll(s, vcls.user, "", -1, 50)
|
||||
// Otherwise get all projects
|
||||
theprojects, _, _, err := vcls.project.ReadAll(s, vcls.user, "", -1, 50)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return nil, err
|
||||
@ -106,17 +106,17 @@ func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bo
|
||||
if err := s.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lists := thelists.([]*models.List)
|
||||
projects := theprojects.([]*models.Project)
|
||||
|
||||
var resources []data.Resource
|
||||
for _, l := range lists {
|
||||
rr := VikunjaListResourceAdapter{
|
||||
list: &models.ListWithTasksAndBuckets{
|
||||
List: *l,
|
||||
for _, l := range projects {
|
||||
rr := VikunjaProjectResourceAdapter{
|
||||
project: &models.ProjectWithTasksAndBuckets{
|
||||
Project: *l,
|
||||
},
|
||||
isCollection: true,
|
||||
}
|
||||
r := data.NewResource(ListBasePath+"/"+strconv.FormatInt(l.ID, 10), &rr)
|
||||
r := data.NewResource(ProjectBasePath+"/"+strconv.FormatInt(l.ID, 10), &rr)
|
||||
r.Name = l.Title
|
||||
resources = append(resources, r)
|
||||
}
|
||||
@ -124,11 +124,11 @@ func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bo
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
// GetResourcesByList fetches a list of resources from a slice of paths
|
||||
func (vcls *VikunjaCaldavListStorage) GetResourcesByList(rpaths []string) ([]data.Resource, error) {
|
||||
// GetResourcesByList fetches a project of resources from a slice of paths
|
||||
func (vcls *VikunjaCaldavProjectStorage) GetResourcesByList(rpaths []string) ([]data.Resource, error) {
|
||||
|
||||
// Parse the set of resourcepaths into usable uids
|
||||
// A path looks like this: /dav/lists/10/a6eb526d5748a5c499da202fe74f36ed1aea2aef.ics
|
||||
// A path looks like this: /dav/projects/10/a6eb526d5748a5c499da202fe74f36ed1aea2aef.ics
|
||||
// So we split the url in parts, take the last one and strip the ".ics" at the end
|
||||
var uids []string
|
||||
for _, path := range rpaths {
|
||||
@ -154,7 +154,7 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByList(rpaths []string) ([]dat
|
||||
|
||||
var resources []data.Resource
|
||||
for _, t := range tasks {
|
||||
rr := VikunjaListResourceAdapter{
|
||||
rr := VikunjaProjectResourceAdapter{
|
||||
task: t,
|
||||
}
|
||||
r := data.NewResource(getTaskURL(t), &rr)
|
||||
@ -165,17 +165,17 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByList(rpaths []string) ([]dat
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
// GetResourcesByFilters fetches a list of resources with a filter
|
||||
func (vcls *VikunjaCaldavListStorage) GetResourcesByFilters(rpath string, filters *data.ResourceFilter) ([]data.Resource, error) {
|
||||
// GetResourcesByFilters fetches a project of resources with a filter
|
||||
func (vcls *VikunjaCaldavProjectStorage) GetResourcesByFilters(rpath string, filters *data.ResourceFilter) ([]data.Resource, error) {
|
||||
|
||||
// If we already have a list saved, that means the user is making a REPORT request to find out if
|
||||
// If we already have a project saved, that means the user is making a REPORT request to find out if
|
||||
// anything changed, in that case we need to return all tasks.
|
||||
// That list is coming from a previous "getListRessource" in L177
|
||||
if vcls.list.Tasks != nil {
|
||||
// That project is coming from a previous "getProjectRessource" in L177
|
||||
if vcls.project.Tasks != nil {
|
||||
var resources []data.Resource
|
||||
for _, t := range vcls.list.Tasks {
|
||||
rr := VikunjaListResourceAdapter{
|
||||
list: vcls.list,
|
||||
for _, t := range vcls.project.Tasks {
|
||||
rr := VikunjaProjectResourceAdapter{
|
||||
project: vcls.project,
|
||||
task: &t.Task,
|
||||
isCollection: false,
|
||||
}
|
||||
@ -187,25 +187,25 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByFilters(rpath string, filter
|
||||
}
|
||||
|
||||
// This is used to get all
|
||||
rr, err := vcls.getListRessource(false)
|
||||
rr, err := vcls.getProjectRessource(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r := data.NewResource(rpath, &rr)
|
||||
r.Name = vcls.list.Title
|
||||
r.Name = vcls.project.Title
|
||||
return []data.Resource{r}, nil
|
||||
// For now, filtering is disabled.
|
||||
// return vcls.GetResources(rpath, false)
|
||||
}
|
||||
|
||||
func getTaskURL(task *models.Task) string {
|
||||
return ListBasePath + "/" + strconv.FormatInt(task.ListID, 10) + `/` + task.UID + `.ics`
|
||||
return ProjectBasePath + "/" + strconv.FormatInt(task.ProjectID, 10) + `/` + task.UID + `.ics`
|
||||
}
|
||||
|
||||
// GetResource fetches a single resource
|
||||
func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource, bool, error) {
|
||||
func (vcls *VikunjaCaldavProjectStorage) GetResource(rpath string) (*data.Resource, bool, error) {
|
||||
|
||||
// If the task is not nil, we need to get the task and not the list
|
||||
// If the task is not nil, we need to get the task and not the project
|
||||
if vcls.task != nil {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
@ -233,16 +233,16 @@ func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource,
|
||||
vcls.task.Updated = updated
|
||||
}
|
||||
|
||||
rr := VikunjaListResourceAdapter{
|
||||
list: vcls.list,
|
||||
task: vcls.task,
|
||||
rr := VikunjaProjectResourceAdapter{
|
||||
project: vcls.project,
|
||||
task: vcls.task,
|
||||
}
|
||||
r := data.NewResource(rpath, &rr)
|
||||
return &r, true, nil
|
||||
}
|
||||
|
||||
// Otherwise get the list with all tasks
|
||||
rr, err := vcls.getListRessource(true)
|
||||
// Otherwise get the project with all tasks
|
||||
rr, err := vcls.getProjectRessource(true)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@ -252,14 +252,14 @@ func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource,
|
||||
|
||||
// GetShallowResource gets a ressource without childs
|
||||
// Since Vikunja has no children, this is the same as GetResource
|
||||
func (vcls *VikunjaCaldavListStorage) GetShallowResource(rpath string) (*data.Resource, bool, error) {
|
||||
func (vcls *VikunjaCaldavProjectStorage) GetShallowResource(rpath string) (*data.Resource, bool, error) {
|
||||
// Since Vikunja has no childs, this just returns the same as GetResource()
|
||||
// FIXME: This should just get the list with no tasks whatsoever, nothing else
|
||||
// FIXME: This should just get the project with no tasks whatsoever, nothing else
|
||||
return vcls.GetResource(rpath)
|
||||
}
|
||||
|
||||
// CreateResource creates a new resource
|
||||
func (vcls *VikunjaCaldavListStorage) CreateResource(rpath, content string) (*data.Resource, error) {
|
||||
func (vcls *VikunjaCaldavProjectStorage) CreateResource(rpath, content string) (*data.Resource, error) {
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
@ -269,7 +269,7 @@ func (vcls *VikunjaCaldavListStorage) CreateResource(rpath, content string) (*da
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vTask.ListID = vcls.list.ID
|
||||
vTask.ProjectID = vcls.project.ID
|
||||
|
||||
// Check the rights
|
||||
canCreate, err := vTask.CanCreate(s, vcls.user)
|
||||
@ -299,16 +299,16 @@ func (vcls *VikunjaCaldavListStorage) CreateResource(rpath, content string) (*da
|
||||
}
|
||||
|
||||
// Build up the proper response
|
||||
rr := VikunjaListResourceAdapter{
|
||||
list: vcls.list,
|
||||
task: vTask,
|
||||
rr := VikunjaProjectResourceAdapter{
|
||||
project: vcls.project,
|
||||
task: vTask,
|
||||
}
|
||||
r := data.NewResource(rpath, &rr)
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
// UpdateResource updates a resource
|
||||
func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*data.Resource, error) {
|
||||
func (vcls *VikunjaCaldavProjectStorage) UpdateResource(rpath, content string) (*data.Resource, error) {
|
||||
|
||||
vTask, err := caldav.ParseTaskFromVTODO(content)
|
||||
if err != nil {
|
||||
@ -350,16 +350,16 @@ func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*da
|
||||
}
|
||||
|
||||
// Build up the proper response
|
||||
rr := VikunjaListResourceAdapter{
|
||||
list: vcls.list,
|
||||
task: vTask,
|
||||
rr := VikunjaProjectResourceAdapter{
|
||||
project: vcls.project,
|
||||
task: vTask,
|
||||
}
|
||||
r := data.NewResource(rpath, &rr)
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
// DeleteResource deletes a resource
|
||||
func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error {
|
||||
func (vcls *VikunjaCaldavProjectStorage) DeleteResource(rpath string) error {
|
||||
if vcls.task != nil {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
@ -432,31 +432,31 @@ func persistLabels(s *xorm.Session, a web.Auth, task *models.Task, labels []*mod
|
||||
return task.UpdateTaskLabels(s, a, labels)
|
||||
}
|
||||
|
||||
// VikunjaListResourceAdapter holds the actual resource
|
||||
type VikunjaListResourceAdapter struct {
|
||||
list *models.ListWithTasksAndBuckets
|
||||
listTasks []*models.TaskWithComments
|
||||
task *models.Task
|
||||
// VikunjaProjectResourceAdapter holds the actual resource
|
||||
type VikunjaProjectResourceAdapter struct {
|
||||
project *models.ProjectWithTasksAndBuckets
|
||||
projectTasks []*models.TaskWithComments
|
||||
task *models.Task
|
||||
|
||||
isPrincipal bool
|
||||
isCollection bool
|
||||
}
|
||||
|
||||
// IsCollection checks if the resoure in the adapter is a collection
|
||||
func (vlra *VikunjaListResourceAdapter) IsCollection() bool {
|
||||
func (vlra *VikunjaProjectResourceAdapter) IsCollection() bool {
|
||||
// If the discovery does not work, setting this to true makes it work again.
|
||||
return vlra.isCollection
|
||||
}
|
||||
|
||||
// CalculateEtag returns the etag of a resource
|
||||
func (vlra *VikunjaListResourceAdapter) CalculateEtag() string {
|
||||
func (vlra *VikunjaProjectResourceAdapter) CalculateEtag() string {
|
||||
|
||||
// If we're updating a task, the client sends the etag of the list instead of the one from the task.
|
||||
// If we're updating a task, the client sends the etag of the project instead of the one from the task.
|
||||
// And therefore, updating the task fails since these etags don't match.
|
||||
// To fix that, we use this extra field to determine if we're currently updating a task and return the
|
||||
// etag of the list instead.
|
||||
// if vlra.list != nil {
|
||||
// return `"` + strconv.FormatInt(vlra.list.ID, 10) + `-` + strconv.FormatInt(vlra.list.Updated, 10) + `"`
|
||||
// etag of the project instead.
|
||||
// if vlra.project != nil {
|
||||
// return `"` + strconv.FormatInt(vlra.project.ID, 10) + `-` + strconv.FormatInt(vlra.project.Updated, 10) + `"`
|
||||
// }
|
||||
|
||||
// Return the etag of a task if we have one
|
||||
@ -464,76 +464,76 @@ func (vlra *VikunjaListResourceAdapter) CalculateEtag() string {
|
||||
return `"` + strconv.FormatInt(vlra.task.ID, 10) + `-` + strconv.FormatInt(vlra.task.Updated.Unix(), 10) + `"`
|
||||
}
|
||||
|
||||
if vlra.list == nil {
|
||||
if vlra.project == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// This also returns the etag of the list, and not of the task,
|
||||
// which becomes problematic because the client uses this etag (= the one from the list) to make
|
||||
// This also returns the etag of the project, and not of the task,
|
||||
// which becomes problematic because the client uses this etag (= the one from the project) to make
|
||||
// Requests to update a task. These do not match and thus updating a task fails.
|
||||
return `"` + strconv.FormatInt(vlra.list.ID, 10) + `-` + strconv.FormatInt(vlra.list.Updated.Unix(), 10) + `"`
|
||||
return `"` + strconv.FormatInt(vlra.project.ID, 10) + `-` + strconv.FormatInt(vlra.project.Updated.Unix(), 10) + `"`
|
||||
}
|
||||
|
||||
// GetContent returns the content string of a resource (a task in our case)
|
||||
func (vlra *VikunjaListResourceAdapter) GetContent() string {
|
||||
if vlra.list != nil && vlra.list.Tasks != nil {
|
||||
return caldav.GetCaldavTodosForTasks(vlra.list, vlra.listTasks)
|
||||
func (vlra *VikunjaProjectResourceAdapter) GetContent() string {
|
||||
if vlra.project != nil && vlra.project.Tasks != nil {
|
||||
return caldav.GetCaldavTodosForTasks(vlra.project, vlra.projectTasks)
|
||||
}
|
||||
|
||||
if vlra.task != nil {
|
||||
list := models.ListWithTasksAndBuckets{Tasks: []*models.TaskWithComments{{Task: *vlra.task}}}
|
||||
return caldav.GetCaldavTodosForTasks(&list, list.Tasks)
|
||||
project := models.ProjectWithTasksAndBuckets{Tasks: []*models.TaskWithComments{{Task: *vlra.task}}}
|
||||
return caldav.GetCaldavTodosForTasks(&project, project.Tasks)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetContentSize is the size of a caldav content
|
||||
func (vlra *VikunjaListResourceAdapter) GetContentSize() int64 {
|
||||
func (vlra *VikunjaProjectResourceAdapter) GetContentSize() int64 {
|
||||
return int64(len(vlra.GetContent()))
|
||||
}
|
||||
|
||||
// GetModTime returns when the resource was last modified
|
||||
func (vlra *VikunjaListResourceAdapter) GetModTime() time.Time {
|
||||
func (vlra *VikunjaProjectResourceAdapter) GetModTime() time.Time {
|
||||
if vlra.task != nil {
|
||||
return vlra.task.Updated
|
||||
}
|
||||
|
||||
if vlra.list != nil {
|
||||
return vlra.list.Updated
|
||||
if vlra.project != nil {
|
||||
return vlra.project.Updated
|
||||
}
|
||||
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (vcls *VikunjaCaldavListStorage) getListRessource(isCollection bool) (rr VikunjaListResourceAdapter, err error) {
|
||||
func (vcls *VikunjaCaldavProjectStorage) getProjectRessource(isCollection bool) (rr VikunjaProjectResourceAdapter, err error) {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
if vcls.list == nil {
|
||||
if vcls.project == nil {
|
||||
return
|
||||
}
|
||||
|
||||
can, _, err := vcls.list.CanRead(s, vcls.user)
|
||||
can, _, err := vcls.project.CanRead(s, vcls.user)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return
|
||||
}
|
||||
if !can {
|
||||
_ = s.Rollback()
|
||||
log.Errorf("User %v tried to access a caldav resource (List %v) which they are not allowed to access", vcls.user.Username, vcls.list.ID)
|
||||
return rr, models.ErrUserDoesNotHaveAccessToList{ListID: vcls.list.ID}
|
||||
log.Errorf("User %v tried to access a caldav resource (Project %v) which they are not allowed to access", vcls.user.Username, vcls.project.ID)
|
||||
return rr, models.ErrUserDoesNotHaveAccessToProject{ProjectID: vcls.project.ID}
|
||||
}
|
||||
err = vcls.list.ReadOne(s, vcls.user)
|
||||
err = vcls.project.ReadOne(s, vcls.user)
|
||||
if err != nil {
|
||||
_ = s.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
listTasks := vcls.list.Tasks
|
||||
if listTasks == nil {
|
||||
projectTasks := vcls.project.Tasks
|
||||
if projectTasks == nil {
|
||||
tk := models.TaskCollection{
|
||||
ListID: vcls.list.ID,
|
||||
ProjectID: vcls.project.ID,
|
||||
}
|
||||
iface, _, _, err := tk.ReadAll(s, vcls.user, "", 1, 1000)
|
||||
if err != nil {
|
||||
@ -546,18 +546,18 @@ func (vcls *VikunjaCaldavListStorage) getListRessource(isCollection bool) (rr Vi
|
||||
}
|
||||
|
||||
for _, t := range tasks {
|
||||
listTasks = append(listTasks, &models.TaskWithComments{Task: *t})
|
||||
projectTasks = append(projectTasks, &models.TaskWithComments{Task: *t})
|
||||
}
|
||||
vcls.list.Tasks = listTasks
|
||||
vcls.project.Tasks = projectTasks
|
||||
}
|
||||
|
||||
if err := s.Commit(); err != nil {
|
||||
return rr, err
|
||||
}
|
||||
|
||||
rr = VikunjaListResourceAdapter{
|
||||
list: vcls.list,
|
||||
listTasks: listTasks,
|
||||
rr = VikunjaProjectResourceAdapter{
|
||||
project: vcls.project,
|
||||
projectTasks: projectTasks,
|
||||
isCollection: isCollection,
|
||||
}
|
||||
|
||||
|
@ -44,8 +44,8 @@ func setupMetrics(a *echo.Group) {
|
||||
|
||||
for _, c := range []countable{
|
||||
{
|
||||
metrics.ListCountKey,
|
||||
models.List{},
|
||||
metrics.ProjectCountKey,
|
||||
models.Project{},
|
||||
},
|
||||
{
|
||||
metrics.UserCountKey,
|
||||
|
@ -15,14 +15,14 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// @title Vikunja API
|
||||
// @description This is the documentation for the [Vikunja](http://vikunja.io) API. Vikunja is a cross-plattform To-do-application with a lot of features, such as sharing lists with users or teams. <!-- ReDoc-Inject: <security-definitions> -->
|
||||
// @description This is the documentation for the [Vikunja](http://vikunja.io) API. Vikunja is a cross-plattform To-do-application with a lot of features, such as sharing projects with users or teams. <!-- ReDoc-Inject: <security-definitions> -->
|
||||
|
||||
// @description # Pagination
|
||||
// @description Every endpoint capable of pagination will return two headers:
|
||||
// @description * `x-pagination-total-pages`: The total number of available pages for this request
|
||||
// @description * `x-pagination-result-count`: The number of items returned for this request.
|
||||
// @description # Rights
|
||||
// @description All endpoints which return a single item (list, task, namespace, etc.) - no array - will also return a `x-max-right` header with the max right the user has on this item as an int where `0` is `Read Only`, `1` is `Read & Write` and `2` is `Admin`.
|
||||
// @description All endpoints which return a single item (project, task, namespace, etc.) - no array - will also return a `x-max-right` header with the max right the user has on this item as an int where `0` is `Read Only`, `1` is `Read & Write` and `2` is `Admin`.
|
||||
// @description This can be used to show or hide ui elements based on the rights the user has.
|
||||
// @description # Authorization
|
||||
// @description **JWT-Auth:** Main authorization method, used for most of the requests. Needs `Authorization: Bearer <jwt-token>`-header to authenticate successfully.
|
||||
@ -47,6 +47,7 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/modules/migration/wunderlist"
|
||||
"errors"
|
||||
"net/url"
|
||||
"strings"
|
||||
@ -287,7 +288,7 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
|
||||
u.GET("", apiv1.UserShow)
|
||||
u.POST("/password", apiv1.UserChangePassword)
|
||||
u.GET("s", apiv1.UserList)
|
||||
u.GET("s", apiv1.UserProject)
|
||||
u.POST("/token", apiv1.RenewToken)
|
||||
u.POST("/settings/email", apiv1.UpdateUserEmail)
|
||||
u.GET("/settings/avatar", apiv1.GetUserAvatarProvider)
|
||||
@ -316,28 +317,28 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
u.POST("/deletion/cancel", apiv1.UserCancelDeletion)
|
||||
}
|
||||
|
||||
listHandler := &handler.WebHandler{
|
||||
projectHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.List{}
|
||||
return &models.Project{}
|
||||
},
|
||||
}
|
||||
a.GET("/lists", listHandler.ReadAllWeb)
|
||||
a.GET("/lists/:list", listHandler.ReadOneWeb)
|
||||
a.POST("/lists/:list", listHandler.UpdateWeb)
|
||||
a.DELETE("/lists/:list", listHandler.DeleteWeb)
|
||||
a.PUT("/namespaces/:namespace/lists", listHandler.CreateWeb)
|
||||
a.GET("/lists/:list/listusers", apiv1.ListUsersForList)
|
||||
a.GET("/projects", projectHandler.ReadAllWeb)
|
||||
a.GET("/projects/:project", projectHandler.ReadOneWeb)
|
||||
a.POST("/projects/:project", projectHandler.UpdateWeb)
|
||||
a.DELETE("/projects/:project", projectHandler.DeleteWeb)
|
||||
a.PUT("/namespaces/:namespace/projects", projectHandler.CreateWeb)
|
||||
a.GET("/projects/:project/projectusers", apiv1.ProjectUsersForProject)
|
||||
|
||||
if config.ServiceEnableLinkSharing.GetBool() {
|
||||
listSharingHandler := &handler.WebHandler{
|
||||
projectSharingHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.LinkSharing{}
|
||||
},
|
||||
}
|
||||
a.PUT("/lists/:list/shares", listSharingHandler.CreateWeb)
|
||||
a.GET("/lists/:list/shares", listSharingHandler.ReadAllWeb)
|
||||
a.GET("/lists/:list/shares/:share", listSharingHandler.ReadOneWeb)
|
||||
a.DELETE("/lists/:list/shares/:share", listSharingHandler.DeleteWeb)
|
||||
a.PUT("/projects/:project/shares", projectSharingHandler.CreateWeb)
|
||||
a.GET("/projects/:project/shares", projectSharingHandler.ReadAllWeb)
|
||||
a.GET("/projects/:project/shares/:share", projectSharingHandler.ReadOneWeb)
|
||||
a.DELETE("/projects/:project/shares/:share", projectSharingHandler.DeleteWeb)
|
||||
}
|
||||
|
||||
taskCollectionHandler := &handler.WebHandler{
|
||||
@ -345,35 +346,35 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
return &models.TaskCollection{}
|
||||
},
|
||||
}
|
||||
a.GET("/lists/:list/tasks", taskCollectionHandler.ReadAllWeb)
|
||||
a.GET("/projects/:project/tasks", taskCollectionHandler.ReadAllWeb)
|
||||
|
||||
kanbanBucketHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.Bucket{}
|
||||
},
|
||||
}
|
||||
a.GET("/lists/:list/buckets", kanbanBucketHandler.ReadAllWeb)
|
||||
a.PUT("/lists/:list/buckets", kanbanBucketHandler.CreateWeb)
|
||||
a.POST("/lists/:list/buckets/:bucket", kanbanBucketHandler.UpdateWeb)
|
||||
a.DELETE("/lists/:list/buckets/:bucket", kanbanBucketHandler.DeleteWeb)
|
||||
a.GET("/projects/:project/buckets", kanbanBucketHandler.ReadAllWeb)
|
||||
a.PUT("/projects/:project/buckets", kanbanBucketHandler.CreateWeb)
|
||||
a.POST("/projects/:project/buckets/:bucket", kanbanBucketHandler.UpdateWeb)
|
||||
a.DELETE("/projects/:project/buckets/:bucket", kanbanBucketHandler.DeleteWeb)
|
||||
|
||||
listDuplicateHandler := &handler.WebHandler{
|
||||
projectDuplicateHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.ListDuplicate{}
|
||||
return &models.ProjectDuplicate{}
|
||||
},
|
||||
}
|
||||
a.PUT("/lists/:listid/duplicate", listDuplicateHandler.CreateWeb)
|
||||
a.PUT("/projects/:projectid/duplicate", projectDuplicateHandler.CreateWeb)
|
||||
|
||||
taskHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.Task{}
|
||||
},
|
||||
}
|
||||
a.PUT("/lists/:list", taskHandler.CreateWeb)
|
||||
a.GET("/tasks/:listtask", taskHandler.ReadOneWeb)
|
||||
a.PUT("/projects/:project", taskHandler.CreateWeb)
|
||||
a.GET("/tasks/:projecttask", taskHandler.ReadOneWeb)
|
||||
a.GET("/tasks/all", taskCollectionHandler.ReadAllWeb)
|
||||
a.DELETE("/tasks/:listtask", taskHandler.DeleteWeb)
|
||||
a.POST("/tasks/:listtask", taskHandler.UpdateWeb)
|
||||
a.DELETE("/tasks/:projecttask", taskHandler.DeleteWeb)
|
||||
a.POST("/tasks/:projecttask", taskHandler.UpdateWeb)
|
||||
|
||||
bulkTaskHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
@ -387,32 +388,32 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
return &models.TaskAssginee{}
|
||||
},
|
||||
}
|
||||
a.PUT("/tasks/:listtask/assignees", assigneeTaskHandler.CreateWeb)
|
||||
a.DELETE("/tasks/:listtask/assignees/:user", assigneeTaskHandler.DeleteWeb)
|
||||
a.GET("/tasks/:listtask/assignees", assigneeTaskHandler.ReadAllWeb)
|
||||
a.PUT("/tasks/:projecttask/assignees", assigneeTaskHandler.CreateWeb)
|
||||
a.DELETE("/tasks/:projecttask/assignees/:user", assigneeTaskHandler.DeleteWeb)
|
||||
a.GET("/tasks/:projecttask/assignees", assigneeTaskHandler.ReadAllWeb)
|
||||
|
||||
bulkAssigneeHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.BulkAssignees{}
|
||||
},
|
||||
}
|
||||
a.POST("/tasks/:listtask/assignees/bulk", bulkAssigneeHandler.CreateWeb)
|
||||
a.POST("/tasks/:projecttask/assignees/bulk", bulkAssigneeHandler.CreateWeb)
|
||||
|
||||
labelTaskHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.LabelTask{}
|
||||
},
|
||||
}
|
||||
a.PUT("/tasks/:listtask/labels", labelTaskHandler.CreateWeb)
|
||||
a.DELETE("/tasks/:listtask/labels/:label", labelTaskHandler.DeleteWeb)
|
||||
a.GET("/tasks/:listtask/labels", labelTaskHandler.ReadAllWeb)
|
||||
a.PUT("/tasks/:projecttask/labels", labelTaskHandler.CreateWeb)
|
||||
a.DELETE("/tasks/:projecttask/labels/:label", labelTaskHandler.DeleteWeb)
|
||||
a.GET("/tasks/:projecttask/labels", labelTaskHandler.ReadAllWeb)
|
||||
|
||||
bulkLabelTaskHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.LabelTaskBulk{}
|
||||
},
|
||||
}
|
||||
a.POST("/tasks/:listtask/labels/bulk", bulkLabelTaskHandler.CreateWeb)
|
||||
a.POST("/tasks/:projecttask/labels/bulk", bulkLabelTaskHandler.CreateWeb)
|
||||
|
||||
taskRelationHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
@ -458,25 +459,25 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
a.DELETE("/labels/:label", labelHandler.DeleteWeb)
|
||||
a.POST("/labels/:label", labelHandler.UpdateWeb)
|
||||
|
||||
listTeamHandler := &handler.WebHandler{
|
||||
projectTeamHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.TeamList{}
|
||||
return &models.TeamProject{}
|
||||
},
|
||||
}
|
||||
a.GET("/lists/:list/teams", listTeamHandler.ReadAllWeb)
|
||||
a.PUT("/lists/:list/teams", listTeamHandler.CreateWeb)
|
||||
a.DELETE("/lists/:list/teams/:team", listTeamHandler.DeleteWeb)
|
||||
a.POST("/lists/:list/teams/:team", listTeamHandler.UpdateWeb)
|
||||
a.GET("/projects/:project/teams", projectTeamHandler.ReadAllWeb)
|
||||
a.PUT("/projects/:project/teams", projectTeamHandler.CreateWeb)
|
||||
a.DELETE("/projects/:project/teams/:team", projectTeamHandler.DeleteWeb)
|
||||
a.POST("/projects/:project/teams/:team", projectTeamHandler.UpdateWeb)
|
||||
|
||||
listUserHandler := &handler.WebHandler{
|
||||
projectUserHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
return &models.ListUser{}
|
||||
return &models.ProjectUser{}
|
||||
},
|
||||
}
|
||||
a.GET("/lists/:list/users", listUserHandler.ReadAllWeb)
|
||||
a.PUT("/lists/:list/users", listUserHandler.CreateWeb)
|
||||
a.DELETE("/lists/:list/users/:user", listUserHandler.DeleteWeb)
|
||||
a.POST("/lists/:list/users/:user", listUserHandler.UpdateWeb)
|
||||
a.GET("/projects/:project/users", projectUserHandler.ReadAllWeb)
|
||||
a.PUT("/projects/:project/users", projectUserHandler.CreateWeb)
|
||||
a.DELETE("/projects/:project/users/:user", projectUserHandler.DeleteWeb)
|
||||
a.POST("/projects/:project/users/:user", projectUserHandler.UpdateWeb)
|
||||
|
||||
savedFiltersHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
@ -498,7 +499,7 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
a.GET("/namespaces/:namespace", namespaceHandler.ReadOneWeb)
|
||||
a.POST("/namespaces/:namespace", namespaceHandler.UpdateWeb)
|
||||
a.DELETE("/namespaces/:namespace", namespaceHandler.DeleteWeb)
|
||||
a.GET("/namespaces/:namespace/lists", apiv1.GetListsByNamespaceID)
|
||||
a.GET("/namespaces/:namespace/projects", apiv1.GetProjectsByNamespaceID)
|
||||
|
||||
namespaceTeamHandler := &handler.WebHandler{
|
||||
EmptyStruct: func() handler.CObject {
|
||||
@ -562,17 +563,17 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
m := a.Group("/migration")
|
||||
registerMigrations(m)
|
||||
|
||||
// List Backgrounds
|
||||
// Project Backgrounds
|
||||
if config.BackgroundsEnabled.GetBool() {
|
||||
a.GET("/lists/:list/background", backgroundHandler.GetListBackground)
|
||||
a.DELETE("/lists/:list/background", backgroundHandler.RemoveListBackground)
|
||||
a.GET("/projects/:project/background", backgroundHandler.GetProjectBackground)
|
||||
a.DELETE("/projects/:project/background", backgroundHandler.RemoveProjectBackground)
|
||||
if config.BackgroundsUploadEnabled.GetBool() {
|
||||
uploadBackgroundProvider := &backgroundHandler.BackgroundProvider{
|
||||
Provider: func() background.Provider {
|
||||
return &upload.Provider{}
|
||||
},
|
||||
}
|
||||
a.PUT("/lists/:list/backgrounds/upload", uploadBackgroundProvider.UploadBackground)
|
||||
a.PUT("/projects/:project/backgrounds/upload", uploadBackgroundProvider.UploadBackground)
|
||||
}
|
||||
if config.BackgroundsUnsplashEnabled.GetBool() {
|
||||
unsplashBackgroundProvider := &backgroundHandler.BackgroundProvider{
|
||||
@ -581,7 +582,7 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
},
|
||||
}
|
||||
a.GET("/backgrounds/unsplash/search", unsplashBackgroundProvider.SearchBackgrounds)
|
||||
a.POST("/lists/:list/backgrounds/unsplash", unsplashBackgroundProvider.SetBackground)
|
||||
a.POST("/projects/:project/backgrounds/unsplash", unsplashBackgroundProvider.SetBackground)
|
||||
a.GET("/backgrounds/unsplash/images/:image/thumb", unsplash.ProxyUnsplashThumb)
|
||||
a.GET("/backgrounds/unsplash/images/:image", unsplash.ProxyUnsplashImage)
|
||||
}
|
||||
@ -641,13 +642,13 @@ func registerCalDavRoutes(c *echo.Group) {
|
||||
// Basic auth middleware
|
||||
c.Use(middleware.BasicAuth(caldav.BasicAuth))
|
||||
|
||||
// THIS is the entry point for caldav clients, otherwise lists will show up double
|
||||
// THIS is the entry point for caldav clients, otherwise projects will show up double
|
||||
c.Any("", caldav.EntryHandler)
|
||||
c.Any("/", caldav.EntryHandler)
|
||||
c.Any("/principals/*/", caldav.PrincipalHandler)
|
||||
c.Any("/lists", caldav.ListHandler)
|
||||
c.Any("/lists/", caldav.ListHandler)
|
||||
c.Any("/lists/:list", caldav.ListHandler)
|
||||
c.Any("/lists/:list/", caldav.ListHandler)
|
||||
c.Any("/lists/:list/:task", caldav.TaskHandler) // Mostly used for editing
|
||||
c.Any("/projects", caldav.ProjectHandler)
|
||||
c.Any("/projects/", caldav.ProjectHandler)
|
||||
c.Any("/projects/:project", caldav.ProjectHandler)
|
||||
c.Any("/projects/:project/", caldav.ProjectHandler)
|
||||
c.Any("/projects/:project/:task", caldav.TaskHandler) // Mostly used for editing
|
||||
}
|
||||
|
Reference in New Issue
Block a user