diff --git a/cmd/crm/main.go b/cmd/crm/main.go index 5cd88f287..c50f0313e 100644 --- a/cmd/crm/main.go +++ b/cmd/crm/main.go @@ -10,7 +10,7 @@ import ( "github.com/go-chi/chi" - project "github.com/crusttech/crust/crm" + "github.com/crusttech/crust/crm/rest" "github.com/titpetric/factory" ) @@ -51,6 +51,6 @@ func main() { // mount routes r := chi.NewRouter() - MountRoutes(r, routeOptions, project.MountRoutes) + MountRoutes(r, routeOptions, rest.MountRoutes) http.Serve(listener, r) } diff --git a/cmd/sam/main.go b/cmd/sam/main.go index 2c6950578..06ea71814 100644 --- a/cmd/sam/main.go +++ b/cmd/sam/main.go @@ -11,7 +11,7 @@ import ( "github.com/go-chi/chi" _ "github.com/joho/godotenv/autoload" - project "github.com/crusttech/crust/sam" + "github.com/crusttech/crust/sam/rest" "github.com/titpetric/factory" ) @@ -72,6 +72,6 @@ func main() { // mount routes r := chi.NewRouter() - MountRoutes(r, routeOptions, project.MountRoutes) + MountRoutes(r, routeOptions, rest.MountRoutes) http.Serve(listener, r) } diff --git a/codegen/codegen.php b/codegen/codegen.php index 026f20c3d..b33e1754f 100755 --- a/codegen/codegen.php +++ b/codegen/codegen.php @@ -70,7 +70,7 @@ foreach ($generators as $generator) { if (!is_dir($dirname) && !empty($dirname)) { mkdir($dirname, 0777, true); } - $common = compact("parsers"); + $common = compact("parsers", "project"); include($generator); } diff --git a/codegen/crm/index.php b/codegen/crm/index.php deleted file mode 100644 index 2da0ce18a..000000000 --- a/codegen/crm/index.php +++ /dev/null @@ -1,56 +0,0 @@ -load("http_routes.tpl"); -$tpl->assign($common); -$tpl->assign("package", basename($dirname)); -$tpl->assign("name", $name); -$tpl->assign("api", $api); -$tpl->assign("apis", $apis); -$tpl->assign("self", strtolower(substr($name, 0, 1))); -$tpl->assign("structs", $api['struct']); -$imports = array(); -foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } -} -$tpl->assign("imports", $imports); -$tpl->assign("calls", $api['apis']); -$contents = str_replace("\n\n}", "\n}", $tpl->get()); - -file_put_contents($filename, $contents); -echo $filename . "\n"; - -foreach ($apis as $api) { - if (is_array($api['struct'])) { - $name = ucfirst($api['interface']); - $filename = $dirname . "/" . str_replace("..", ".", strtolower($name) . ".go"); - - $tpl->load("http_.tpl"); - $tpl->assign($common); - $tpl->assign("package", basename(__DIR__)); - $tpl->assign("name", $name); - $tpl->assign("api", $api); - $tpl->assign("self", strtolower(substr($name, 0, 1))); - $tpl->assign("structs", $api['struct']); - $imports = array(); - foreach ($api['struct'] as $struct) { - if (isset($struct['imports'])) - foreach ($struct['imports'] as $import) { - $imports[] = $import; - } - } - $tpl->assign("imports", $imports); - $tpl->assign("calls", $api['apis']); - $contents = str_replace("\n\n}", "\n}", $tpl->get()); - - if (!file_exists($filename)) { - file_put_contents($filename, $contents); - echo $filename . "\n"; - } - } -} diff --git a/codegen/crm/rest/index.php b/codegen/crm/rest/index.php index 5401d36c6..1b8c37457 100644 --- a/codegen/crm/rest/index.php +++ b/codegen/crm/rest/index.php @@ -1,24 +1,36 @@ function($name, $api) { - return strtolower($name) . ".go"; - }, - "http_request.tpl" => function($name, $api) { - return strtolower($name) . "_requests.go"; - }, - "http_handlers.tpl" => function($name, $api) { - return strtolower($name) . "_handlers.go"; - } -); +$name = ucfirst($api['interface']); +$filename = $dirname . "/router.go"; + +$tpl->load("http_routes.tpl"); +$tpl->assign($common); +$tpl->assign("package", basename($dirname)); +$tpl->assign("name", $name); +$tpl->assign("api", $api); +$tpl->assign("apis", $apis); +$tpl->assign("self", strtolower(substr($name, 0, 1))); +$tpl->assign("structs", $api['struct']); +$imports = array(); +foreach ($api['struct'] as $struct) { + if (isset($struct['imports'])) + foreach ($struct['imports'] as $import) { + $imports[] = $import; + } +} +$tpl->assign("imports", $imports); +$tpl->assign("calls", $api['apis']); +$contents = str_replace("\n\n}", "\n}", $tpl->get()); + +file_put_contents($filename, $contents); +echo $filename . "\n"; -foreach ($templates as $template => $fn) foreach ($apis as $api) { if (is_array($api['struct'])) { $name = ucfirst($api['interface']); - $filename = $dirname . "/" . $fn($name, $api); + $filename = $dirname . "/" . str_replace("..", ".", strtolower($name) . ".go"); - $tpl->load($template); + $tpl->load("http_.tpl"); $tpl->assign($common); $tpl->assign("package", basename(__DIR__)); $tpl->assign("name", $name); @@ -36,7 +48,9 @@ foreach ($apis as $api) { $tpl->assign("calls", $api['apis']); $contents = str_replace("\n\n}", "\n}", $tpl->get()); - file_put_contents($filename, $contents); - echo $filename . "\n"; + if (!file_exists($filename)) { + file_put_contents($filename, $contents); + echo $filename . "\n"; + } } } diff --git a/codegen/crm/rest/server/index.php b/codegen/crm/rest/server/index.php new file mode 100644 index 000000000..5401d36c6 --- /dev/null +++ b/codegen/crm/rest/server/index.php @@ -0,0 +1,42 @@ + function($name, $api) { + return strtolower($name) . ".go"; + }, + "http_request.tpl" => function($name, $api) { + return strtolower($name) . "_requests.go"; + }, + "http_handlers.tpl" => function($name, $api) { + return strtolower($name) . "_handlers.go"; + } +); + +foreach ($templates as $template => $fn) +foreach ($apis as $api) { + if (is_array($api['struct'])) { + $name = ucfirst($api['interface']); + $filename = $dirname . "/" . $fn($name, $api); + + $tpl->load($template); + $tpl->assign($common); + $tpl->assign("package", basename(__DIR__)); + $tpl->assign("name", $name); + $tpl->assign("api", $api); + $tpl->assign("self", strtolower(substr($name, 0, 1))); + $tpl->assign("structs", $api['struct']); + $imports = array(); + foreach ($api['struct'] as $struct) { + if (isset($struct['imports'])) + foreach ($struct['imports'] as $import) { + $imports[] = $import; + } + } + $tpl->assign("imports", $imports); + $tpl->assign("calls", $api['apis']); + $contents = str_replace("\n\n}", "\n}", $tpl->get()); + + file_put_contents($filename, $contents); + echo $filename . "\n"; + } +} diff --git a/codegen/templates/http_routes.tpl b/codegen/templates/http_routes.tpl index d2599a41a..3f3d2839c 100644 --- a/codegen/templates/http_routes.tpl +++ b/codegen/templates/http_routes.tpl @@ -8,12 +8,12 @@ import ( "reflect" "github.com/go-chi/chi" - "github.com/crusttech/crust/{package}/rest" + "github.com/crusttech/crust/{project}/rest/server" ) func MountRoutes(r chi.Router) { {foreach $apis as $api} - {api.interface|strtolower} := &rest.{api.interface|capitalize}Handlers{{api.interface|capitalize}{ldelim}{rdelim}.New()} + {api.interface|strtolower} := &server.{api.interface|capitalize}Handlers{{api.interface|capitalize}{ldelim}{rdelim}.New()} {/foreach} {foreach $apis as $api} r.Group(func (r chi.Router) { diff --git a/crm/field.go b/crm/field.go deleted file mode 100644 index 786e0c21c..000000000 --- a/crm/field.go +++ /dev/null @@ -1,33 +0,0 @@ -package crm - -import ( - "github.com/pkg/errors" - - "github.com/crusttech/crust/crm/rest" - "github.com/crusttech/crust/crm/service" -) - -var _ = errors.Wrap - -type ( - Field struct { - service FieldInterface - } - - FieldInterface interface { - List() (interface{}, error) - Type(id string) (interface{}, error) - } -) - -func (Field) New() *Field { - return &Field{service.Field{}.New()} -} - -func (self *Field) List(_ *rest.FieldListRequest) (interface{}, error) { - return self.service.List() -} - -func (self *Field) Type(r *rest.FieldTypeRequest) (interface{}, error) { - return self.service.Type(r.ID) -} diff --git a/crm/module.go b/crm/module.go deleted file mode 100644 index e41d2fac6..000000000 --- a/crm/module.go +++ /dev/null @@ -1,72 +0,0 @@ -package crm - -import ( - "github.com/pkg/errors" - "github.com/titpetric/factory" - - "github.com/crusttech/crust/crm/rest" - "github.com/crusttech/crust/crm/types" -) - -var _ = errors.Wrap - -type Module struct{} - -func (Module) New() *Module { - return &Module{} -} - -func (*Module) List(r *rest.ModuleListRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - if r.ID > 0 { - m := types.Module{}.New() - return m, db.Get(m, "select * from crm_module id=?", r.ID) - } - - res := make([]Module, 0) - err = db.Select(&res, "select * from crm_module order by name asc") - return res, err -} - -func (*Module) Edit(r *rest.ModuleEditRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - m := types.Module{}.New() - m.SetID(r.ID).SetName(r.Name) - if m.GetID() > 0 { - return m, db.Replace("crm_module", m) - } - m.SetID(factory.Sonyflake.NextID()) - return m, db.Insert("crm_module", m) -} - -func (*Module) ContentList(r *rest.ModuleContentListRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - if r.ID > 0 { - m := types.ModuleContentRow{}.New() - return m, db.Get(m, "select * from crm_module id=?", r.ID) - } - - res := make([]types.ModuleContentRow, 0) - err = db.Select(&res, "select * from crm_module order by name asc") - return res, err -} - -func (*Module) ContentEdit(r *rest.ModuleContentEditRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Module.content/edit") -} - -func (*Module) ContentDelete(r *rest.ModuleContentDeleteRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Module.content/delete") -} diff --git a/crm/rest_auth.go b/crm/rest/auth.go similarity index 96% rename from crm/rest_auth.go rename to crm/rest/auth.go index 5b9e36bb4..ca1985c58 100644 --- a/crm/rest_auth.go +++ b/crm/rest/auth.go @@ -1,4 +1,4 @@ -package crm +package rest import ( "net/http" diff --git a/crm/rest/field.go b/crm/rest/field.go index ebca9ad35..98f0c0af1 100644 --- a/crm/rest/field.go +++ b/crm/rest/field.go @@ -1,40 +1,33 @@ package rest -/* - Hello! This file is auto-generated from `docs/src/spec.json`. - - For development: - In order to update the generated files, edit this file under the location, - add your struct fields, imports, API definitions and whatever you want, and: - - 1. run [spec](https://github.com/titpetric/spec) in the same folder, - 2. run `./_gen.php` in this folder. - - You may edit `field.go`, `field.util.go` or `field_test.go` to - implement your API calls, helper functions and tests. The file `field.go` - is only generated the first time, and will not be overwritten if it exists. -*/ - import ( - "net/http" + "github.com/pkg/errors" + + "github.com/crusttech/crust/crm/rest/server" + "github.com/crusttech/crust/crm/service" ) -// HTTP handlers are a superset of internal APIs -type FieldHandlers struct { - Field FieldAPI +var _ = errors.Wrap + +type ( + Field struct { + service FieldInterface + } + + FieldInterface interface { + List() (interface{}, error) + Type(id string) (interface{}, error) + } +) + +func (Field) New() *Field { + return &Field{service.Field{}.New()} } -// Internal API interface -type FieldAPI interface { - List(*FieldListRequest) (interface{}, error) - Type(*FieldTypeRequest) (interface{}, error) - - // Authenticate API requests - Authenticator() func(http.Handler) http.Handler +func (self *Field) List(_ *server.FieldListRequest) (interface{}, error) { + return self.service.List() } -// HTTP API interface -type FieldHandlersAPI interface { - List(http.ResponseWriter, *http.Request) - Type(http.ResponseWriter, *http.Request) +func (self *Field) Type(r *server.FieldTypeRequest) (interface{}, error) { + return self.service.Type(r.ID) } diff --git a/crm/rest/module.go b/crm/rest/module.go index fd2ff770c..001b65a42 100644 --- a/crm/rest/module.go +++ b/crm/rest/module.go @@ -1,46 +1,72 @@ package rest -/* - Hello! This file is auto-generated from `docs/src/spec.json`. - - For development: - In order to update the generated files, edit this file under the location, - add your struct fields, imports, API definitions and whatever you want, and: - - 1. run [spec](https://github.com/titpetric/spec) in the same folder, - 2. run `./_gen.php` in this folder. - - You may edit `module.go`, `module.util.go` or `module_test.go` to - implement your API calls, helper functions and tests. The file `module.go` - is only generated the first time, and will not be overwritten if it exists. -*/ - import ( - "net/http" + "github.com/pkg/errors" + "github.com/titpetric/factory" + + "github.com/crusttech/crust/crm/rest/server" + "github.com/crusttech/crust/crm/types" ) -// HTTP handlers are a superset of internal APIs -type ModuleHandlers struct { - Module ModuleAPI +var _ = errors.Wrap + +type Module struct{} + +func (Module) New() *Module { + return &Module{} } -// Internal API interface -type ModuleAPI interface { - List(*ModuleListRequest) (interface{}, error) - Edit(*ModuleEditRequest) (interface{}, error) - ContentList(*ModuleContentListRequest) (interface{}, error) - ContentEdit(*ModuleContentEditRequest) (interface{}, error) - ContentDelete(*ModuleContentDeleteRequest) (interface{}, error) +func (*Module) List(r *server.ModuleListRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } - // Authenticate API requests - Authenticator() func(http.Handler) http.Handler + if r.ID > 0 { + m := types.Module{}.New() + return m, db.Get(m, "select * from crm_module id=?", r.ID) + } + + res := make([]Module, 0) + err = db.Select(&res, "select * from crm_module order by name asc") + return res, err } -// HTTP API interface -type ModuleHandlersAPI interface { - List(http.ResponseWriter, *http.Request) - Edit(http.ResponseWriter, *http.Request) - ContentList(http.ResponseWriter, *http.Request) - ContentEdit(http.ResponseWriter, *http.Request) - ContentDelete(http.ResponseWriter, *http.Request) +func (*Module) Edit(r *server.ModuleEditRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + m := types.Module{}.New() + m.SetID(r.ID).SetName(r.Name) + if m.GetID() > 0 { + return m, db.Replace("crm_module", m) + } + m.SetID(factory.Sonyflake.NextID()) + return m, db.Insert("crm_module", m) +} + +func (*Module) ContentList(r *server.ModuleContentListRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + if r.ID > 0 { + m := types.ModuleContentRow{}.New() + return m, db.Get(m, "select * from crm_module id=?", r.ID) + } + + res := make([]types.ModuleContentRow, 0) + err = db.Select(&res, "select * from crm_module order by name asc") + return res, err +} + +func (*Module) ContentEdit(r *server.ModuleContentEditRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Module.content/edit") +} + +func (*Module) ContentDelete(r *server.ModuleContentDeleteRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Module.content/delete") } diff --git a/crm/rest_router.go b/crm/rest/router.go similarity index 92% rename from crm/rest_router.go rename to crm/rest/router.go index 780a78f9c..9bcbc68e8 100644 --- a/crm/rest_router.go +++ b/crm/rest/router.go @@ -1,4 +1,4 @@ -package crm +package rest /* Hello! This file is auto-generated from `docs/src/spec.json`. @@ -21,12 +21,12 @@ import ( "reflect" "runtime" - "github.com/crusttech/crust/crm/rest" + "github.com/crusttech/crust/crm/rest/server" ) func MountRoutes(r chi.Router) { - field := &rest.FieldHandlers{Field{}.New()} - module := &rest.ModuleHandlers{Module{}.New()} + field := &server.FieldHandlers{Field{}.New()} + module := &server.ModuleHandlers{Module{}.New()} r.Group(func(r chi.Router) { r.Use(field.Field.Authenticator()) r.Route("/field", func(r chi.Router) { diff --git a/crm/rest/server/field.go b/crm/rest/server/field.go new file mode 100644 index 000000000..8f0960f90 --- /dev/null +++ b/crm/rest/server/field.go @@ -0,0 +1,40 @@ +package server + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `field.go`, `field.util.go` or `field_test.go` to + implement your API calls, helper functions and tests. The file `field.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "net/http" +) + +// HTTP handlers are a superset of internal APIs +type FieldHandlers struct { + Field FieldAPI +} + +// Internal API interface +type FieldAPI interface { + List(*FieldListRequest) (interface{}, error) + Type(*FieldTypeRequest) (interface{}, error) + + // Authenticate API requests + Authenticator() func(http.Handler) http.Handler +} + +// HTTP API interface +type FieldHandlersAPI interface { + List(http.ResponseWriter, *http.Request) + Type(http.ResponseWriter, *http.Request) +} diff --git a/crm/rest/field_handlers.go b/crm/rest/server/field_handlers.go similarity index 98% rename from crm/rest/field_handlers.go rename to crm/rest/server/field_handlers.go index 5e48fceb4..5f5da038c 100644 --- a/crm/rest/field_handlers.go +++ b/crm/rest/server/field_handlers.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/crm/rest/field_requests.go b/crm/rest/server/field_requests.go similarity index 99% rename from crm/rest/field_requests.go rename to crm/rest/server/field_requests.go index bfaddebd3..662d189b2 100644 --- a/crm/rest/field_requests.go +++ b/crm/rest/server/field_requests.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/misc.go b/crm/rest/server/misc.go similarity index 90% rename from sam/rest/misc.go rename to crm/rest/server/misc.go index 8745731b6..8d0a991a9 100644 --- a/sam/rest/misc.go +++ b/crm/rest/server/misc.go @@ -1,4 +1,4 @@ -package rest +package server import ( "net/http" diff --git a/crm/rest/server/module.go b/crm/rest/server/module.go new file mode 100644 index 000000000..dd652a265 --- /dev/null +++ b/crm/rest/server/module.go @@ -0,0 +1,46 @@ +package server + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `module.go`, `module.util.go` or `module_test.go` to + implement your API calls, helper functions and tests. The file `module.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "net/http" +) + +// HTTP handlers are a superset of internal APIs +type ModuleHandlers struct { + Module ModuleAPI +} + +// Internal API interface +type ModuleAPI interface { + List(*ModuleListRequest) (interface{}, error) + Edit(*ModuleEditRequest) (interface{}, error) + ContentList(*ModuleContentListRequest) (interface{}, error) + ContentEdit(*ModuleContentEditRequest) (interface{}, error) + ContentDelete(*ModuleContentDeleteRequest) (interface{}, error) + + // Authenticate API requests + Authenticator() func(http.Handler) http.Handler +} + +// HTTP API interface +type ModuleHandlersAPI interface { + List(http.ResponseWriter, *http.Request) + Edit(http.ResponseWriter, *http.Request) + ContentList(http.ResponseWriter, *http.Request) + ContentEdit(http.ResponseWriter, *http.Request) + ContentDelete(http.ResponseWriter, *http.Request) +} diff --git a/crm/rest/module_handlers.go b/crm/rest/server/module_handlers.go similarity index 99% rename from crm/rest/module_handlers.go rename to crm/rest/server/module_handlers.go index 7aa6ede6d..c28286055 100644 --- a/crm/rest/module_handlers.go +++ b/crm/rest/server/module_handlers.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/crm/rest/module_requests.go b/crm/rest/server/module_requests.go similarity index 99% rename from crm/rest/module_requests.go rename to crm/rest/server/module_requests.go index d2dde4b50..dc23729b6 100644 --- a/crm/rest/module_requests.go +++ b/crm/rest/server/module_requests.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/crm/rest/util.go b/crm/rest/server/util.go similarity index 97% rename from crm/rest/util.go rename to crm/rest/server/util.go index 4b64b4986..ad45db86b 100644 --- a/crm/rest/util.go +++ b/crm/rest/server/util.go @@ -1,4 +1,4 @@ -package rest +package server import ( "regexp" diff --git a/sam/rest/util_test.go b/crm/rest/server/util_test.go similarity index 96% rename from sam/rest/util_test.go rename to crm/rest/server/util_test.go index f4824a0cc..5ea194bfa 100644 --- a/sam/rest/util_test.go +++ b/crm/rest/server/util_test.go @@ -1,4 +1,4 @@ -package rest +package server import ( "testing" diff --git a/sam/channel.go b/sam/channel.go deleted file mode 100644 index f3f3fad1f..000000000 --- a/sam/channel.go +++ /dev/null @@ -1,133 +0,0 @@ -package sam - -import ( - "github.com/davecgh/go-spew/spew" - "github.com/pkg/errors" - "github.com/titpetric/factory" - - "github.com/crusttech/crust/sam/rest" - "github.com/crusttech/crust/sam/types" -) - -var _ = errors.Wrap - -const ( - sqlChannelScope = "deleted_at IS NULL AND archived_at IS NULL" - sqlChannelSelect = "SELECT * FROM channels WHERE " + sqlChannelScope -) - -type Channel struct{} - -func (Channel) New() *Channel { - return &Channel{} -} - -func (*Channel) Create(r *rest.ChannelCreateRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: topic message/log entry - // @todo: channel name cmessage/log entry - // @todo: permission check if user can add channel - - c := types.Channel{}. - New(). - SetName(r.Name). - SetTopic(r.Topic). - SetMeta([]byte("{}")). - SetID(factory.Sonyflake.NextID()) - - return c, db.Insert("channels", c) -} - -func (*Channel) Edit(r *rest.ChannelEditRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - /*var c *types.Channel - if c, err = c.load(r.ID); err != nil { - return nil, err - }*/ - - // @todo: topic change message/log entry - // @todo: channel name change message/log entry - // @todo: permission check if user can edit channel - // @todo: make sure archived & deleted entries can not be edited - // @todo: handle channel moving - // @todo: handle channel archiving - - c := types.Channel{}. - New(). - SetName(r.Name). - SetTopic(r.Topic) - - return c, db.Replace("channels", c) - -} - -func (*Channel) Delete(r *rest.ChannelDeleteRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - /*var c *types.Channel - if c, err = c.load(r.ID); err != nil { - return nil, err - }*/ - - // @todo: make history unavailable - // @todo: notify users that channel has been removed (remove from web UI) - // @todo: permissions check if user cah remove channel - - stmt := "UPDATE channels SET deleted_at = NOW() WHERE id = ? AND deleted_at IS NULL" - spew.Dump(r.ID) - return nil, func() error { - _, err := db.Exec(stmt, r.ID) - return err - }() -} - -func (s *Channel) Read(r *rest.ChannelReadRequest) (interface{}, error) { - return s.load(r.ID) -} - -func (*Channel) List(r *rest.ChannelListRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permission check to return only channels that user has access to - // @todo: actual searching not just a full select - - res := make([]types.Channel, 0) - err = db.Select(&res, sqlChannelSelect+" ORDER BY name ASC") - return res, err -} - -func (*Channel) load(id uint64) (*types.Channel, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - c := types.Channel{}.New() - - if id == 0 { - return nil, errors.New("Provide channel ID") - } else if err := db.Get(c, sqlChannelSelect+" AND id = ?", id); err != nil { - return nil, err - } else if c.ID != id { - spew.Dump(c) - return nil, errors.New("Unexisting channel") - } - - // @todo: permission check if user can read channel - - return c, nil -} diff --git a/sam/message.go b/sam/message.go deleted file mode 100644 index f9fa40f29..000000000 --- a/sam/message.go +++ /dev/null @@ -1,44 +0,0 @@ -package sam - -import ( - "github.com/pkg/errors" - - "github.com/crusttech/crust/sam/rest" - _ "github.com/crusttech/crust/sam/types" -) - -type Message struct{} - -func (Message) New() *Message { - return &Message{} -} - -var _ = errors.Wrap - -func (*Message) Edit(r *rest.MessageEditRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Message.edit") -} - -func (*Message) Attach(r *rest.MessageAttachRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Message.attach") -} - -func (*Message) Remove(r *rest.MessageRemoveRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Message.remove") -} - -func (*Message) Read(r *rest.MessageReadRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Message.read") -} - -func (*Message) Search(r *rest.MessageSearchRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Message.search") -} - -func (*Message) Pin(r *rest.MessagePinRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Message.pin") -} - -func (*Message) Flag(r *rest.MessageFlagRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Message.flag") -} diff --git a/sam/organisation.go b/sam/organisation.go deleted file mode 100644 index 63f78527a..000000000 --- a/sam/organisation.go +++ /dev/null @@ -1,110 +0,0 @@ -package sam - -import ( - "fmt" - "github.com/pkg/errors" - "github.com/titpetric/factory" - - "github.com/crusttech/crust/sam/rest" - "github.com/crusttech/crust/sam/types" -) - -var _ = errors.Wrap - -const ( - sqlOrganisationScope = "deleted_at IS NULL AND archived_at IS NULL" - sqlOrganisationSelect = "SELECT * FROM organisations WHERE " + sqlOrganisationScope -) - -type Organisation struct{} - -func (Organisation) New() *Organisation { - return &Organisation{} -} - -func (*Organisation) Create(r *rest.OrganisationCreateRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permission check if user can add/edit organisation - // @todo: make sure archived & deleted entries can not be edited - - o := types.Organisation{}.New().SetName(r.Name).SetID(factory.Sonyflake.NextID()) - return o, db.Insert("organisation", o) -} - -func (*Organisation) Edit(r *rest.OrganisationEditRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permission check if user can add/edit organisation - // @todo: make sure archived & deleted entries can not be edited - - o := types.Organisation{}.New().SetID(r.ID).SetName(r.Name) - return o, db.Replace("organisation", o) -} - -func (*Organisation) Remove(r *rest.OrganisationRemoveRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permission check - // @todo: don't actually delete organisation?! - - stmt := "UPDATE organisationss SET deleted_at = NOW() WHERE deleted_at IS NULL AND id = ?" - - return nil, func() error { - _, err := db.Exec(stmt, r.ID) - return err - }() -} - -func (*Organisation) Read(r *rest.OrganisationReadRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permissions check - - o := types.Organisation{}.New() - return o, db.Get(o, sqlOrganisationSelect+" AND id = ?", r.ID) -} - -func (*Organisation) List(r *rest.OrganisationListRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permissions check - // @todo: actual search for org - - res := make([]Organisation, 0) - err = db.Select(&res, sqlOrganisationSelect+" WHERE label LIKE = ? ORDER BY label ASC", r.Query+"%") - return res, err -} - -func (*Organisation) Archive(r *rest.OrganisationArchiveRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permission check - - stmt := fmt.Sprintf( - "UPDATE organisation SET archived_at = NOW() WHERE %s AND id = ?", - sqlChannelScope) - - return nil, func() error { - _, err := db.Exec(stmt, r.ID) - return err - }() -} diff --git a/sam/rest_auth.go b/sam/rest/auth.go similarity index 98% rename from sam/rest_auth.go rename to sam/rest/auth.go index 1b7bcf0fc..0380e9220 100644 --- a/sam/rest_auth.go +++ b/sam/rest/auth.go @@ -1,4 +1,4 @@ -package sam +package rest import ( "net/http" diff --git a/sam/rest/channel.go b/sam/rest/channel.go index c60e4181f..cbe7822f2 100644 --- a/sam/rest/channel.go +++ b/sam/rest/channel.go @@ -1,46 +1,133 @@ package rest -/* - Hello! This file is auto-generated from `docs/src/spec.json`. - - For development: - In order to update the generated files, edit this file under the location, - add your struct fields, imports, API definitions and whatever you want, and: - - 1. run [spec](https://github.com/titpetric/spec) in the same folder, - 2. run `./_gen.php` in this folder. - - You may edit `channel.go`, `channel.util.go` or `channel_test.go` to - implement your API calls, helper functions and tests. The file `channel.go` - is only generated the first time, and will not be overwritten if it exists. -*/ - import ( - "net/http" + "github.com/davecgh/go-spew/spew" + "github.com/pkg/errors" + "github.com/titpetric/factory" + + "github.com/crusttech/crust/sam/rest/server" + "github.com/crusttech/crust/sam/types" ) -// HTTP handlers are a superset of internal APIs -type ChannelHandlers struct { - Channel ChannelAPI +var _ = errors.Wrap + +const ( + sqlChannelScope = "deleted_at IS NULL AND archived_at IS NULL" + sqlChannelSelect = "SELECT * FROM channels WHERE " + sqlChannelScope +) + +type Channel struct{} + +func (Channel) New() *Channel { + return &Channel{} } -// Internal API interface -type ChannelAPI interface { - List(*ChannelListRequest) (interface{}, error) - Create(*ChannelCreateRequest) (interface{}, error) - Edit(*ChannelEditRequest) (interface{}, error) - Read(*ChannelReadRequest) (interface{}, error) - Delete(*ChannelDeleteRequest) (interface{}, error) +func (*Channel) Create(r *server.ChannelCreateRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } - // Authenticate API requests - Authenticator() func(http.Handler) http.Handler + // @todo: topic message/log entry + // @todo: channel name cmessage/log entry + // @todo: permission check if user can add channel + + c := types.Channel{}. + New(). + SetName(r.Name). + SetTopic(r.Topic). + SetMeta([]byte("{}")). + SetID(factory.Sonyflake.NextID()) + + return c, db.Insert("channels", c) } -// HTTP API interface -type ChannelHandlersAPI interface { - List(http.ResponseWriter, *http.Request) - Create(http.ResponseWriter, *http.Request) - Edit(http.ResponseWriter, *http.Request) - Read(http.ResponseWriter, *http.Request) - Delete(http.ResponseWriter, *http.Request) +func (*Channel) Edit(r *server.ChannelEditRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + /*var c *types.Channel + if c, err = c.load(r.ID); err != nil { + return nil, err + }*/ + + // @todo: topic change message/log entry + // @todo: channel name change message/log entry + // @todo: permission check if user can edit channel + // @todo: make sure archived & deleted entries can not be edited + // @todo: handle channel moving + // @todo: handle channel archiving + + c := types.Channel{}. + New(). + SetName(r.Name). + SetTopic(r.Topic) + + return c, db.Replace("channels", c) + +} + +func (*Channel) Delete(r *server.ChannelDeleteRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + /*var c *types.Channel + if c, err = c.load(r.ID); err != nil { + return nil, err + }*/ + + // @todo: make history unavailable + // @todo: notify users that channel has been removed (remove from web UI) + // @todo: permissions check if user cah remove channel + + stmt := "UPDATE channels SET deleted_at = NOW() WHERE id = ? AND deleted_at IS NULL" + spew.Dump(r.ID) + return nil, func() error { + _, err := db.Exec(stmt, r.ID) + return err + }() +} + +func (s *Channel) Read(r *server.ChannelReadRequest) (interface{}, error) { + return s.load(r.ID) +} + +func (*Channel) List(r *server.ChannelListRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + // @todo: permission check to return only channels that user has access to + // @todo: actual searching not just a full select + + res := make([]types.Channel, 0) + err = db.Select(&res, sqlChannelSelect+" ORDER BY name ASC") + return res, err +} + +func (*Channel) load(id uint64) (*types.Channel, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + c := types.Channel{}.New() + + if id == 0 { + return nil, errors.New("Provide channel ID") + } else if err := db.Get(c, sqlChannelSelect+" AND id = ?", id); err != nil { + return nil, err + } else if c.ID != id { + spew.Dump(c) + return nil, errors.New("Unexisting channel") + } + + // @todo: permission check if user can read channel + + return c, nil } diff --git a/sam/rest/message.go b/sam/rest/message.go index 22ebe84dd..74d572e43 100644 --- a/sam/rest/message.go +++ b/sam/rest/message.go @@ -1,50 +1,44 @@ package rest -/* - Hello! This file is auto-generated from `docs/src/spec.json`. - - For development: - In order to update the generated files, edit this file under the location, - add your struct fields, imports, API definitions and whatever you want, and: - - 1. run [spec](https://github.com/titpetric/spec) in the same folder, - 2. run `./_gen.php` in this folder. - - You may edit `message.go`, `message.util.go` or `message_test.go` to - implement your API calls, helper functions and tests. The file `message.go` - is only generated the first time, and will not be overwritten if it exists. -*/ - import ( - "net/http" + "github.com/pkg/errors" + + "github.com/crusttech/crust/sam/rest/server" + _ "github.com/crusttech/crust/sam/types" ) -// HTTP handlers are a superset of internal APIs -type MessageHandlers struct { - Message MessageAPI +type Message struct{} + +func (Message) New() *Message { + return &Message{} } -// Internal API interface -type MessageAPI interface { - Edit(*MessageEditRequest) (interface{}, error) - Attach(*MessageAttachRequest) (interface{}, error) - Remove(*MessageRemoveRequest) (interface{}, error) - Read(*MessageReadRequest) (interface{}, error) - Search(*MessageSearchRequest) (interface{}, error) - Pin(*MessagePinRequest) (interface{}, error) - Flag(*MessageFlagRequest) (interface{}, error) +var _ = errors.Wrap - // Authenticate API requests - Authenticator() func(http.Handler) http.Handler +func (*Message) Edit(r *server.MessageEditRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Message.edit") } -// HTTP API interface -type MessageHandlersAPI interface { - Edit(http.ResponseWriter, *http.Request) - Attach(http.ResponseWriter, *http.Request) - Remove(http.ResponseWriter, *http.Request) - Read(http.ResponseWriter, *http.Request) - Search(http.ResponseWriter, *http.Request) - Pin(http.ResponseWriter, *http.Request) - Flag(http.ResponseWriter, *http.Request) +func (*Message) Attach(r *server.MessageAttachRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Message.attach") +} + +func (*Message) Remove(r *server.MessageRemoveRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Message.remove") +} + +func (*Message) Read(r *server.MessageReadRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Message.read") +} + +func (*Message) Search(r *server.MessageSearchRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Message.search") +} + +func (*Message) Pin(r *server.MessagePinRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Message.pin") +} + +func (*Message) Flag(r *server.MessageFlagRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Message.flag") } diff --git a/sam/rest/organisation.go b/sam/rest/organisation.go index eedc90e00..53750e2d3 100644 --- a/sam/rest/organisation.go +++ b/sam/rest/organisation.go @@ -1,48 +1,110 @@ package rest -/* - Hello! This file is auto-generated from `docs/src/spec.json`. - - For development: - In order to update the generated files, edit this file under the location, - add your struct fields, imports, API definitions and whatever you want, and: - - 1. run [spec](https://github.com/titpetric/spec) in the same folder, - 2. run `./_gen.php` in this folder. - - You may edit `organisation.go`, `organisation.util.go` or `organisation_test.go` to - implement your API calls, helper functions and tests. The file `organisation.go` - is only generated the first time, and will not be overwritten if it exists. -*/ - import ( - "net/http" + "fmt" + "github.com/pkg/errors" + "github.com/titpetric/factory" + + "github.com/crusttech/crust/sam/rest/server" + "github.com/crusttech/crust/sam/types" ) -// HTTP handlers are a superset of internal APIs -type OrganisationHandlers struct { - Organisation OrganisationAPI +var _ = errors.Wrap + +const ( + sqlOrganisationScope = "deleted_at IS NULL AND archived_at IS NULL" + sqlOrganisationSelect = "SELECT * FROM organisations WHERE " + sqlOrganisationScope +) + +type Organisation struct{} + +func (Organisation) New() *Organisation { + return &Organisation{} } -// Internal API interface -type OrganisationAPI interface { - List(*OrganisationListRequest) (interface{}, error) - Create(*OrganisationCreateRequest) (interface{}, error) - Edit(*OrganisationEditRequest) (interface{}, error) - Remove(*OrganisationRemoveRequest) (interface{}, error) - Read(*OrganisationReadRequest) (interface{}, error) - Archive(*OrganisationArchiveRequest) (interface{}, error) +func (*Organisation) Create(r *server.OrganisationCreateRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } - // Authenticate API requests - Authenticator() func(http.Handler) http.Handler + // @todo: permission check if user can add/edit organisation + // @todo: make sure archived & deleted entries can not be edited + + o := types.Organisation{}.New().SetName(r.Name).SetID(factory.Sonyflake.NextID()) + return o, db.Insert("organisation", o) } -// HTTP API interface -type OrganisationHandlersAPI interface { - List(http.ResponseWriter, *http.Request) - Create(http.ResponseWriter, *http.Request) - Edit(http.ResponseWriter, *http.Request) - Remove(http.ResponseWriter, *http.Request) - Read(http.ResponseWriter, *http.Request) - Archive(http.ResponseWriter, *http.Request) +func (*Organisation) Edit(r *server.OrganisationEditRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + // @todo: permission check if user can add/edit organisation + // @todo: make sure archived & deleted entries can not be edited + + o := types.Organisation{}.New().SetID(r.ID).SetName(r.Name) + return o, db.Replace("organisation", o) +} + +func (*Organisation) Remove(r *server.OrganisationRemoveRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + // @todo: permission check + // @todo: don't actually delete organisation?! + + stmt := "UPDATE organisationss SET deleted_at = NOW() WHERE deleted_at IS NULL AND id = ?" + + return nil, func() error { + _, err := db.Exec(stmt, r.ID) + return err + }() +} + +func (*Organisation) Read(r *server.OrganisationReadRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + // @todo: permissions check + + o := types.Organisation{}.New() + return o, db.Get(o, sqlOrganisationSelect+" AND id = ?", r.ID) +} + +func (*Organisation) List(r *server.OrganisationListRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + // @todo: permissions check + // @todo: actual search for org + + res := make([]Organisation, 0) + err = db.Select(&res, sqlOrganisationSelect+" WHERE label LIKE = ? ORDER BY label ASC", r.Query+"%") + return res, err +} + +func (*Organisation) Archive(r *server.OrganisationArchiveRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + // @todo: permission check + + stmt := fmt.Sprintf( + "UPDATE organisation SET archived_at = NOW() WHERE %s AND id = ?", + sqlChannelScope) + + return nil, func() error { + _, err := db.Exec(stmt, r.ID) + return err + }() } diff --git a/sam/rest_router.go b/sam/rest/router.go similarity index 89% rename from sam/rest_router.go rename to sam/rest/router.go index 3cf7f4306..1353f68df 100644 --- a/sam/rest_router.go +++ b/sam/rest/router.go @@ -1,4 +1,4 @@ -package sam +package rest /* Hello! This file is auto-generated from `docs/src/spec.json`. @@ -21,16 +21,16 @@ import ( "reflect" "runtime" - "github.com/crusttech/crust/sam/rest" + "github.com/crusttech/crust/sam/rest/server" ) func MountRoutes(r chi.Router) { - channel := &rest.ChannelHandlers{Channel{}.New()} - message := &rest.MessageHandlers{Message{}.New()} - organisation := &rest.OrganisationHandlers{Organisation{}.New()} - team := &rest.TeamHandlers{Team{}.New()} - user := &rest.UserHandlers{User{}.New()} - websocket := &rest.WebsocketHandlers{Websocket{}.New()} + channel := &server.ChannelHandlers{Channel{}.New()} + message := &server.MessageHandlers{Message{}.New()} + organisation := &server.OrganisationHandlers{Organisation{}.New()} + team := &server.TeamHandlers{Team{}.New()} + user := &server.UserHandlers{User{}.New()} + websocket := &server.WebsocketHandlers{Websocket{}.New()} r.Group(func(r chi.Router) { r.Use(channel.Channel.Authenticator()) r.Route("/channel", func(r chi.Router) { diff --git a/sam/rest/server/channel.go b/sam/rest/server/channel.go new file mode 100644 index 000000000..51eeb969c --- /dev/null +++ b/sam/rest/server/channel.go @@ -0,0 +1,46 @@ +package server + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `channel.go`, `channel.util.go` or `channel_test.go` to + implement your API calls, helper functions and tests. The file `channel.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "net/http" +) + +// HTTP handlers are a superset of internal APIs +type ChannelHandlers struct { + Channel ChannelAPI +} + +// Internal API interface +type ChannelAPI interface { + List(*ChannelListRequest) (interface{}, error) + Create(*ChannelCreateRequest) (interface{}, error) + Edit(*ChannelEditRequest) (interface{}, error) + Read(*ChannelReadRequest) (interface{}, error) + Delete(*ChannelDeleteRequest) (interface{}, error) + + // Authenticate API requests + Authenticator() func(http.Handler) http.Handler +} + +// HTTP API interface +type ChannelHandlersAPI interface { + List(http.ResponseWriter, *http.Request) + Create(http.ResponseWriter, *http.Request) + Edit(http.ResponseWriter, *http.Request) + Read(http.ResponseWriter, *http.Request) + Delete(http.ResponseWriter, *http.Request) +} diff --git a/sam/rest/channel_handlers.go b/sam/rest/server/channel_handlers.go similarity index 99% rename from sam/rest/channel_handlers.go rename to sam/rest/server/channel_handlers.go index 07fb9aaaa..7be5a4e4a 100644 --- a/sam/rest/channel_handlers.go +++ b/sam/rest/server/channel_handlers.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/channel_requests.go b/sam/rest/server/channel_requests.go similarity index 99% rename from sam/rest/channel_requests.go rename to sam/rest/server/channel_requests.go index fc5dd8548..aeb6639d2 100644 --- a/sam/rest/channel_requests.go +++ b/sam/rest/server/channel_requests.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/server/message.go b/sam/rest/server/message.go new file mode 100644 index 000000000..f13f01c3e --- /dev/null +++ b/sam/rest/server/message.go @@ -0,0 +1,50 @@ +package server + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `message.go`, `message.util.go` or `message_test.go` to + implement your API calls, helper functions and tests. The file `message.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "net/http" +) + +// HTTP handlers are a superset of internal APIs +type MessageHandlers struct { + Message MessageAPI +} + +// Internal API interface +type MessageAPI interface { + Edit(*MessageEditRequest) (interface{}, error) + Attach(*MessageAttachRequest) (interface{}, error) + Remove(*MessageRemoveRequest) (interface{}, error) + Read(*MessageReadRequest) (interface{}, error) + Search(*MessageSearchRequest) (interface{}, error) + Pin(*MessagePinRequest) (interface{}, error) + Flag(*MessageFlagRequest) (interface{}, error) + + // Authenticate API requests + Authenticator() func(http.Handler) http.Handler +} + +// HTTP API interface +type MessageHandlersAPI interface { + Edit(http.ResponseWriter, *http.Request) + Attach(http.ResponseWriter, *http.Request) + Remove(http.ResponseWriter, *http.Request) + Read(http.ResponseWriter, *http.Request) + Search(http.ResponseWriter, *http.Request) + Pin(http.ResponseWriter, *http.Request) + Flag(http.ResponseWriter, *http.Request) +} diff --git a/sam/rest/message_handlers.go b/sam/rest/server/message_handlers.go similarity index 99% rename from sam/rest/message_handlers.go rename to sam/rest/server/message_handlers.go index 239ed02f2..ad33ce025 100644 --- a/sam/rest/message_handlers.go +++ b/sam/rest/server/message_handlers.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/message_requests.go b/sam/rest/server/message_requests.go similarity index 99% rename from sam/rest/message_requests.go rename to sam/rest/server/message_requests.go index 0e5865dda..0a8989cce 100644 --- a/sam/rest/message_requests.go +++ b/sam/rest/server/message_requests.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/crm/rest/misc.go b/sam/rest/server/misc.go similarity index 90% rename from crm/rest/misc.go rename to sam/rest/server/misc.go index 8745731b6..8d0a991a9 100644 --- a/crm/rest/misc.go +++ b/sam/rest/server/misc.go @@ -1,4 +1,4 @@ -package rest +package server import ( "net/http" diff --git a/sam/rest/server/organisation.go b/sam/rest/server/organisation.go new file mode 100644 index 000000000..3212c0a0f --- /dev/null +++ b/sam/rest/server/organisation.go @@ -0,0 +1,48 @@ +package server + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `organisation.go`, `organisation.util.go` or `organisation_test.go` to + implement your API calls, helper functions and tests. The file `organisation.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "net/http" +) + +// HTTP handlers are a superset of internal APIs +type OrganisationHandlers struct { + Organisation OrganisationAPI +} + +// Internal API interface +type OrganisationAPI interface { + List(*OrganisationListRequest) (interface{}, error) + Create(*OrganisationCreateRequest) (interface{}, error) + Edit(*OrganisationEditRequest) (interface{}, error) + Remove(*OrganisationRemoveRequest) (interface{}, error) + Read(*OrganisationReadRequest) (interface{}, error) + Archive(*OrganisationArchiveRequest) (interface{}, error) + + // Authenticate API requests + Authenticator() func(http.Handler) http.Handler +} + +// HTTP API interface +type OrganisationHandlersAPI interface { + List(http.ResponseWriter, *http.Request) + Create(http.ResponseWriter, *http.Request) + Edit(http.ResponseWriter, *http.Request) + Remove(http.ResponseWriter, *http.Request) + Read(http.ResponseWriter, *http.Request) + Archive(http.ResponseWriter, *http.Request) +} diff --git a/sam/rest/organisation_handlers.go b/sam/rest/server/organisation_handlers.go similarity index 99% rename from sam/rest/organisation_handlers.go rename to sam/rest/server/organisation_handlers.go index b5cf78480..5843f48ea 100644 --- a/sam/rest/organisation_handlers.go +++ b/sam/rest/server/organisation_handlers.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/organisation_requests.go b/sam/rest/server/organisation_requests.go similarity index 99% rename from sam/rest/organisation_requests.go rename to sam/rest/server/organisation_requests.go index 4e10dafb6..1566ae1b4 100644 --- a/sam/rest/organisation_requests.go +++ b/sam/rest/server/organisation_requests.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/server/team.go b/sam/rest/server/team.go new file mode 100644 index 000000000..13fbdf60d --- /dev/null +++ b/sam/rest/server/team.go @@ -0,0 +1,52 @@ +package server + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `team.go`, `team.util.go` or `team_test.go` to + implement your API calls, helper functions and tests. The file `team.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "net/http" +) + +// HTTP handlers are a superset of internal APIs +type TeamHandlers struct { + Team TeamAPI +} + +// Internal API interface +type TeamAPI interface { + List(*TeamListRequest) (interface{}, error) + Create(*TeamCreateRequest) (interface{}, error) + Edit(*TeamEditRequest) (interface{}, error) + Read(*TeamReadRequest) (interface{}, error) + Remove(*TeamRemoveRequest) (interface{}, error) + Archive(*TeamArchiveRequest) (interface{}, error) + Move(*TeamMoveRequest) (interface{}, error) + Merge(*TeamMergeRequest) (interface{}, error) + + // Authenticate API requests + Authenticator() func(http.Handler) http.Handler +} + +// HTTP API interface +type TeamHandlersAPI interface { + List(http.ResponseWriter, *http.Request) + Create(http.ResponseWriter, *http.Request) + Edit(http.ResponseWriter, *http.Request) + Read(http.ResponseWriter, *http.Request) + Remove(http.ResponseWriter, *http.Request) + Archive(http.ResponseWriter, *http.Request) + Move(http.ResponseWriter, *http.Request) + Merge(http.ResponseWriter, *http.Request) +} diff --git a/sam/rest/team_handlers.go b/sam/rest/server/team_handlers.go similarity index 99% rename from sam/rest/team_handlers.go rename to sam/rest/server/team_handlers.go index 22bc7e123..e4aa7950d 100644 --- a/sam/rest/team_handlers.go +++ b/sam/rest/server/team_handlers.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/team_requests.go b/sam/rest/server/team_requests.go similarity index 99% rename from sam/rest/team_requests.go rename to sam/rest/server/team_requests.go index 7317c2a39..c2e64b9e5 100644 --- a/sam/rest/team_requests.go +++ b/sam/rest/server/team_requests.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/server/user.go b/sam/rest/server/user.go new file mode 100644 index 000000000..ff6469a18 --- /dev/null +++ b/sam/rest/server/user.go @@ -0,0 +1,40 @@ +package server + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `user.go`, `user.util.go` or `user_test.go` to + implement your API calls, helper functions and tests. The file `user.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "net/http" +) + +// HTTP handlers are a superset of internal APIs +type UserHandlers struct { + User UserAPI +} + +// Internal API interface +type UserAPI interface { + Login(*UserLoginRequest) (interface{}, error) + Search(*UserSearchRequest) (interface{}, error) + + // Authenticate API requests + Authenticator() func(http.Handler) http.Handler +} + +// HTTP API interface +type UserHandlersAPI interface { + Login(http.ResponseWriter, *http.Request) + Search(http.ResponseWriter, *http.Request) +} diff --git a/sam/rest/user_handlers.go b/sam/rest/server/user_handlers.go similarity index 98% rename from sam/rest/user_handlers.go rename to sam/rest/server/user_handlers.go index 939ef913e..fa99776bc 100644 --- a/sam/rest/user_handlers.go +++ b/sam/rest/server/user_handlers.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/user_requests.go b/sam/rest/server/user_requests.go similarity index 99% rename from sam/rest/user_requests.go rename to sam/rest/server/user_requests.go index ad0b9f3e9..707977756 100644 --- a/sam/rest/user_requests.go +++ b/sam/rest/server/user_requests.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/util.go b/sam/rest/server/util.go similarity index 97% rename from sam/rest/util.go rename to sam/rest/server/util.go index 4b64b4986..ad45db86b 100644 --- a/sam/rest/util.go +++ b/sam/rest/server/util.go @@ -1,4 +1,4 @@ -package rest +package server import ( "regexp" diff --git a/crm/rest/util_test.go b/sam/rest/server/util_test.go similarity index 96% rename from crm/rest/util_test.go rename to sam/rest/server/util_test.go index f4824a0cc..5ea194bfa 100644 --- a/crm/rest/util_test.go +++ b/sam/rest/server/util_test.go @@ -1,4 +1,4 @@ -package rest +package server import ( "testing" diff --git a/sam/rest/server/websocket.go b/sam/rest/server/websocket.go new file mode 100644 index 000000000..d4f20f46a --- /dev/null +++ b/sam/rest/server/websocket.go @@ -0,0 +1,38 @@ +package server + +/* + Hello! This file is auto-generated from `docs/src/spec.json`. + + For development: + In order to update the generated files, edit this file under the location, + add your struct fields, imports, API definitions and whatever you want, and: + + 1. run [spec](https://github.com/titpetric/spec) in the same folder, + 2. run `./_gen.php` in this folder. + + You may edit `websocket.go`, `websocket.util.go` or `websocket_test.go` to + implement your API calls, helper functions and tests. The file `websocket.go` + is only generated the first time, and will not be overwritten if it exists. +*/ + +import ( + "net/http" +) + +// HTTP handlers are a superset of internal APIs +type WebsocketHandlers struct { + Websocket WebsocketAPI +} + +// Internal API interface +type WebsocketAPI interface { + Client(*WebsocketClientRequest) (interface{}, error) + + // Authenticate API requests + Authenticator() func(http.Handler) http.Handler +} + +// HTTP API interface +type WebsocketHandlersAPI interface { + Client(http.ResponseWriter, *http.Request) +} diff --git a/sam/rest/websocket_handlers.go b/sam/rest/server/websocket_handlers.go similarity index 98% rename from sam/rest/websocket_handlers.go rename to sam/rest/server/websocket_handlers.go index fbd7b87d7..d223ba0bf 100644 --- a/sam/rest/websocket_handlers.go +++ b/sam/rest/server/websocket_handlers.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/websocket_requests.go b/sam/rest/server/websocket_requests.go similarity index 98% rename from sam/rest/websocket_requests.go rename to sam/rest/server/websocket_requests.go index 8beca626c..9b8f0c021 100644 --- a/sam/rest/websocket_requests.go +++ b/sam/rest/server/websocket_requests.go @@ -1,4 +1,4 @@ -package rest +package server /* Hello! This file is auto-generated from `docs/src/spec.json`. diff --git a/sam/rest/team.go b/sam/rest/team.go index c9b5150c9..fb2ab0a02 100644 --- a/sam/rest/team.go +++ b/sam/rest/team.go @@ -1,52 +1,110 @@ package rest -/* - Hello! This file is auto-generated from `docs/src/spec.json`. - - For development: - In order to update the generated files, edit this file under the location, - add your struct fields, imports, API definitions and whatever you want, and: - - 1. run [spec](https://github.com/titpetric/spec) in the same folder, - 2. run `./_gen.php` in this folder. - - You may edit `team.go`, `team.util.go` or `team_test.go` to - implement your API calls, helper functions and tests. The file `team.go` - is only generated the first time, and will not be overwritten if it exists. -*/ - import ( - "net/http" + "fmt" + "github.com/pkg/errors" + "github.com/titpetric/factory" + + "github.com/crusttech/crust/sam/rest/server" + "github.com/crusttech/crust/sam/types" ) -// HTTP handlers are a superset of internal APIs -type TeamHandlers struct { - Team TeamAPI +var _ = errors.Wrap + +const ( + sqlTeamScope = "deleted_at IS NULL AND archived_at IS NULL" + sqlTeamSelect = "SELECT * FROM teams WHERE " + sqlTeamScope +) + +type Team struct{} + +func (Team) New() *Team { + return &Team{} } -// Internal API interface -type TeamAPI interface { - List(*TeamListRequest) (interface{}, error) - Create(*TeamCreateRequest) (interface{}, error) - Edit(*TeamEditRequest) (interface{}, error) - Read(*TeamReadRequest) (interface{}, error) - Remove(*TeamRemoveRequest) (interface{}, error) - Archive(*TeamArchiveRequest) (interface{}, error) - Move(*TeamMoveRequest) (interface{}, error) - Merge(*TeamMergeRequest) (interface{}, error) +func (*Team) Create(r *server.TeamCreateRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } - // Authenticate API requests - Authenticator() func(http.Handler) http.Handler + // @todo: permission check if user can add/edit the team + // @todo: make sure archived & deleted entries can not be edited + + t := types.Team{}.New() + t.SetName(r.Name).SetMemberIDs(r.Members).SetID(factory.Sonyflake.NextID()) + return t, db.Insert("team", t) } -// HTTP API interface -type TeamHandlersAPI interface { - List(http.ResponseWriter, *http.Request) - Create(http.ResponseWriter, *http.Request) - Edit(http.ResponseWriter, *http.Request) - Read(http.ResponseWriter, *http.Request) - Remove(http.ResponseWriter, *http.Request) - Archive(http.ResponseWriter, *http.Request) - Move(http.ResponseWriter, *http.Request) - Merge(http.ResponseWriter, *http.Request) +func (*Team) Edit(r *server.TeamEditRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + // @todo: permission check if user can add/edit the team + // @todo: make sure archived & deleted entries can not be edited + + t := types.Team{}.New() + t.SetID(r.ID).SetName(r.Name).SetMemberIDs(r.Members) + return t, db.Replace("team", t) +} + +func (*Team) Remove(r *server.TeamRemoveRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + stmt := "UPDATE teams SET deleted_at = NOW() WHERE deleted_at IS NULL AND id = ?" + + return nil, func() error { + _, err := db.Exec(stmt, r.ID) + return err + }() +} + +func (*Team) Read(r *server.TeamReadRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + t := types.Team{}.New() + return t, db.Get(t, sqlTeamSelect+" AND id = ?", r.ID) +} + +func (*Team) List(r *server.TeamListRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + res := make([]Team, 0) + err = db.Select(&res, sqlTeamSelect+" ORDER BY name ASC") + return res, err +} + +func (*Team) Archive(r *server.TeamArchiveRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + stmt := fmt.Sprintf( + "UPDATE teams SET archived_at = NOW() WHERE %s AND id = ?", + sqlTeamScope) + + return nil, func() error { + _, err := db.Exec(stmt, r.ID) + return err + }() +} + +func (*Team) Move(r *server.TeamMoveRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Team.move") +} + +func (*Team) Merge(r *server.TeamMergeRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Team.merge") } diff --git a/sam/rest/user.go b/sam/rest/user.go index 534166767..a462a2d63 100644 --- a/sam/rest/user.go +++ b/sam/rest/user.go @@ -1,40 +1,118 @@ package rest -/* - Hello! This file is auto-generated from `docs/src/spec.json`. - - For development: - In order to update the generated files, edit this file under the location, - add your struct fields, imports, API definitions and whatever you want, and: - - 1. run [spec](https://github.com/titpetric/spec) in the same folder, - 2. run `./_gen.php` in this folder. - - You may edit `user.go`, `user.util.go` or `user_test.go` to - implement your API calls, helper functions and tests. The file `user.go` - is only generated the first time, and will not be overwritten if it exists. -*/ - import ( - "net/http" + "github.com/pkg/errors" + "github.com/titpetric/factory" + + "github.com/crusttech/crust/sam/rest/server" + "github.com/crusttech/crust/sam/service" + "github.com/crusttech/crust/sam/types" ) -// HTTP handlers are a superset of internal APIs -type UserHandlers struct { - User UserAPI +var _ = errors.Wrap + +const ( + sqlUserScope = "suspended_at IS NULL AND archived_at IS NULL" + sqlUserSelect = "SELECT * FROM users WHERE " + sqlUserScope +) + +type ( + User struct { + service UserInterface + } + + UserInterface interface { + Set(*types.User) + CanLogin() bool + GeneratePassword(value string) ([]byte, error) + ValidatePassword(value string) bool + ValidateUser() bool + } +) + +func (User) New() *User { + return &User{service.User{}.New()} } -// Internal API interface -type UserAPI interface { - Login(*UserLoginRequest) (interface{}, error) - Search(*UserSearchRequest) (interface{}, error) +/* +func (self *User) Read(r *teamReadRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } - // Authenticate API requests - Authenticator() func(http.Handler) http.Handler + t := types.User{}.New() + return t, db.Get(t, sqlUserSelect+" AND id = ?", r.ID) +} +*/ + +// User lookup & login +func (self *User) Login(r *server.UserLoginRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + u := types.User{}.New() + if err = db.Get(u, sqlUserSelect+" AND username = ?", r.Username); err != nil { + return nil, err + } + self.service.Set(u) + + if self.service.ValidateUser() || !self.service.ValidatePassword(r.Password) { + return nil, errors.New("Invalid username and password combination") + } + + if !self.service.CanLogin() { + return nil, errors.New("User is not allowed to login") + } + + return u, nil } -// HTTP API interface -type UserHandlersAPI interface { - Login(http.ResponseWriter, *http.Request) - Search(http.ResponseWriter, *http.Request) +// Searches the users table in the database to find users by matching (by-prefix) their.Username +func (*User) Search(r *server.UserSearchRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + uu := []types.User{} + if err != db.Get(uu, sqlUserSelect+" AND username LIKE ?", r.Query+"%") { + return nil, err + } + + return uu, nil } + +/* +func (self *User) Remove(r *teamRemoveRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + stmt := "UPDATE users SET deleted_at = NOW() WHERE deleted_at IS NULL AND id = ?" + + return nil, func() error { + _, err := db.Exec(stmt, r.ID) + return err + }() +} + +func (self *User) Archive(r *teamArchiveRequest) (interface{}, error) { + db, err := factory.Database.Get() + if err != nil { + return nil, err + } + + stmt := fmt.Sprintf( + "UPDATE users SET archived_at = NOW() WHERE %s AND id = ?", + sqlUserScope) + + return nil, func() error { + _, err := db.Exec(stmt, r.ID) + return err + }() +} +*/ diff --git a/sam/rest/websocket.go b/sam/rest/websocket.go index d44e3b473..b138b8e8e 100644 --- a/sam/rest/websocket.go +++ b/sam/rest/websocket.go @@ -1,38 +1,20 @@ package rest -/* - Hello! This file is auto-generated from `docs/src/spec.json`. - - For development: - In order to update the generated files, edit this file under the location, - add your struct fields, imports, API definitions and whatever you want, and: - - 1. run [spec](https://github.com/titpetric/spec) in the same folder, - 2. run `./_gen.php` in this folder. - - You may edit `websocket.go`, `websocket.util.go` or `websocket_test.go` to - implement your API calls, helper functions and tests. The file `websocket.go` - is only generated the first time, and will not be overwritten if it exists. -*/ - import ( - "net/http" + "github.com/pkg/errors" + + "github.com/crusttech/crust/sam/rest/server" + _ "github.com/crusttech/crust/sam/types" ) -// HTTP handlers are a superset of internal APIs -type WebsocketHandlers struct { - Websocket WebsocketAPI +var _ = errors.Wrap + +type Websocket struct{} + +func (Websocket) New() *Websocket { + return &Websocket{} } -// Internal API interface -type WebsocketAPI interface { - Client(*WebsocketClientRequest) (interface{}, error) - - // Authenticate API requests - Authenticator() func(http.Handler) http.Handler -} - -// HTTP API interface -type WebsocketHandlersAPI interface { - Client(http.ResponseWriter, *http.Request) +func (*Websocket) Client(r *server.WebsocketClientRequest) (interface{}, error) { + return nil, errors.New("Not implemented: Websocket.client") } diff --git a/sam/team.go b/sam/team.go deleted file mode 100644 index 5631341be..000000000 --- a/sam/team.go +++ /dev/null @@ -1,110 +0,0 @@ -package sam - -import ( - "fmt" - "github.com/pkg/errors" - "github.com/titpetric/factory" - - "github.com/crusttech/crust/sam/rest" - "github.com/crusttech/crust/sam/types" -) - -var _ = errors.Wrap - -const ( - sqlTeamScope = "deleted_at IS NULL AND archived_at IS NULL" - sqlTeamSelect = "SELECT * FROM teams WHERE " + sqlTeamScope -) - -type Team struct{} - -func (Team) New() *Team { - return &Team{} -} - -func (*Team) Create(r *rest.TeamCreateRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permission check if user can add/edit the team - // @todo: make sure archived & deleted entries can not be edited - - t := types.Team{}.New() - t.SetName(r.Name).SetMemberIDs(r.Members).SetID(factory.Sonyflake.NextID()) - return t, db.Insert("team", t) -} - -func (*Team) Edit(r *rest.TeamEditRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - // @todo: permission check if user can add/edit the team - // @todo: make sure archived & deleted entries can not be edited - - t := types.Team{}.New() - t.SetID(r.ID).SetName(r.Name).SetMemberIDs(r.Members) - return t, db.Replace("team", t) -} - -func (*Team) Remove(r *rest.TeamRemoveRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - stmt := "UPDATE teams SET deleted_at = NOW() WHERE deleted_at IS NULL AND id = ?" - - return nil, func() error { - _, err := db.Exec(stmt, r.ID) - return err - }() -} - -func (*Team) Read(r *rest.TeamReadRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - t := types.Team{}.New() - return t, db.Get(t, sqlTeamSelect+" AND id = ?", r.ID) -} - -func (*Team) List(r *rest.TeamListRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - res := make([]Team, 0) - err = db.Select(&res, sqlTeamSelect+" ORDER BY name ASC") - return res, err -} - -func (*Team) Archive(r *rest.TeamArchiveRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - stmt := fmt.Sprintf( - "UPDATE teams SET archived_at = NOW() WHERE %s AND id = ?", - sqlTeamScope) - - return nil, func() error { - _, err := db.Exec(stmt, r.ID) - return err - }() -} - -func (*Team) Move(r *rest.TeamMoveRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Team.move") -} - -func (*Team) Merge(r *rest.TeamMergeRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Team.merge") -} diff --git a/sam/user.go b/sam/user.go deleted file mode 100644 index ab51540a4..000000000 --- a/sam/user.go +++ /dev/null @@ -1,118 +0,0 @@ -package sam - -import ( - "github.com/pkg/errors" - "github.com/titpetric/factory" - - "github.com/crusttech/crust/sam/rest" - "github.com/crusttech/crust/sam/service" - "github.com/crusttech/crust/sam/types" -) - -var _ = errors.Wrap - -const ( - sqlUserScope = "suspended_at IS NULL AND archived_at IS NULL" - sqlUserSelect = "SELECT * FROM users WHERE " + sqlUserScope -) - -type ( - User struct { - service UserInterface - } - - UserInterface interface { - Set(*types.User) - CanLogin() bool - GeneratePassword(value string) ([]byte, error) - ValidatePassword(value string) bool - ValidateUser() bool - } -) - -func (User) New() *User { - return &User{service.User{}.New()} -} - -/* -func (self *User) Read(r *teamReadRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - t := types.User{}.New() - return t, db.Get(t, sqlUserSelect+" AND id = ?", r.ID) -} -*/ - -// User lookup & login -func (self *User) Login(r *rest.UserLoginRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - u := types.User{}.New() - if err = db.Get(u, sqlUserSelect+" AND username = ?", r.Username); err != nil { - return nil, err - } - self.service.Set(u) - - if self.service.ValidateUser() || !self.service.ValidatePassword(r.Password) { - return nil, errors.New("Invalid username and password combination") - } - - if !self.service.CanLogin() { - return nil, errors.New("User is not allowed to login") - } - - return u, nil -} - -// Searches the users table in the database to find users by matching (by-prefix) their.Username -func (*User) Search(r *rest.UserSearchRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - uu := []types.User{} - if err != db.Get(uu, sqlUserSelect+" AND username LIKE ?", r.Query+"%") { - return nil, err - } - - return uu, nil -} - -/* -func (self *User) Remove(r *teamRemoveRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - stmt := "UPDATE users SET deleted_at = NOW() WHERE deleted_at IS NULL AND id = ?" - - return nil, func() error { - _, err := db.Exec(stmt, r.ID) - return err - }() -} - -func (self *User) Archive(r *teamArchiveRequest) (interface{}, error) { - db, err := factory.Database.Get() - if err != nil { - return nil, err - } - - stmt := fmt.Sprintf( - "UPDATE users SET archived_at = NOW() WHERE %s AND id = ?", - sqlUserScope) - - return nil, func() error { - _, err := db.Exec(stmt, r.ID) - return err - }() -} -*/ diff --git a/sam/websocket.go b/sam/websocket.go deleted file mode 100644 index 3c58f26b9..000000000 --- a/sam/websocket.go +++ /dev/null @@ -1,20 +0,0 @@ -package sam - -import ( - "github.com/pkg/errors" - - "github.com/crusttech/crust/sam/rest" - _ "github.com/crusttech/crust/sam/types" -) - -var _ = errors.Wrap - -type Websocket struct{} - -func (Websocket) New() *Websocket { - return &Websocket{} -} - -func (*Websocket) Client(r *rest.WebsocketClientRequest) (interface{}, error) { - return nil, errors.New("Not implemented: Websocket.client") -}