mirror of
https://github.com/jeremyd/ergo.git
synced 2026-08-07 14:33:04 -07:00
add saget and saset to API (#2421)
This commit is contained in:
committed by
GitHub
parent
84eb71f72f
commit
7007c2c787
+32
@@ -136,6 +136,38 @@ The response is a JSON object with fields:
|
||||
* `success`: whether the password change succeeded
|
||||
* `errorCode`: string, optional, machine-readable description of the error. Possible values include: `ACCOUNT_DOES_NOT_EXIST`, `INVALID_PASSPHRASE`, `CREDENTIALS_EXTERNALLY_MANAGED`, `UNKNOWN_ERROR`.
|
||||
|
||||
`/v1/ns/saget`
|
||||
--------------
|
||||
|
||||
This endpoint retrieves account settings associated with an existing NickServ account. The request is a JSON object with fields:
|
||||
|
||||
* `accountName`: string, name of the account
|
||||
|
||||
The response is a JSON object with fields:
|
||||
|
||||
* `success`: boolean, whether the request succeeded
|
||||
* `errorCode`: string, optional, machine-readable description of the error if `success` is false. Possible values: `INVALID_REQUEST`, `ACCOUNT_DOES_NOT_EXIST`, `ACCOUNT_UNVERIFIED`, `UNKNOWN_ERROR`. If `success` is false, the remaining fields are omitted.
|
||||
* `error`: string, optional, human-readable description of the failure if `success` is false and `errorCode` is `UNKNOWN_ERROR`
|
||||
* `alwaysOn`, string, whether the user is always-on (`default`, `off`, or `on`)
|
||||
* `autoAway`, string, whether to automatically set an always-on user as away when no client sessions are connected (`default`, `off`, or `on`)
|
||||
* `email`, string, email address associated with the account
|
||||
* `replayJoins`, string, whether to replay events like JOIN as PRIVMSGs from HistServ to legacy clients (`commands-only` or `on`)
|
||||
|
||||
`/v1/ns/saset`
|
||||
--------------
|
||||
|
||||
This endpoint modifies account settings associated with an existing NickServ account. The request is a JSON object with fields:
|
||||
|
||||
* `accountName`: string, name of the account
|
||||
* `alwaysOn`, string, optional, whether the user is always-on (`default`, `off`, or `on`)
|
||||
* `autoAway`, string, optional, whether to automatically set an always-on user as away when no client sessions are connected (`default`, `off`, or `on`)
|
||||
* `email`, string, optional, email address associated with the account
|
||||
* `replayJoins`, string, optional, whether to replay events like JOIN as PRIVMSGs from HistServ to legacy clients (`commands-only` or `on`)
|
||||
|
||||
Omitted fields are not updated (i.e. PATCH semantics).
|
||||
|
||||
The response format is the same as `/v1/ns/saget`.
|
||||
|
||||
`/v1/ns/saregister`
|
||||
-------------------
|
||||
|
||||
|
||||
+202
@@ -40,6 +40,8 @@ func newAPIHandler(server *Server) http.Handler {
|
||||
api.mux.HandleFunc("POST /v1/ns/list", api.handleAccountList)
|
||||
api.mux.HandleFunc("POST /v1/ns/passwd", api.handleNsPasswd)
|
||||
api.mux.HandleFunc("POST /v1/ns/saregister", api.handleSaregister)
|
||||
api.mux.HandleFunc("POST /v1/ns/saget", api.handleNsSaget)
|
||||
api.mux.HandleFunc("POST /v1/ns/saset", api.handleNsSaset)
|
||||
|
||||
return api
|
||||
}
|
||||
@@ -248,6 +250,206 @@ func (a *ergoAPI) handleNsPasswd(w http.ResponseWriter, r *http.Request) {
|
||||
a.writeJSONResponse(response, w, r)
|
||||
}
|
||||
|
||||
// convert to/from the "default"/"off"/"on" vocabulary used by the
|
||||
// /v1/ns/saget and /v1/ns/saset API endpoints
|
||||
func apiPersistentStatusToString(status PersistentStatus) string {
|
||||
switch status {
|
||||
case PersistentDisabled:
|
||||
return "off"
|
||||
case PersistentMandatory:
|
||||
return "on"
|
||||
default:
|
||||
return "default"
|
||||
}
|
||||
}
|
||||
|
||||
func apiPersistentStatusFromString(status string) (PersistentStatus, error) {
|
||||
switch strings.ToLower(status) {
|
||||
case "default":
|
||||
return PersistentUnspecified, nil
|
||||
case "off":
|
||||
return PersistentDisabled, nil
|
||||
case "on":
|
||||
return PersistentMandatory, nil
|
||||
default:
|
||||
return PersistentUnspecified, errInvalidParams
|
||||
}
|
||||
}
|
||||
|
||||
// convert to/from the "commands-only"/"on" vocabulary used by the
|
||||
// /v1/ns/saget and /v1/ns/saset API endpoints
|
||||
func apiReplayJoinsToString(status ReplayJoinsSetting) string {
|
||||
switch status {
|
||||
case ReplayJoinsAlways:
|
||||
return "on"
|
||||
default:
|
||||
return "commands-only"
|
||||
}
|
||||
}
|
||||
|
||||
func apiReplayJoinsFromString(status string) (ReplayJoinsSetting, error) {
|
||||
switch strings.ToLower(status) {
|
||||
case "commands-only":
|
||||
return ReplayJoinsCommandsOnly, nil
|
||||
case "on":
|
||||
return ReplayJoinsAlways, nil
|
||||
default:
|
||||
return ReplayJoinsCommandsOnly, errInvalidParams
|
||||
}
|
||||
}
|
||||
|
||||
type apiAccountSettingsRequest struct {
|
||||
AccountName string `json:"accountName"`
|
||||
}
|
||||
|
||||
type apiAccountSettingsResponse struct {
|
||||
apiGenericResponse
|
||||
AlwaysOn string `json:"alwaysOn,omitempty"`
|
||||
AutoAway string `json:"autoAway,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
ReplayJoins string `json:"replayJoins,omitempty"`
|
||||
}
|
||||
|
||||
// accountSettingsErrorCode maps an error from loading or modifying account
|
||||
// settings to the machine-readable errorCode conventions shared by
|
||||
// /v1/ns/saget and /v1/ns/saset.
|
||||
func accountSettingsErrorCode(err error) string {
|
||||
switch err {
|
||||
case errAccountDoesNotExist:
|
||||
return "ACCOUNT_DOES_NOT_EXIST"
|
||||
case errAccountUnverified:
|
||||
return "ACCOUNT_UNVERIFIED"
|
||||
default:
|
||||
return "UNKNOWN_ERROR"
|
||||
}
|
||||
}
|
||||
|
||||
func accountSettingsErrorResponse(err error) apiAccountSettingsResponse {
|
||||
response := apiAccountSettingsResponse{
|
||||
apiGenericResponse: apiGenericResponse{Success: false, ErrorCode: accountSettingsErrorCode(err)},
|
||||
}
|
||||
if response.ErrorCode == "UNKNOWN_ERROR" {
|
||||
response.Error = err.Error()
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
// loadVerifiedAccount loads an account and checks that it exists and is
|
||||
// verified, returning the appropriate sentinel error otherwise.
|
||||
func (a *ergoAPI) loadVerifiedAccount(accountName string) (accountData ClientAccount, err error) {
|
||||
accountData, err = a.server.accounts.LoadAccount(accountName)
|
||||
if err == nil && !accountData.Verified {
|
||||
err = errAccountUnverified
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *ergoAPI) accountSettingsResponse(accountName string) apiAccountSettingsResponse {
|
||||
accountData, err := a.loadVerifiedAccount(accountName)
|
||||
if err != nil {
|
||||
return accountSettingsErrorResponse(err)
|
||||
}
|
||||
|
||||
settings := accountData.Settings
|
||||
return apiAccountSettingsResponse{
|
||||
apiGenericResponse: apiGenericResponse{Success: true},
|
||||
AlwaysOn: apiPersistentStatusToString(settings.AlwaysOn),
|
||||
AutoAway: apiPersistentStatusToString(settings.AutoAway),
|
||||
Email: settings.Email,
|
||||
ReplayJoins: apiReplayJoinsToString(settings.ReplayJoins),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *ergoAPI) handleNsSaget(w http.ResponseWriter, r *http.Request) {
|
||||
var request apiAccountSettingsRequest
|
||||
if err := a.decodeJSONRequest(&request, w, r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if request.AccountName == "" {
|
||||
a.writeJSONResponse(apiAccountSettingsResponse{
|
||||
apiGenericResponse: apiGenericResponse{Success: false, ErrorCode: "INVALID_REQUEST"},
|
||||
}, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
a.writeJSONResponse(a.accountSettingsResponse(request.AccountName), w, r)
|
||||
}
|
||||
|
||||
type apiNsSasetRequest struct {
|
||||
AccountName string `json:"accountName"`
|
||||
AlwaysOn *string `json:"alwaysOn"`
|
||||
AutoAway *string `json:"autoAway"`
|
||||
Email *string `json:"email"`
|
||||
ReplayJoins *string `json:"replayJoins"`
|
||||
}
|
||||
|
||||
func (a *ergoAPI) handleNsSaset(w http.ResponseWriter, r *http.Request) {
|
||||
var request apiNsSasetRequest
|
||||
if err := a.decodeJSONRequest(&request, w, r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if request.AccountName == "" {
|
||||
a.writeJSONResponse(apiAccountSettingsResponse{
|
||||
apiGenericResponse: apiGenericResponse{Success: false, ErrorCode: "INVALID_REQUEST"},
|
||||
}, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
var alwaysOn, autoAway PersistentStatus
|
||||
var replayJoins ReplayJoinsSetting
|
||||
var err error
|
||||
if request.AlwaysOn != nil {
|
||||
if alwaysOn, err = apiPersistentStatusFromString(*request.AlwaysOn); err != nil {
|
||||
a.writeJSONResponse(apiAccountSettingsResponse{
|
||||
apiGenericResponse: apiGenericResponse{Success: false, ErrorCode: "INVALID_REQUEST"},
|
||||
}, w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
if request.AutoAway != nil {
|
||||
if autoAway, err = apiPersistentStatusFromString(*request.AutoAway); err != nil {
|
||||
a.writeJSONResponse(apiAccountSettingsResponse{
|
||||
apiGenericResponse: apiGenericResponse{Success: false, ErrorCode: "INVALID_REQUEST"},
|
||||
}, w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
if request.ReplayJoins != nil {
|
||||
if replayJoins, err = apiReplayJoinsFromString(*request.ReplayJoins); err != nil {
|
||||
a.writeJSONResponse(apiAccountSettingsResponse{
|
||||
apiGenericResponse: apiGenericResponse{Success: false, ErrorCode: "INVALID_REQUEST"},
|
||||
}, w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
munger := func(in AccountSettings) (out AccountSettings, err error) {
|
||||
out = in
|
||||
if request.AlwaysOn != nil {
|
||||
out.AlwaysOn = alwaysOn
|
||||
}
|
||||
if request.AutoAway != nil {
|
||||
out.AutoAway = autoAway
|
||||
}
|
||||
if request.Email != nil {
|
||||
out.Email = *request.Email
|
||||
}
|
||||
if request.ReplayJoins != nil {
|
||||
out.ReplayJoins = replayJoins
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := a.server.accounts.ModifyAccountSettings(request.AccountName, munger); err != nil {
|
||||
a.writeJSONResponse(accountSettingsErrorResponse(err), w, r)
|
||||
return
|
||||
}
|
||||
|
||||
a.writeJSONResponse(a.accountSettingsResponse(request.AccountName), w, r)
|
||||
}
|
||||
|
||||
type apiAccountDetailsResponse struct {
|
||||
apiGenericResponse
|
||||
AccountName string `json:"accountName,omitempty"`
|
||||
|
||||
Reference in New Issue
Block a user