add(system): implement additional user apis

This commit is contained in:
Tit Petric
2018-11-25 11:01:42 +01:00
parent e7ea318f17
commit d0233e3377
11 changed files with 993 additions and 29 deletions
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
View File
@@ -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
View File
@@ -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"
}
]
}
}
]
}
+197 -3
View File
@@ -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"
}
]
}
}
]
}
+1
View File
@@ -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
+66 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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)
}
+16
View File
@@ -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
View File
@@ -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"`