mirror of
https://github.com/netbirdio/netbird.git
synced 2025-03-11 05:08:12 +01:00
Add Account HTTP API (#691)
Extend HTTP API with Account endpoints to configure global peer login expiration. GET /api/accounts PUT /api/account/{id}/ The GET endpoint returns an array of accounts with always one account in the list. No exceptions. The PUT endpoint updates account settings: PeerLoginExpiration and PeerLoginExpirationEnabled. PeerLoginExpiration is a duration in seconds after which peers' logins will expire.
This commit is contained in:
parent
d31219ba89
commit
fe63a64b6e
@ -97,6 +97,7 @@ type AccountManager interface {
|
||||
SaveDNSSettings(accountID string, userID string, dnsSettingsToSave *DNSSettings) error
|
||||
GetPeer(accountID, peerID, userID string) (*Peer, error)
|
||||
UpdatePeerLastLogin(peerID string) error
|
||||
UpdateAccountSettings(accountID, userID string, newSettings *Settings) (*Account, error)
|
||||
}
|
||||
|
||||
type DefaultAccountManager struct {
|
||||
@ -315,6 +316,12 @@ func (a *Account) GetPeers() []*Peer {
|
||||
return peers
|
||||
}
|
||||
|
||||
// UpdateSettings saves new account settings
|
||||
func (a *Account) UpdateSettings(update *Settings) *Account {
|
||||
a.Settings = update.Copy()
|
||||
return a
|
||||
}
|
||||
|
||||
// UpdatePeer saves new or replaces existing peer
|
||||
func (a *Account) UpdatePeer(update *Peer) {
|
||||
a.Peers[update.ID] = update
|
||||
@ -596,6 +603,61 @@ func BuildManager(store Store, peersUpdateManager *PeersUpdateManager, idpManage
|
||||
return am, nil
|
||||
}
|
||||
|
||||
// UpdateAccountSettings updates Account settings.
|
||||
// Only users with role UserRoleAdmin can update the account.
|
||||
// User that performs the update has to belong to the account.
|
||||
// Returns an updated Account
|
||||
func (am *DefaultAccountManager) UpdateAccountSettings(accountID, userID string, newSettings *Settings) (*Account, error) {
|
||||
|
||||
halfYearLimit := 180 * 24 * time.Hour
|
||||
if newSettings.PeerLoginExpiration > halfYearLimit {
|
||||
return nil, status.Errorf(status.InvalidArgument, "peer login expiration can't be larger than 180 days")
|
||||
}
|
||||
|
||||
if newSettings.PeerLoginExpiration < time.Hour {
|
||||
return nil, status.Errorf(status.InvalidArgument, "peer login expiration can't be smaller than one hour")
|
||||
}
|
||||
|
||||
unlock := am.Store.AcquireAccountLock(accountID)
|
||||
defer unlock()
|
||||
|
||||
account, err := am.Store.GetAccountByUser(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user, err := account.FindUser(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !user.IsAdmin() {
|
||||
return nil, status.Errorf(status.PermissionDenied, "user is not allowed to update account")
|
||||
}
|
||||
|
||||
oldSettings := account.Settings
|
||||
if oldSettings.PeerLoginExpirationEnabled != newSettings.PeerLoginExpirationEnabled {
|
||||
event := activity.AccountPeerLoginExpirationEnabled
|
||||
if !newSettings.PeerLoginExpirationEnabled {
|
||||
event = activity.AccountPeerLoginExpirationDisabled
|
||||
}
|
||||
am.storeEvent(userID, accountID, accountID, event, nil)
|
||||
}
|
||||
|
||||
if oldSettings.PeerLoginExpiration != newSettings.PeerLoginExpiration {
|
||||
am.storeEvent(userID, accountID, accountID, activity.AccountPeerLoginExpirationDurationUpdated, nil)
|
||||
}
|
||||
|
||||
updatedAccount := account.UpdateSettings(newSettings)
|
||||
|
||||
err = am.Store.SaveAccount(account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return updatedAccount, nil
|
||||
}
|
||||
|
||||
// newAccount creates a new Account with a generated ID and generated default setup keys.
|
||||
// If ID is already in use (due to collision) we try one more time before returning error
|
||||
func (am *DefaultAccountManager) newAccount(userID, domain string) (*Account, error) {
|
||||
|
@ -1283,6 +1283,48 @@ func hasNilField(x interface{}) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func TestDefaultAccountManager_DefaultAccountSettings(t *testing.T) {
|
||||
manager, err := createManager(t)
|
||||
require.NoError(t, err, "unable to create account manager")
|
||||
|
||||
account, err := manager.GetAccountByUserOrAccountID(userID, "", "")
|
||||
require.NoError(t, err, "unable to create an account")
|
||||
|
||||
assert.NotNil(t, account.Settings)
|
||||
assert.Equal(t, account.Settings.PeerLoginExpirationEnabled, true)
|
||||
assert.Equal(t, account.Settings.PeerLoginExpiration, 24*time.Hour)
|
||||
}
|
||||
|
||||
func TestDefaultAccountManager_UpdateAccountSettings(t *testing.T) {
|
||||
manager, err := createManager(t)
|
||||
require.NoError(t, err, "unable to create account manager")
|
||||
|
||||
account, err := manager.GetAccountByUserOrAccountID(userID, "", "")
|
||||
require.NoError(t, err, "unable to create an account")
|
||||
|
||||
updated, err := manager.UpdateAccountSettings(account.Id, userID, &Settings{
|
||||
PeerLoginExpiration: time.Hour,
|
||||
PeerLoginExpirationEnabled: false})
|
||||
require.NoError(t, err, "expecting to update account settings successfully but got error")
|
||||
assert.False(t, updated.Settings.PeerLoginExpirationEnabled)
|
||||
assert.Equal(t, updated.Settings.PeerLoginExpiration, time.Hour)
|
||||
|
||||
account, err = manager.GetAccountByUserOrAccountID("", account.Id, "")
|
||||
require.NoError(t, err, "unable to get account by ID")
|
||||
|
||||
assert.False(t, account.Settings.PeerLoginExpirationEnabled)
|
||||
assert.Equal(t, account.Settings.PeerLoginExpiration, time.Hour)
|
||||
|
||||
_, err = manager.UpdateAccountSettings(account.Id, userID, &Settings{
|
||||
PeerLoginExpiration: time.Second,
|
||||
PeerLoginExpirationEnabled: false})
|
||||
require.Error(t, err, "expecting to fail when providing PeerLoginExpiration less than one hour")
|
||||
|
||||
_, err = manager.UpdateAccountSettings(account.Id, userID, &Settings{
|
||||
PeerLoginExpiration: time.Hour * 24 * 181,
|
||||
PeerLoginExpirationEnabled: false})
|
||||
require.Error(t, err, "expecting to fail when providing PeerLoginExpiration more than 180 days")
|
||||
}
|
||||
|
||||
func createManager(t *testing.T) (*DefaultAccountManager, error) {
|
||||
store, err := createStore(t)
|
||||
|
@ -71,6 +71,12 @@ const (
|
||||
NameserverGroupDeleted
|
||||
// NameserverGroupUpdated indicates that a user updated a nameservers group
|
||||
NameserverGroupUpdated
|
||||
// AccountPeerLoginExpirationEnabled indicates that a user enabled peer login expiration for the account
|
||||
AccountPeerLoginExpirationEnabled
|
||||
// AccountPeerLoginExpirationDisabled indicates that a user disabled peer login expiration for the account
|
||||
AccountPeerLoginExpirationDisabled
|
||||
// AccountPeerLoginExpirationDurationUpdated indicates that a user updated peer login expiration duration for the account
|
||||
AccountPeerLoginExpirationDurationUpdated
|
||||
)
|
||||
|
||||
const (
|
||||
@ -144,6 +150,12 @@ const (
|
||||
NameserverGroupDeletedMessage string = "Nameserver group deleted"
|
||||
// NameserverGroupUpdatedMessage is a human-readable text message of the NameserverGroupUpdated activity
|
||||
NameserverGroupUpdatedMessage string = "Nameserver group updated"
|
||||
// AccountPeerLoginExpirationEnabledMessage is a human-readable text message of the AccountPeerLoginExpirationEnabled activity
|
||||
AccountPeerLoginExpirationEnabledMessage string = "Peer login expiration enabled for the account"
|
||||
// AccountPeerLoginExpirationDisabledMessage is a human-readable text message of the AccountPeerLoginExpirationDisabled activity
|
||||
AccountPeerLoginExpirationDisabledMessage string = "Peer login expiration disabled for the account"
|
||||
// AccountPeerLoginExpirationDurationUpdatedMessage is a human-readable text message of the AccountPeerLoginExpirationDurationUpdated activity
|
||||
AccountPeerLoginExpirationDurationUpdatedMessage string = "Peer login expiration duration updated"
|
||||
)
|
||||
|
||||
// Activity that triggered an Event
|
||||
@ -222,6 +234,12 @@ func (a Activity) Message() string {
|
||||
return NameserverGroupDeletedMessage
|
||||
case NameserverGroupUpdated:
|
||||
return NameserverGroupUpdatedMessage
|
||||
case AccountPeerLoginExpirationEnabled:
|
||||
return AccountPeerLoginExpirationEnabledMessage
|
||||
case AccountPeerLoginExpirationDisabled:
|
||||
return AccountPeerLoginExpirationDisabledMessage
|
||||
case AccountPeerLoginExpirationDurationUpdated:
|
||||
return AccountPeerLoginExpirationDurationUpdatedMessage
|
||||
default:
|
||||
return "UNKNOWN_ACTIVITY"
|
||||
}
|
||||
@ -300,6 +318,12 @@ func (a Activity) StringCode() string {
|
||||
return "nameserver.group.delete"
|
||||
case NameserverGroupUpdated:
|
||||
return "nameserver.group.update"
|
||||
case AccountPeerLoginExpirationDurationUpdated:
|
||||
return "account.settings.peer.login.expiration.update"
|
||||
case AccountPeerLoginExpirationEnabled:
|
||||
return "account.setting.peer.login.expiration.enable"
|
||||
case AccountPeerLoginExpirationDisabled:
|
||||
return "account.setting.peer.login.expiration.disable"
|
||||
default:
|
||||
return "UNKNOWN_ACTIVITY"
|
||||
}
|
||||
|
96
management/server/http/accounts.go
Normal file
96
management/server/http/accounts.go
Normal file
@ -0,0 +1,96 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/http/util"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Accounts is a handler that handles the server.Account HTTP endpoints
|
||||
type Accounts struct {
|
||||
accountManager server.AccountManager
|
||||
claimsExtractor *jwtclaims.ClaimsExtractor
|
||||
}
|
||||
|
||||
// NewAccounts creates a new Accounts HTTP handler
|
||||
func NewAccounts(accountManager server.AccountManager, authCfg AuthCfg) *Accounts {
|
||||
return &Accounts{
|
||||
accountManager: accountManager,
|
||||
claimsExtractor: jwtclaims.NewClaimsExtractor(
|
||||
jwtclaims.WithAudience(authCfg.Audience),
|
||||
jwtclaims.WithUserIDClaim(authCfg.UserIDClaim),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// GetAccountsHandler is HTTP GET handler that returns a list of accounts. Effectively returns just a single account.
|
||||
func (h *Accounts) GetAccountsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
claims := h.claimsExtractor.FromRequestContext(r)
|
||||
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
if !user.IsAdmin() {
|
||||
util.WriteError(status.Errorf(status.PermissionDenied, "the user has no permission to access account data"), w)
|
||||
return
|
||||
}
|
||||
|
||||
resp := toAccountResponse(account)
|
||||
util.WriteJSONObject(w, []*api.Account{resp})
|
||||
}
|
||||
|
||||
// UpdateAccountHandler is HTTP PUT handler that updates the provided account. Updates only account settings (server.Settings)
|
||||
func (h *Accounts) UpdateAccountHandler(w http.ResponseWriter, r *http.Request) {
|
||||
claims := h.claimsExtractor.FromRequestContext(r)
|
||||
_, user, err := h.accountManager.GetAccountFromToken(claims)
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
accountID := vars["id"]
|
||||
if len(accountID) == 0 {
|
||||
util.WriteError(status.Errorf(status.InvalidArgument, "invalid accountID ID"), w)
|
||||
return
|
||||
}
|
||||
|
||||
var req api.PutApiAccountsIdJSONBody
|
||||
err = json.NewDecoder(r.Body).Decode(&req)
|
||||
if err != nil {
|
||||
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
|
||||
return
|
||||
}
|
||||
|
||||
updatedAccount, err := h.accountManager.UpdateAccountSettings(accountID, user.Id, &server.Settings{
|
||||
PeerLoginExpirationEnabled: req.Settings.PeerLoginExpirationEnabled,
|
||||
PeerLoginExpiration: time.Duration(float64(time.Second.Nanoseconds()) * float64(req.Settings.PeerLoginExpiration)),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
util.WriteError(err, w)
|
||||
return
|
||||
}
|
||||
|
||||
resp := toAccountResponse(updatedAccount)
|
||||
|
||||
util.WriteJSONObject(w, &resp)
|
||||
}
|
||||
|
||||
func toAccountResponse(account *server.Account) *api.Account {
|
||||
return &api.Account{
|
||||
Id: account.Id,
|
||||
Settings: api.AccountSettings{
|
||||
PeerLoginExpiration: int(account.Settings.PeerLoginExpiration.Seconds()),
|
||||
PeerLoginExpirationEnabled: account.Settings.PeerLoginExpirationEnabled,
|
||||
},
|
||||
}
|
||||
}
|
181
management/server/http/accounts_test.go
Normal file
181
management/server/http/accounts_test.go
Normal file
@ -0,0 +1,181 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/netbirdio/netbird/management/server"
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/status"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func initAccountsTestData(account *server.Account, admin *server.User) *Accounts {
|
||||
return &Accounts{
|
||||
accountManager: &mock_server.MockAccountManager{
|
||||
GetAccountFromTokenFunc: func(claims jwtclaims.AuthorizationClaims) (*server.Account, *server.User, error) {
|
||||
return account, admin, nil
|
||||
},
|
||||
UpdateAccountSettingsFunc: func(accountID, userID string, newSettings *server.Settings) (*server.Account, error) {
|
||||
halfYearLimit := 180 * 24 * time.Hour
|
||||
if newSettings.PeerLoginExpiration > halfYearLimit {
|
||||
return nil, status.Errorf(status.InvalidArgument, "peer login expiration can't be larger than 180 days")
|
||||
}
|
||||
|
||||
if newSettings.PeerLoginExpiration < time.Hour {
|
||||
return nil, status.Errorf(status.InvalidArgument, "peer login expiration can't be smaller than one hour")
|
||||
}
|
||||
|
||||
accCopy := account.Copy()
|
||||
accCopy.UpdateSettings(newSettings)
|
||||
return accCopy, nil
|
||||
|
||||
},
|
||||
},
|
||||
claimsExtractor: jwtclaims.NewClaimsExtractor(
|
||||
jwtclaims.WithFromRequestContext(func(r *http.Request) jwtclaims.AuthorizationClaims {
|
||||
return jwtclaims.AuthorizationClaims{
|
||||
UserId: "test_user",
|
||||
Domain: "hotmail.com",
|
||||
AccountId: "test_account",
|
||||
}
|
||||
}),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccounts_AccountsHandler(t *testing.T) {
|
||||
|
||||
accountID := "test_account"
|
||||
adminUser := server.NewAdminUser("test_user")
|
||||
|
||||
handler := initAccountsTestData(&server.Account{
|
||||
Id: accountID,
|
||||
Domain: "hotmail.com",
|
||||
Network: server.NewNetwork(),
|
||||
Users: map[string]*server.User{
|
||||
adminUser.Id: adminUser,
|
||||
},
|
||||
Settings: &server.Settings{
|
||||
PeerLoginExpirationEnabled: false,
|
||||
PeerLoginExpiration: time.Hour,
|
||||
},
|
||||
}, adminUser)
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
expectedStatus int
|
||||
expectedBody bool
|
||||
expectedID string
|
||||
expectedArray bool
|
||||
expectedSettings api.AccountSettings
|
||||
requestType string
|
||||
requestPath string
|
||||
requestBody io.Reader
|
||||
}{
|
||||
{
|
||||
name: "GetAccounts OK",
|
||||
expectedBody: true,
|
||||
requestType: http.MethodGet,
|
||||
requestPath: "/api/accounts",
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedSettings: api.AccountSettings{
|
||||
PeerLoginExpiration: int(time.Hour.Seconds()),
|
||||
PeerLoginExpirationEnabled: false,
|
||||
},
|
||||
expectedArray: true,
|
||||
expectedID: accountID,
|
||||
},
|
||||
{
|
||||
name: "PutAccount OK",
|
||||
expectedBody: true,
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/accounts/" + accountID,
|
||||
requestBody: bytes.NewBufferString("{\"settings\": {\"peer_login_expiration\": 15552000,\"peer_login_expiration_enabled\": true}}"),
|
||||
expectedStatus: http.StatusOK,
|
||||
expectedSettings: api.AccountSettings{
|
||||
PeerLoginExpiration: 15552000,
|
||||
PeerLoginExpirationEnabled: true,
|
||||
},
|
||||
expectedArray: false,
|
||||
expectedID: accountID,
|
||||
},
|
||||
{
|
||||
name: "Update account failure with high peer_login_expiration more than 180 days",
|
||||
expectedBody: true,
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/accounts/" + accountID,
|
||||
requestBody: bytes.NewBufferString("{\"settings\": {\"peer_login_expiration\": 15552001,\"peer_login_expiration_enabled\": true}}"),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedArray: false,
|
||||
},
|
||||
{
|
||||
name: "Update account failure with peer_login_expiration less than an hour",
|
||||
expectedBody: true,
|
||||
requestType: http.MethodPut,
|
||||
requestPath: "/api/accounts/" + accountID,
|
||||
requestBody: bytes.NewBufferString("{\"settings\": {\"peer_login_expiration\": 3599,\"peer_login_expiration_enabled\": true}}"),
|
||||
expectedStatus: http.StatusUnprocessableEntity,
|
||||
expectedArray: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(tc.requestType, tc.requestPath, tc.requestBody)
|
||||
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/api/accounts", handler.GetAccountsHandler).Methods("GET")
|
||||
router.HandleFunc("/api/accounts/{id}", handler.UpdateAccountHandler).Methods("PUT")
|
||||
router.ServeHTTP(recorder, req)
|
||||
|
||||
res := recorder.Result()
|
||||
defer res.Body.Close()
|
||||
|
||||
if status := recorder.Code; status != tc.expectedStatus {
|
||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
||||
status, tc.expectedStatus)
|
||||
return
|
||||
}
|
||||
|
||||
if tc.expectedStatus != http.StatusOK {
|
||||
return
|
||||
}
|
||||
|
||||
if !tc.expectedBody {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("I don't know what I expected; %v", err)
|
||||
}
|
||||
|
||||
var actual *api.Account
|
||||
if tc.expectedArray {
|
||||
var got []*api.Account
|
||||
if err = json.Unmarshal(content, &got); err != nil {
|
||||
t.Fatalf("Sent content is not in correct json format; %v", err)
|
||||
}
|
||||
|
||||
assert.Len(t, got, 1)
|
||||
actual = got[0]
|
||||
} else {
|
||||
if err = json.Unmarshal(content, &actual); err != nil {
|
||||
t.Fatalf("Sent content is not in correct json format; %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.expectedID, actual.Id)
|
||||
assert.Equal(t, tc.expectedSettings, actual.Settings)
|
||||
})
|
||||
}
|
||||
}
|
@ -20,8 +20,31 @@ tags:
|
||||
description: Interact with and view information about DNS configuration.
|
||||
- name: Events
|
||||
description: View information about the account and network events.
|
||||
- name: Accounts
|
||||
description: View information about the accounts.
|
||||
components:
|
||||
schemas:
|
||||
Account:
|
||||
properties:
|
||||
id:
|
||||
description: Account ID
|
||||
type: string
|
||||
settings:
|
||||
$ref: '#/components/schemas/AccountSettings'
|
||||
required:
|
||||
- id
|
||||
- settings
|
||||
AccountSettings:
|
||||
properties:
|
||||
peer_login_expiration_enabled:
|
||||
description: Enables or disables peer login expiration globally. After peer's login has expired the user has to log in (authenticate). Applies only to peers that were added by a user (interactive SSO login).
|
||||
type: boolean
|
||||
peer_login_expiration:
|
||||
description: Period of time after which peer login expires (seconds).
|
||||
type: integer
|
||||
required:
|
||||
- peer_login_expiration_enabled
|
||||
- peer_login_expiration
|
||||
User:
|
||||
type: object
|
||||
properties:
|
||||
@ -606,6 +629,68 @@ components:
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
paths:
|
||||
/api/accounts:
|
||||
get:
|
||||
summary: Returns a list of accounts of a user. Always returns a list of one account. Only available for admin users.
|
||||
tags: [ Accounts ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
responses:
|
||||
'200':
|
||||
description: A JSON array of accounts
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Account'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/accounts/{id}:
|
||||
put:
|
||||
summary: Update information about an account
|
||||
tags: [ Accounts ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The Account ID
|
||||
requestBody:
|
||||
description: update an account
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
settings:
|
||||
$ref: '#/components/schemas/AccountSettings'
|
||||
required:
|
||||
- settings
|
||||
responses:
|
||||
'200':
|
||||
description: An Account object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Account'
|
||||
'400':
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/users:
|
||||
get:
|
||||
summary: Returns a list of all users
|
||||
|
@ -134,6 +134,22 @@ const (
|
||||
UserStatusInvited UserStatus = "invited"
|
||||
)
|
||||
|
||||
// Account defines model for Account.
|
||||
type Account struct {
|
||||
// Id Account ID
|
||||
Id string `json:"id"`
|
||||
Settings AccountSettings `json:"settings"`
|
||||
}
|
||||
|
||||
// AccountSettings defines model for AccountSettings.
|
||||
type AccountSettings struct {
|
||||
// PeerLoginExpiration Period of time after which peer login expires (seconds).
|
||||
PeerLoginExpiration int `json:"peer_login_expiration"`
|
||||
|
||||
// PeerLoginExpirationEnabled Enables or disables peer login expiration globally. After peer's login has expired the user has to log in (authenticate). Applies only to peers that were added by a user (interactive SSO login).
|
||||
PeerLoginExpirationEnabled bool `json:"peer_login_expiration_enabled"`
|
||||
}
|
||||
|
||||
// DNSSettings defines model for DNSSettings.
|
||||
type DNSSettings struct {
|
||||
// DisabledManagementGroups Groups whose DNS management is disabled
|
||||
@ -617,6 +633,11 @@ type UserRequest struct {
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
// PutApiAccountsIdJSONBody defines parameters for PutApiAccountsId.
|
||||
type PutApiAccountsIdJSONBody struct {
|
||||
Settings AccountSettings `json:"settings"`
|
||||
}
|
||||
|
||||
// PatchApiDnsNameserversIdJSONBody defines parameters for PatchApiDnsNameserversId.
|
||||
type PatchApiDnsNameserversIdJSONBody = []NameserverGroupPatchOperation
|
||||
|
||||
@ -682,6 +703,9 @@ type PutApiRulesIdJSONBody struct {
|
||||
Sources *[]string `json:"sources,omitempty"`
|
||||
}
|
||||
|
||||
// PutApiAccountsIdJSONRequestBody defines body for PutApiAccountsId for application/json ContentType.
|
||||
type PutApiAccountsIdJSONRequestBody PutApiAccountsIdJSONBody
|
||||
|
||||
// PostApiDnsNameserversJSONRequestBody defines body for PostApiDnsNameservers for application/json ContentType.
|
||||
type PostApiDnsNameserversJSONRequestBody = NameserverGroupRequest
|
||||
|
||||
|
@ -50,6 +50,10 @@ func APIHandler(accountManager s.AccountManager, appMetrics telemetry.AppMetrics
|
||||
nameserversHandler := NewNameservers(accountManager, authCfg)
|
||||
eventsHandler := NewEvents(accountManager, authCfg)
|
||||
dnsSettingsHandler := NewDNSSettings(accountManager, authCfg)
|
||||
accountsHandler := NewAccounts(accountManager, authCfg)
|
||||
|
||||
apiHandler.HandleFunc("/accounts/{id}", accountsHandler.UpdateAccountHandler).Methods("PUT", "OPTIONS")
|
||||
apiHandler.HandleFunc("/accounts", accountsHandler.GetAccountsHandler).Methods("GET", "OPTIONS")
|
||||
|
||||
apiHandler.HandleFunc("/peers", peersHandler.GetPeers).Methods("GET", "OPTIONS")
|
||||
apiHandler.HandleFunc("/peers/{id}", peersHandler.HandlePeer).
|
||||
|
@ -70,6 +70,7 @@ type MockAccountManager struct {
|
||||
GetPeerFunc func(accountID, peerID, userID string) (*server.Peer, error)
|
||||
GetAccountByPeerIDFunc func(peerID string) (*server.Account, error)
|
||||
UpdatePeerLastLoginFunc func(peerID string) error
|
||||
UpdateAccountSettingsFunc func(accountID, userID string, newSettings *server.Settings) (*server.Account, error)
|
||||
}
|
||||
|
||||
// GetUsersFromAccount mock implementation of GetUsersFromAccount from server.AccountManager interface
|
||||
@ -553,3 +554,11 @@ func (am *MockAccountManager) UpdatePeerLastLogin(peerID string) error {
|
||||
}
|
||||
return status.Errorf(codes.Unimplemented, "method UpdatePeerLastLogin is not implemented")
|
||||
}
|
||||
|
||||
// UpdateAccountSettings mocks UpdateAccountSettings of the AccountManager interface
|
||||
func (am *MockAccountManager) UpdateAccountSettings(accountID, userID string, newSettings *server.Settings) (*server.Account, error) {
|
||||
if am.UpdateAccountSettingsFunc != nil {
|
||||
return am.UpdateAccountSettingsFunc(accountID, userID, newSettings)
|
||||
}
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateAccountSettings is not implemented")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user