feat(api): improve authentication

master
Xeronith 2023-06-08 10:42:37 +03:30
rodzic 039dd7f665
commit 8fa38c6002
18 zmienionych plików z 590 dodań i 261 usunięć

Wyświetl plik

@ -0,0 +1,29 @@
package commands
import (
. "github.com/reiver/greatape/app/validators"
. "github.com/reiver/greatape/components/constants"
. "github.com/reiver/greatape/components/contracts"
)
func ResetPassword(x IDispatcher, usernameOrEmail string) (IResetPasswordResult, error) {
isEmail := x.MatchString(EMAIL, usernameOrEmail)
if !isEmail && !UsernameIsValid(usernameOrEmail) {
return nil, ERROR_INVALID_PARAMETERS
}
identities := x.FilterIdentities(func(identity IIdentity) bool {
if isEmail {
return identity.Email() == usernameOrEmail
} else {
return identity.Username() == usernameOrEmail
}
})
if identities.HasExactlyOneItem() {
identity := identities.First()
_ = identity
}
return x.NewResetPasswordResult(), nil
}

Wyświetl plik

@ -137,6 +137,18 @@ func TestChangePasswordApi(test *testing.T) {
}
}
func TestResetPasswordApi(test *testing.T) {
input := &ResetPasswordRequest{
UsernameOrEmail: "username_or_email",
}
if output, err := api.ResetPassword(input); err != nil {
test.Fatal(err)
} else if output == nil {
test.Fail()
}
}
func TestLogoutApi(test *testing.T) {
input := &LogoutRequest{}

Wyświetl plik

@ -15,6 +15,7 @@ func (factory *operationFactory) Operations() []IOperation {
GetProfileByUserOperation(),
UpdateProfileByUserOperation(),
ChangePasswordOperation(),
ResetPasswordOperation(),
LogoutOperation(),
WebfingerOperation(),
GetPackagesOperation(),

Wyświetl plik

@ -0,0 +1,51 @@
package operations
import (
. "github.com/reiver/greatape/components/api/protobuf"
. "github.com/reiver/greatape/components/api/services"
. "github.com/reiver/greatape/components/contracts"
. "github.com/xeronith/diamante/contracts/operation"
. "github.com/xeronith/diamante/contracts/service"
. "github.com/xeronith/diamante/contracts/system"
. "github.com/xeronith/diamante/operation"
)
type resetPasswordOperation struct {
Operation
run func(IContext, *ResetPasswordRequest) (*ResetPasswordResult, error)
}
func ResetPasswordOperation() IOperation {
return &resetPasswordOperation{
run: ResetPasswordService,
}
}
func (operation *resetPasswordOperation) Id() (ID, ID) {
return RESET_PASSWORD_REQUEST, RESET_PASSWORD_RESULT
}
func (operation *resetPasswordOperation) InputContainer() Pointer {
return new(ResetPasswordRequest)
}
func (operation *resetPasswordOperation) OutputContainer() Pointer {
return new(ResetPasswordResult)
}
func (operation *resetPasswordOperation) Execute(context IContext, payload Pointer) (Pointer, error) {
return operation.run(context, payload.(*ResetPasswordRequest))
}
/*
func (operation *resetPasswordOperation) ExecutionTimeLimits() (Duration, Duration, Duration) {
var (
TIME_LIMIT_WARNING Duration = 20_000_000
TIME_LIMIT_ALERT Duration = 35_000_000
TIME_LIMIT_CRITICAL Duration = 50_000_000
)
return TIME_LIMIT_WARNING, TIME_LIMIT_ALERT, TIME_LIMIT_CRITICAL
}
*/

Wyświetl plik

@ -114,6 +114,15 @@ message ChangePasswordRequest {
message ChangePasswordResult {
}
// API: ResetPassword
//-----------------------------------------------------------
message ResetPasswordRequest {
string usernameOrEmail = 0x00000001;
}
message ResetPasswordResult {
}
// API: Logout
//-----------------------------------------------------------
message LogoutRequest {

Wyświetl plik

@ -0,0 +1,27 @@
package services
import (
. "github.com/reiver/greatape/components/api/protobuf"
. "github.com/reiver/greatape/components/contracts"
"github.com/reiver/greatape/components/core"
. "github.com/xeronith/diamante/contracts/service"
)
// noinspection GoUnusedParameter
func ResetPasswordService(context IContext, input *ResetPasswordRequest) (result *ResetPasswordResult, err error) {
conductor := core.Conductor
conductor.LogRemoteCall(context, INITIALIZE, "reset_password", input, result, err)
defer func() { conductor.LogRemoteCall(context, FINALIZE, "reset_password", input, result, err) }()
_result, _err := conductor.ResetPassword(input.UsernameOrEmail, context.Identity())
if _err != nil {
err = _err
return nil, err
}
_ = _result
result = context.ResultContainer().(*ResetPasswordResult)
return result, nil
}

Wyświetl plik

@ -15,6 +15,7 @@ type IApi interface {
GetProfileByUser(*GetProfileByUserRequest) (*GetProfileByUserResult, error)
UpdateProfileByUser(*UpdateProfileByUserRequest) (*UpdateProfileByUserResult, error)
ChangePassword(*ChangePasswordRequest) (*ChangePasswordResult, error)
ResetPassword(*ResetPasswordRequest) (*ResetPasswordResult, error)
Logout(*LogoutRequest) (*LogoutResult, error)
Webfinger(*WebfingerRequest) (*WebfingerResult, error)
GetPackages(*GetPackagesRequest) (*GetPackagesResult, error)

Wyświetl plik

@ -40,6 +40,10 @@ const (
CHANGE_PASSWORD_REQUEST = 0x926A5565
CHANGE_PASSWORD_RESULT = 0x521E68DF
//ResetPasswordOperation
RESET_PASSWORD_REQUEST = 0xF4030036
RESET_PASSWORD_RESULT = 0x3D70F105
//LogoutOperation
LOGOUT_REQUEST = 0x447AFA34
LOGOUT_RESULT = 0x9412D17F
@ -107,6 +111,8 @@ var OPCODES = Opcodes{
0x678A8BAF: "UpdateProfileByUser",
0x926A5565: "CHANGE_PASSWORD",
0x521E68DF: "ChangePassword",
0xF4030036: "RESET_PASSWORD",
0x3D70F105: "ResetPassword",
0x447AFA34: "LOGOUT",
0x9412D17F: "Logout",
0x01FD357C: "WEBFINGER",

Wyświetl plik

@ -63,6 +63,7 @@ type (
GetProfileByUser(editor Identity) (IGetProfileByUserResult, error)
UpdateProfileByUser(displayName string, avatar string, banner string, summary string, github string, editor Identity) (IUpdateProfileByUserResult, error)
ChangePassword(currentPassword string, newPassword string, editor Identity) (IChangePasswordResult, error)
ResetPassword(usernameOrEmail string, editor Identity) (IResetPasswordResult, error)
Logout(editor Identity) (ILogoutResult, error)
Webfinger(resource string, editor Identity) (IWebfingerResult, error)
GetPackages(editor Identity) (IGetPackagesResult, error)
@ -119,6 +120,9 @@ type (
IChangePasswordResult interface {
}
IResetPasswordResult interface {
}
ILogoutResult interface {
}

Wyświetl plik

@ -265,6 +265,7 @@ type (
GetProfileByUser(editor Identity) (IGetProfileByUserResult, error)
UpdateProfileByUser(displayName string, avatar string, banner string, summary string, github string, editor Identity) (IUpdateProfileByUserResult, error)
ChangePassword(currentPassword string, newPassword string, editor Identity) (IChangePasswordResult, error)
ResetPassword(usernameOrEmail string, editor Identity) (IResetPasswordResult, error)
Logout(editor Identity) (ILogoutResult, error)
Webfinger(resource string, editor Identity) (IWebfingerResult, error)
GetPackages(editor Identity) (IGetPackagesResult, error)
@ -303,6 +304,7 @@ type (
NewGetProfileByUserResult(username string, displayName string, avatar string, banner string, summary string, github string, ignored interface{}) IGetProfileByUserResult
NewUpdateProfileByUserResult(displayName string, avatar string, banner string, summary string, github string, ignored interface{}) IUpdateProfileByUserResult
NewChangePasswordResult(ignored interface{}) IChangePasswordResult
NewResetPasswordResult(ignored interface{}) IResetPasswordResult
NewLogoutResult(ignored interface{}) ILogoutResult
NewWebfingerResult(aliases []string, links []IActivityPubLink, subject string, ignored interface{}) IWebfingerResult
NewGetPackagesResult(body []byte, ignored interface{}) IGetPackagesResult

Wyświetl plik

@ -1040,6 +1040,7 @@ type IDispatcher interface {
GetProfileByUser() (IGetProfileByUserResult, error)
UpdateProfileByUser(displayName string, avatar string, banner string, summary string, github string) (IUpdateProfileByUserResult, error)
ChangePassword(currentPassword string, newPassword string) (IChangePasswordResult, error)
ResetPassword(usernameOrEmail string) (IResetPasswordResult, error)
Logout() (ILogoutResult, error)
Webfinger(resource string) (IWebfingerResult, error)
GetPackages() (IGetPackagesResult, error)
@ -1137,6 +1138,8 @@ type IDispatcher interface {
NewUpdateProfileByUserResult(displayName string, avatar string, banner string, summary string, github string) IUpdateProfileByUserResult
// NewChangePasswordResult creates a new result container for 'Change Password' system action.
NewChangePasswordResult() IChangePasswordResult
// NewResetPasswordResult creates a new result container for 'Reset Password' system action.
NewResetPasswordResult() IResetPasswordResult
// NewLogoutResult creates a new result container for 'Logout' system action.
NewLogoutResult() ILogoutResult
// NewWebfingerResult creates a new result container for 'Webfinger' system action.

Wyświetl plik

@ -95,6 +95,16 @@ func (api *api) ChangePassword(request *ChangePasswordRequest) (*ChangePasswordR
}
}
func (api *api) ResetPassword(request *ResetPasswordRequest) (*ResetPasswordResult, error) {
result, err := api.call(RESET_PASSWORD_REQUEST, request)
if err != nil {
return nil, err
} else {
return result.(*ResetPasswordResult), nil
}
}
func (api *api) Logout(request *LogoutRequest) (*LogoutResult, error) {
result, err := api.call(LOGOUT_REQUEST, request)
@ -225,6 +235,7 @@ func init() {
API_RESULT[GET_PROFILE_BY_USER_RESULT] = GetProfileByUserResult{}
API_RESULT[UPDATE_PROFILE_BY_USER_RESULT] = UpdateProfileByUserResult{}
API_RESULT[CHANGE_PASSWORD_RESULT] = ChangePasswordResult{}
API_RESULT[RESET_PASSWORD_RESULT] = ResetPasswordResult{}
API_RESULT[LOGOUT_RESULT] = LogoutResult{}
API_RESULT[WEBFINGER_RESULT] = WebfingerResult{}
API_RESULT[GET_PACKAGES_RESULT] = GetPackagesResult{}

Wyświetl plik

@ -1126,6 +1126,10 @@ func (conductor *conductor) ChangePassword(currentPassword string, newPassword s
return conductor.spiManager.ChangePassword(currentPassword, newPassword, editor)
}
func (conductor *conductor) ResetPassword(usernameOrEmail string, editor Identity) (IResetPasswordResult, error) {
return conductor.spiManager.ResetPassword(usernameOrEmail, editor)
}
func (conductor *conductor) Logout(editor Identity) (ILogoutResult, error) {
return conductor.spiManager.Logout(editor)
}
@ -1274,6 +1278,10 @@ func (conductor *conductor) NewChangePasswordResult(_ interface{}) IChangePasswo
return NewChangePasswordResult(nil)
}
func (conductor *conductor) NewResetPasswordResult(_ interface{}) IResetPasswordResult {
return NewResetPasswordResult(nil)
}
func (conductor *conductor) NewLogoutResult(_ interface{}) ILogoutResult {
return NewLogoutResult(nil)
}

Wyświetl plik

@ -272,6 +272,10 @@ func (dispatcher *dispatcher) ChangePassword(currentPassword string, newPassword
return dispatcher.conductor.SpiManager().ChangePassword(currentPassword, newPassword, dispatcher.identity)
}
func (dispatcher *dispatcher) ResetPassword(usernameOrEmail string) (IResetPasswordResult, error) {
return dispatcher.conductor.SpiManager().ResetPassword(usernameOrEmail, dispatcher.identity)
}
func (dispatcher *dispatcher) Logout() (ILogoutResult, error) {
return dispatcher.conductor.SpiManager().Logout(dispatcher.identity)
}

Wyświetl plik

@ -580,6 +580,34 @@ func (manager *spiManager) ChangePassword(currentPassword string, newPassword st
}
}
//region IResetPasswordResult Implementation
type resetPasswordResult struct {
}
func NewResetPasswordResult(_ interface{}) IResetPasswordResult {
return &resetPasswordResult{}
}
//endregion
func (manager *spiManager) ResetPassword(usernameOrEmail string, editor Identity) (result IResetPasswordResult, err error) {
defer func() {
if reason := recover(); reason != nil {
err = manager.Error(reason)
}
}()
editor.Lock(RESET_PASSWORD_REQUEST)
defer editor.Unlock(RESET_PASSWORD_REQUEST)
if result, err = commands.ResetPassword(NewDispatcher(Conductor, editor), usernameOrEmail); err != nil {
return nil, err
} else {
return result, nil
}
}
//region ILogoutResult Implementation
type logoutResult struct {

Wyświetl plik

@ -237,6 +237,17 @@ func TestSpiManager_ChangePassword(test *testing.T) {
_ = result
}
func TestSpiManager_ResetPassword(test *testing.T) {
manager := Conductor.SpiManager()
result, err := manager.ResetPassword("username_or_email", nil)
if err != nil {
test.Fatal(err)
}
_ = result
}
func TestSpiManager_Logout(test *testing.T) {
manager := Conductor.SpiManager()

Wyświetl plik

@ -36,6 +36,10 @@ func (dispatcher *dispatcher) NewChangePasswordResult() IChangePasswordResult {
return NewChangePasswordResult(nil)
}
func (dispatcher *dispatcher) NewResetPasswordResult() IResetPasswordResult {
return NewResetPasswordResult(nil)
}
func (dispatcher *dispatcher) NewLogoutResult() ILogoutResult {
return NewLogoutResult(nil)
}