add(system): implement additional user apis
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
|
||||
# add field to manage user type (bot support)
|
||||
ALTER TABLE `sys_user` ADD `kind` VARCHAR(8) NOT NULL DEFAULT '' AFTER `handle`;
|
||||
|
||||
# add field to manage "ownership" (get all bots created by user)
|
||||
ALTER TABLE `sys_user` ADD `rel_user_id` BIGINT UNSIGNED NOT NULL AFTER `rel_organisation`, ADD INDEX (`rel_user_id`);
|
||||
+101
-2
@@ -283,10 +283,109 @@ An organisation may have many teams. Teams may have many channels available. Acc
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/users/search` | HTTP/S | GET | Client ID, Session ID |
|
||||
| `/users/` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| query | string | GET | Search query to match against users | N/A | NO |
|
||||
| query | string | GET | Search query to match against users | N/A | NO |
|
||||
|
||||
## Create user
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/users/` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| email | string | POST | Email | N/A | YES |
|
||||
| username | string | POST | Username | N/A | YES |
|
||||
| password | string | POST | Password | N/A | YES |
|
||||
| name | string | POST | Name | N/A | YES |
|
||||
| handle | string | POST | Handle | N/A | YES |
|
||||
| meta | types.JSONText | POST | Meta data | N/A | NO |
|
||||
| satosaID | string | POST | Satosa ID | N/A | NO |
|
||||
| organisationID | uint64 | POST | Organisation ID | N/A | NO |
|
||||
|
||||
## Update user details
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/users/{userID}` | HTTP/S | PUT | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| userID | uint64 | PATH | User ID | N/A | YES |
|
||||
| email | string | POST | Email | N/A | YES |
|
||||
| username | string | POST | Username | N/A | YES |
|
||||
| password | string | POST | Password | N/A | YES |
|
||||
| name | string | POST | Name | N/A | YES |
|
||||
| handle | string | POST | Handle | N/A | YES |
|
||||
| meta | types.JSONText | POST | Meta data | N/A | NO |
|
||||
| satosaID | string | POST | Satosa ID | N/A | NO |
|
||||
| organisationID | uint64 | POST | Organisation ID | N/A | NO |
|
||||
|
||||
## Read user details and memberships
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/users/{userID}` | HTTP/S | GET | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| userID | uint64 | PATH | User ID | N/A | YES |
|
||||
|
||||
## Remove user
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/users/{userID}` | HTTP/S | DELETE | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| userID | uint64 | PATH | User ID | N/A | YES |
|
||||
|
||||
## Suspend user
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/users/{userID}/suspend` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| userID | uint64 | PATH | User ID | N/A | YES |
|
||||
|
||||
## Unsuspend user
|
||||
|
||||
#### Method
|
||||
|
||||
| URI | Protocol | Method | Authentication |
|
||||
| --- | -------- | ------ | -------------- |
|
||||
| `/users/{userID}/unsuspend` | HTTP/S | POST | Client ID, Session ID |
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| userID | uint64 | PATH | User ID | N/A | YES |
|
||||
+197
-1
@@ -373,11 +373,19 @@
|
||||
"Client ID",
|
||||
"Session ID"
|
||||
],
|
||||
"struct": [
|
||||
{
|
||||
"imports": [
|
||||
"github.com/jmoiron/sqlx/types"
|
||||
]
|
||||
}
|
||||
],
|
||||
"apis": [
|
||||
{
|
||||
"name": "search",
|
||||
"name": "list",
|
||||
"method": "GET",
|
||||
"title": "Search users (Directory)",
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"get": [
|
||||
{
|
||||
@@ -388,6 +396,194 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "create",
|
||||
"method": "POST",
|
||||
"title": "Create user",
|
||||
"path": "/",
|
||||
"parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "email",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Email"
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Username"
|
||||
},
|
||||
{
|
||||
"name": "password",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Password"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Name"
|
||||
},
|
||||
{
|
||||
"name": "handle",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Handle"
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"type": "types.JSONText",
|
||||
"required": false,
|
||||
"title": "Meta data"
|
||||
},
|
||||
{
|
||||
"name": "satosaID",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"title": "Satosa ID"
|
||||
},
|
||||
{
|
||||
"name": "organisationID",
|
||||
"type": "uint64",
|
||||
"required": false,
|
||||
"title": "Organisation ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "edit",
|
||||
"method": "PUT",
|
||||
"title": "Update user details",
|
||||
"path": "/{userID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "email",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Email"
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Username"
|
||||
},
|
||||
{
|
||||
"name": "password",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Password"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Name"
|
||||
},
|
||||
{
|
||||
"name": "handle",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"title": "Handle"
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"type": "types.JSONText",
|
||||
"required": false,
|
||||
"title": "Meta data"
|
||||
},
|
||||
{
|
||||
"name": "satosaID",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"title": "Satosa ID"
|
||||
},
|
||||
{
|
||||
"name": "organisationID",
|
||||
"type": "uint64",
|
||||
"required": false,
|
||||
"title": "Organisation ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "read",
|
||||
"method": "GET",
|
||||
"title": "Read user details and memberships",
|
||||
"path": "/{userID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "remove",
|
||||
"method": "DELETE",
|
||||
"title": "Remove user",
|
||||
"path": "/{userID}",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "suspend",
|
||||
"method": "POST",
|
||||
"title": "Suspend user",
|
||||
"path": "/{userID}/suspend",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "unsuspend",
|
||||
"method": "POST",
|
||||
"title": "Unsuspend user",
|
||||
"path": "/{userID}/unsuspend",
|
||||
"parameters": {
|
||||
"path": [
|
||||
{
|
||||
"type": "uint64",
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
"Title": "Users",
|
||||
"Package": "sam",
|
||||
"Interface": "User",
|
||||
"Struct": null,
|
||||
"Struct": [
|
||||
{
|
||||
"imports": [
|
||||
"github.com/jmoiron/sqlx/types"
|
||||
]
|
||||
}
|
||||
],
|
||||
"Parameters": null,
|
||||
"Protocol": "",
|
||||
"Authentication": [
|
||||
@@ -12,10 +18,10 @@
|
||||
"Path": "/users",
|
||||
"APIs": [
|
||||
{
|
||||
"Name": "search",
|
||||
"Name": "list",
|
||||
"Method": "GET",
|
||||
"Title": "Search users (Directory)",
|
||||
"Path": "/search",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"get": [
|
||||
{
|
||||
@@ -26,6 +32,194 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "create",
|
||||
"Method": "POST",
|
||||
"Title": "Create user",
|
||||
"Path": "/",
|
||||
"Parameters": {
|
||||
"post": [
|
||||
{
|
||||
"name": "email",
|
||||
"required": true,
|
||||
"title": "Email",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"required": true,
|
||||
"title": "Username",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "password",
|
||||
"required": true,
|
||||
"title": "Password",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"required": true,
|
||||
"title": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "handle",
|
||||
"required": true,
|
||||
"title": "Handle",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"required": false,
|
||||
"title": "Meta data",
|
||||
"type": "types.JSONText"
|
||||
},
|
||||
{
|
||||
"name": "satosaID",
|
||||
"required": false,
|
||||
"title": "Satosa ID",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "organisationID",
|
||||
"required": false,
|
||||
"title": "Organisation ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "edit",
|
||||
"Method": "PUT",
|
||||
"Title": "Update user details",
|
||||
"Path": "/{userID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"post": [
|
||||
{
|
||||
"name": "email",
|
||||
"required": true,
|
||||
"title": "Email",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"required": true,
|
||||
"title": "Username",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "password",
|
||||
"required": true,
|
||||
"title": "Password",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"required": true,
|
||||
"title": "Name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "handle",
|
||||
"required": true,
|
||||
"title": "Handle",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"required": false,
|
||||
"title": "Meta data",
|
||||
"type": "types.JSONText"
|
||||
},
|
||||
{
|
||||
"name": "satosaID",
|
||||
"required": false,
|
||||
"title": "Satosa ID",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "organisationID",
|
||||
"required": false,
|
||||
"title": "Organisation ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "read",
|
||||
"Method": "GET",
|
||||
"Title": "Read user details and memberships",
|
||||
"Path": "/{userID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "remove",
|
||||
"Method": "DELETE",
|
||||
"Title": "Remove user",
|
||||
"Path": "/{userID}",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "suspend",
|
||||
"Method": "POST",
|
||||
"Title": "Suspend user",
|
||||
"Path": "/{userID}/suspend",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "unsuspend",
|
||||
"Method": "POST",
|
||||
"Title": "Unsuspend user",
|
||||
"Path": "/{userID}/unsuspend",
|
||||
"Parameters": {
|
||||
"path": [
|
||||
{
|
||||
"name": "userID",
|
||||
"required": true,
|
||||
"title": "User ID",
|
||||
"type": "uint64"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -21,6 +21,7 @@ type (
|
||||
|
||||
Create(mod *types.User) (*types.User, error)
|
||||
Update(mod *types.User) (*types.User, error)
|
||||
|
||||
SuspendByID(id uint64) error
|
||||
UnsuspendByID(id uint64) error
|
||||
DeleteByID(id uint64) error
|
||||
|
||||
@@ -27,21 +27,75 @@ import (
|
||||
|
||||
// Internal API interface
|
||||
type UserAPI interface {
|
||||
Search(context.Context, *request.UserSearch) (interface{}, error)
|
||||
List(context.Context, *request.UserList) (interface{}, error)
|
||||
Create(context.Context, *request.UserCreate) (interface{}, error)
|
||||
Edit(context.Context, *request.UserEdit) (interface{}, error)
|
||||
Read(context.Context, *request.UserRead) (interface{}, error)
|
||||
Remove(context.Context, *request.UserRemove) (interface{}, error)
|
||||
Suspend(context.Context, *request.UserSuspend) (interface{}, error)
|
||||
Unsuspend(context.Context, *request.UserUnsuspend) (interface{}, error)
|
||||
}
|
||||
|
||||
// HTTP API interface
|
||||
type User struct {
|
||||
Search func(http.ResponseWriter, *http.Request)
|
||||
List func(http.ResponseWriter, *http.Request)
|
||||
Create func(http.ResponseWriter, *http.Request)
|
||||
Edit func(http.ResponseWriter, *http.Request)
|
||||
Read func(http.ResponseWriter, *http.Request)
|
||||
Remove func(http.ResponseWriter, *http.Request)
|
||||
Suspend func(http.ResponseWriter, *http.Request)
|
||||
Unsuspend func(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
func NewUser(uh UserAPI) *User {
|
||||
return &User{
|
||||
Search: func(w http.ResponseWriter, r *http.Request) {
|
||||
List: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewUserSearch()
|
||||
params := request.NewUserList()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return uh.Search(r.Context(), params)
|
||||
return uh.List(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Create: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewUserCreate()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return uh.Create(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Edit: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewUserEdit()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return uh.Edit(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Read: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewUserRead()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return uh.Read(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Remove: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewUserRemove()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return uh.Remove(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Suspend: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewUserSuspend()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return uh.Suspend(r.Context(), params)
|
||||
})
|
||||
},
|
||||
Unsuspend: func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
params := request.NewUserUnsuspend()
|
||||
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
|
||||
return uh.Unsuspend(r.Context(), params)
|
||||
})
|
||||
},
|
||||
}
|
||||
@@ -51,7 +105,13 @@ func (uh *User) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middlewares...)
|
||||
r.Route("/users", func(r chi.Router) {
|
||||
r.Get("/search", uh.Search)
|
||||
r.Get("/", uh.List)
|
||||
r.Post("/", uh.Create)
|
||||
r.Put("/{userID}", uh.Edit)
|
||||
r.Get("/{userID}", uh.Read)
|
||||
r.Delete("/{userID}", uh.Remove)
|
||||
r.Post("/{userID}/suspend", uh.Suspend)
|
||||
r.Post("/{userID}/unsuspend", uh.Unsuspend)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
+346
-6
@@ -30,16 +30,16 @@ var _ = chi.URLParam
|
||||
var _ = types.JSONText{}
|
||||
var _ = multipart.FileHeader{}
|
||||
|
||||
// User search request parameters
|
||||
type UserSearch struct {
|
||||
// User list request parameters
|
||||
type UserList struct {
|
||||
Query string
|
||||
}
|
||||
|
||||
func NewUserSearch() *UserSearch {
|
||||
return &UserSearch{}
|
||||
func NewUserList() *UserList {
|
||||
return &UserList{}
|
||||
}
|
||||
|
||||
func (u *UserSearch) Fill(r *http.Request) (err error) {
|
||||
func (u *UserList) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
|
||||
@@ -74,4 +74,344 @@ func (u *UserSearch) Fill(r *http.Request) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewUserSearch()
|
||||
var _ RequestFiller = NewUserList()
|
||||
|
||||
// User create request parameters
|
||||
type UserCreate struct {
|
||||
Email string
|
||||
Username string
|
||||
Password string
|
||||
Name string
|
||||
Handle string
|
||||
Meta types.JSONText
|
||||
SatosaID string
|
||||
OrganisationID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewUserCreate() *UserCreate {
|
||||
return &UserCreate{}
|
||||
}
|
||||
|
||||
func (u *UserCreate) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
if val, ok := post["email"]; ok {
|
||||
|
||||
u.Email = val
|
||||
}
|
||||
if val, ok := post["username"]; ok {
|
||||
|
||||
u.Username = val
|
||||
}
|
||||
if val, ok := post["password"]; ok {
|
||||
|
||||
u.Password = val
|
||||
}
|
||||
if val, ok := post["name"]; ok {
|
||||
|
||||
u.Name = val
|
||||
}
|
||||
if val, ok := post["handle"]; ok {
|
||||
|
||||
u.Handle = val
|
||||
}
|
||||
if val, ok := post["meta"]; ok {
|
||||
|
||||
if u.Meta, err = parseJSONText(val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := post["satosaID"]; ok {
|
||||
|
||||
u.SatosaID = val
|
||||
}
|
||||
if val, ok := post["organisationID"]; ok {
|
||||
|
||||
u.OrganisationID = parseUInt64(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewUserCreate()
|
||||
|
||||
// User edit request parameters
|
||||
type UserEdit struct {
|
||||
UserID uint64 `json:",string"`
|
||||
Email string
|
||||
Username string
|
||||
Password string
|
||||
Name string
|
||||
Handle string
|
||||
Meta types.JSONText
|
||||
SatosaID string
|
||||
OrganisationID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewUserEdit() *UserEdit {
|
||||
return &UserEdit{}
|
||||
}
|
||||
|
||||
func (u *UserEdit) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
if val, ok := post["email"]; ok {
|
||||
|
||||
u.Email = val
|
||||
}
|
||||
if val, ok := post["username"]; ok {
|
||||
|
||||
u.Username = val
|
||||
}
|
||||
if val, ok := post["password"]; ok {
|
||||
|
||||
u.Password = val
|
||||
}
|
||||
if val, ok := post["name"]; ok {
|
||||
|
||||
u.Name = val
|
||||
}
|
||||
if val, ok := post["handle"]; ok {
|
||||
|
||||
u.Handle = val
|
||||
}
|
||||
if val, ok := post["meta"]; ok {
|
||||
|
||||
if u.Meta, err = parseJSONText(val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if val, ok := post["satosaID"]; ok {
|
||||
|
||||
u.SatosaID = val
|
||||
}
|
||||
if val, ok := post["organisationID"]; ok {
|
||||
|
||||
u.OrganisationID = parseUInt64(val)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewUserEdit()
|
||||
|
||||
// User read request parameters
|
||||
type UserRead struct {
|
||||
UserID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewUserRead() *UserRead {
|
||||
return &UserRead{}
|
||||
}
|
||||
|
||||
func (u *UserRead) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewUserRead()
|
||||
|
||||
// User remove request parameters
|
||||
type UserRemove struct {
|
||||
UserID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewUserRemove() *UserRemove {
|
||||
return &UserRemove{}
|
||||
}
|
||||
|
||||
func (u *UserRemove) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewUserRemove()
|
||||
|
||||
// User suspend request parameters
|
||||
type UserSuspend struct {
|
||||
UserID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewUserSuspend() *UserSuspend {
|
||||
return &UserSuspend{}
|
||||
}
|
||||
|
||||
func (u *UserSuspend) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewUserSuspend()
|
||||
|
||||
// User unsuspend request parameters
|
||||
type UserUnsuspend struct {
|
||||
UserID uint64 `json:",string"`
|
||||
}
|
||||
|
||||
func NewUserUnsuspend() *UserUnsuspend {
|
||||
return &UserUnsuspend{}
|
||||
}
|
||||
|
||||
func (u *UserUnsuspend) Fill(r *http.Request) (err error) {
|
||||
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
|
||||
err = json.NewDecoder(r.Body).Decode(u)
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
err = nil
|
||||
case err != nil:
|
||||
return errors.Wrap(err, "error parsing http request body")
|
||||
}
|
||||
}
|
||||
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
get := map[string]string{}
|
||||
post := map[string]string{}
|
||||
urlQuery := r.URL.Query()
|
||||
for name, param := range urlQuery {
|
||||
get[name] = string(param[0])
|
||||
}
|
||||
postVars := r.Form
|
||||
for name, param := range postVars {
|
||||
post[name] = string(param[0])
|
||||
}
|
||||
|
||||
u.UserID = parseUInt64(chi.URLParam(r, "userID"))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var _ RequestFiller = NewUserUnsuspend()
|
||||
|
||||
+50
-1
@@ -25,6 +25,55 @@ func (User) New() *User {
|
||||
}
|
||||
|
||||
// Searches the users table in the database to find users by matching (by-prefix) their.Username
|
||||
func (ctrl *User) Search(ctx context.Context, r *request.UserSearch) (interface{}, error) {
|
||||
func (ctrl *User) List(ctx context.Context, r *request.UserList) (interface{}, error) {
|
||||
return ctrl.user.With(ctx).Find(&types.UserFilter{Query: r.Query})
|
||||
}
|
||||
|
||||
func (ctrl *User) Create(ctx context.Context, r *request.UserCreate) (interface{}, error) {
|
||||
user := &types.User{
|
||||
Email: r.Email,
|
||||
Username: r.Username,
|
||||
Name: r.Name,
|
||||
Handle: r.Handle,
|
||||
Meta: r.Meta,
|
||||
SatosaID: r.SatosaID,
|
||||
OrganisationID: r.OrganisationID,
|
||||
}
|
||||
if err := user.GeneratePassword(r.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ctrl.user.With(ctx).Create(user)
|
||||
}
|
||||
|
||||
func (ctrl *User) Edit(ctx context.Context, r *request.UserEdit) (interface{}, error) {
|
||||
user := &types.User{
|
||||
ID: r.UserID,
|
||||
Email: r.Email,
|
||||
Username: r.Username,
|
||||
Name: r.Name,
|
||||
Handle: r.Handle,
|
||||
Meta: r.Meta,
|
||||
SatosaID: r.SatosaID,
|
||||
OrganisationID: r.OrganisationID,
|
||||
}
|
||||
if err := user.GeneratePassword(r.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ctrl.user.With(ctx).Update(user)
|
||||
}
|
||||
|
||||
func (ctrl *User) Read(ctx context.Context, r *request.UserRead) (interface{}, error) {
|
||||
return ctrl.user.With(ctx).FindByID(r.UserID)
|
||||
}
|
||||
|
||||
func (ctrl *User) Remove(ctx context.Context, r *request.UserRemove) (interface{}, error) {
|
||||
return nil, ctrl.user.With(ctx).Delete(r.UserID)
|
||||
}
|
||||
|
||||
func (ctrl *User) Suspend(ctx context.Context, r *request.UserSuspend) (interface{}, error) {
|
||||
return nil, ctrl.user.With(ctx).Suspend(r.UserID)
|
||||
}
|
||||
|
||||
func (ctrl *User) Unsuspend(ctx context.Context, r *request.UserUnsuspend) (interface{}, error) {
|
||||
return nil, ctrl.user.With(ctx).Unsuspend(r.UserID)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@ type (
|
||||
Create(input *types.User) (*types.User, error)
|
||||
Update(mod *types.User) (*types.User, error)
|
||||
|
||||
Delete(id uint64) error
|
||||
Suspend(id uint64) error
|
||||
Unsuspend(id uint64) error
|
||||
|
||||
FindOrCreate(*types.User) (*types.User, error)
|
||||
ValidateCredentials(username, password string) (*types.User, error)
|
||||
}
|
||||
@@ -53,6 +57,18 @@ func (svc *user) With(ctx context.Context) UserService {
|
||||
}
|
||||
}
|
||||
|
||||
func (svc *user) Delete(id uint64) error {
|
||||
return svc.user.DeleteByID(id)
|
||||
}
|
||||
|
||||
func (svc *user) Suspend(id uint64) error {
|
||||
return svc.user.SuspendByID(id)
|
||||
}
|
||||
|
||||
func (svc *user) Unsuspend(id uint64) error {
|
||||
return svc.user.UnsuspendByID(id)
|
||||
}
|
||||
|
||||
func (svc *user) ValidateCredentials(username, password string) (*types.User, error) {
|
||||
user, err := svc.user.FindByUsername(username)
|
||||
if err != nil {
|
||||
|
||||
+13
-9
@@ -9,15 +9,19 @@ import (
|
||||
|
||||
type (
|
||||
User struct {
|
||||
ID uint64 `json:"id" db:"id"`
|
||||
Username string `json:"username" db:"username"`
|
||||
Email string `json:"email" db:"email"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Handle string `json:"handle" db:"handle"`
|
||||
SatosaID string `json:"-" db:"satosa_id"`
|
||||
Meta types.JSONText `json:"-" db:"meta"`
|
||||
OrganisationID uint64 `json:"organisationId" db:"rel_organisation"`
|
||||
Password []byte `json:"-" db:"password"`
|
||||
ID uint64 `json:"id,string" db:"id"`
|
||||
Username string `json:"username" db:"username"`
|
||||
Email string `json:"email" db:"email"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Handle string `json:"handle" db:"handle"`
|
||||
SatosaID string `json:"-" db:"satosa_id"`
|
||||
Meta types.JSONText `json:"-" db:"meta"`
|
||||
|
||||
OrganisationID uint64 `json:"organisationID,string" db:"rel_organisation"`
|
||||
UserID uint64 `json:"userID,string" db:"rel_user_id"`
|
||||
User *User `json:"user" db:"-"`
|
||||
|
||||
Password []byte `json:"-" db:"password"`
|
||||
|
||||
CreatedAt time.Time `json:"createdAt,omitempty" db:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updatedAt,omitempty" db:"updated_at"`
|
||||
|
||||
Reference in New Issue
Block a user