okrzejahauru.club/x/okrzeja/service Index | Files | Directories

package service

import "hauru.club/x/okrzeja/service"

Package service implements services in their first phase of development. It works as incubator for services.

If bigger service emerges, you can move it to the its own new subpackage of service.

Index

Constants

const (
	// FileMIMEDirectory is MIME type for directories.
	FileMIMEDirectory = rest.FileMIMEDirectory
)
const (
	// ResourceIDGlob is catch-all identifier for matching every
	// resource from resource group.
	//
	// It can be, for example, used to mark that given user has access
	// to every resource from given group.
	ResourceIDGlob = "*"
)

Variables

var (
	// ErrFileNotFound is returned when client requests non-existing file.
	ErrFileNotFound = errors.New("fileserver: file not found")

	// ErrFilenameTaken is returned when file, with given name and the same
	// parent, already exists.
	ErrFilenameTaken = errors.New("fileserver: filemname is already taken")
)
var (
	// ErrUsernameAlreadyTaken is returned when there is already existing user
	// in the system with requested username.
	ErrUsernameAlreadyTaken = errors.New("users: username is already taken")

	// ErrUserNotFound is returned when actions is requested for non-existing user.
	ErrUserNotFound = httpx.NewErrorFromCode(http.StatusNotFound, httpx.ErrorMetadata{
		Message:     "There is no such user in the system.",
		Description: "users: there is no such user",
	})
)
var ErrMissingDependency = errors.New("service: missing dependency")

ErrMissingDependency is returned when method call lacks required dependency injected.

Types

type AccountCreateRepository

type AccountCreateRepository interface {
	// AccountCreate creates new account for requested user. It should return
	// ErrUsernameAlreadyTaken error if there is already user with requested
	// username.
	AccountCreate(context.Context, AccountCreateRequest) (*AccountCreateResponse, error)
}

AccountCreateRepository is storage repository for creating new users' accounts.

type AccountCreateRequest

type AccountCreateRequest struct {
	// ID is unique user's identifier.
	ID uuid.UUID

	// Username is unique login name.
	Username string

	// Password is secret hashed phrase use to access user's account.
	Password []byte
}

AccountCreateRequest holds request arguments for new user's account creation.

type AccountCreateResponse

type AccountCreateResponse struct {
	// CreatedAt is time of account creation.
	CreatedAt time.Time
}

AccountCreateResponse holds response of new user's account creation process.

type AccountDeleteRepository

type AccountDeleteRepository interface {
	// AccountDelete removes account and all its dependencies (like files, roles etc), for
	// user with given ID, from the system.
	//
	// This method can return ErrUserNotFound if there is no user with given ID.
	AccountDelete(context.Context, uuid.UUID) error
}

AccountDeleteRepository removes user accounts from the storage.

type AccountUpdatePasswordRepository

type AccountUpdatePasswordRepository interface {
	// AccountUpdatePassword updates password of existing user.
	//
	// This method can return ErrUserNotFound if there is no user with given ID.
	AccountUpdatePassword(context.Context, AccountUpdatePasswordRequest) error
}

AccountUpdatePasswordRepository changes password of user.

type AccountUpdatePasswordRequest

type AccountUpdatePasswordRequest struct {
	// ID is unique user's identifier.
	ID uuid.UUID

	// NewPassword is new hashed password for user.
	NewPassword []byte
}

AccountUpdatePasswordRequest holds arguments for changing user's password.

type AccountsCreateRepository

type AccountsCreateRepository interface {
	// AccountsCreate creates new accounts for requested users. It should return
	// ErrUsernameAlreadyTaken error if there is already user with username from
	// requested batch of users.
	AccountsCreate(context.Context, []AccountCreateRequest) error
}

AccountsCreateRepository is storage repository for creating batch of new users' accounts.

type AccountsCreator

type AccountsCreator interface {
	AccountCreateRepository
	AccountsCreateRepository
}

AccountsCreator is repository interface that implements all the methods for creating user accounts.

type AccountsReadFromRequest

type AccountsReadFromRequest struct {
	// Limig is the maximum size of return slice.
	Limit int

	// Last is ID of last user from previous query to AccountsReadFrom method. Every
	// ReadAccountResponse from returned slice belongs to the user that was created
	// after account with Last ID.
	Last uuid.UUID

	// Query is an optional query string. It can be prefix, suffix or substring
	// of username of user that you are looking for.
	Query string
}

AccountsReadFromRequest holds arguments for AccountsReadFrom method.

type ActivityDecorator

type ActivityDecorator struct {
	Pusher      ActivityPusher
	OwnerReader FileOwnerReader
	FileService rest.FileCommandService
	FileReader  FileReadRepository
}

ActivityDecorator pushes activity events to the storage on particular user actions.

func (*ActivityDecorator) DirectoryCreate

DirectoryCreate creates new directory with requested properties.

func (*ActivityDecorator) FileCreate

FileCreate creates new file with requested properties.

func (*ActivityDecorator) FileDelete

func (ad *ActivityDecorator) FileDelete(ctx context.Context, fileID uuid.UUID) error

FileDelete removes file or directory with given unique ID from filesystem. All children of removed directory are also removed.

It is impossible to delete any root file with this method.

func (*ActivityDecorator) FileUpdateContent

func (ad *ActivityDecorator) FileUpdateContent(ctx context.Context, req rest.FileUpdateContentRequest) error

FileUpdateContent updates content of the file with given unique ID.

func (*ActivityDecorator) FileUpdateName

func (ad *ActivityDecorator) FileUpdateName(ctx context.Context, req rest.FileUpdateNameRequest) error

FileUpdateName updates name of the file with given unique ID.

type ActivityPushRequest

type ActivityPushRequest struct {
	// ID is unique id of new activity record.
	ID uuid.UUID

	// OwnerID is user's ID, which provoked the activity.
	OwnerID uuid.UUID

	// Type of activity record.
	Type string

	// Details consist flat map of key/value records that will be
	// presented to user and system administrator, to provide useful
	// debug informations related to given action.
	Details map[string]any
}

type ActivityPusher

type ActivityPusher interface {
	// ActivityPush saves activity in the storage.
	ActivityPush(context.Context, ActivityPushRequest) error
}

ActivityPusher implements methods for storing activities.

type Admin

type Admin struct {
	ReadRepository  AdminReadRepository
	WriteRepository AdminWriteRepository
	Registerer      rest.UserRegisterer
}

Admin service manages admin permissions in the system.

It can intercept Users service during registration phase to create first admin account.

func (*Admin) UserRegister

func (a *Admin) UserRegister(
	ctx context.Context,
	req rest.UserRegisterRequest,
) (*rest.UserRegisterResponse, error)

UserRegister creates new account for user and, if there is no other admin account registered, marks created account as admin account.

type AdminReadRepository

type AdminReadRepository interface {
	// AdminCount tracks number of admin accounts in the storage.
	AdminCount(context.Context) (int, error)
}

AdminReadRepository is storage repository for reading admin account details.

type AdminWriteRepository

type AdminWriteRepository interface {
	// AdminMakeNow tags user with given ID as admin account with promotion date
	// set to the current time.
	//
	// Admin account can promote other accounts to the admin status. Admin with
	// earlier promotion date cannot withdraw admin permissions. It means that the
	// first Admin can create new admins, but newer admins cannot make the older
	// admin normal again.
	AdminMakeNow(ctx context.Context, id uuid.UUID) error
}

AdminWriteRepository is storage repository for writing admin account related informations.

type Auth

type Auth struct {
	AccountRepository ReadAccountRepository
	ReadRepository    RolesReadRepository
	WriteRepository   RolesWriteRepository
}

Auth is service for users' authentication and authorization.

func (*Auth) ActionAuthorize

func (a *Auth) ActionAuthorize(
	ctx context.Context,
	req httpx.ResourceAuthorizationRequest,
) (bool, error)

ActionAuthorize returns true if user with given unique identifier is authorized to perform Action on the resource with given unique resource's identifier. Otherwise it returns false.

func (*Auth) AuthenticateUser

func (a *Auth) AuthenticateUser(ctx context.Context, username, password string) (uuid.UUID, error)

AuthenticateUser authorizes user with given username and passwords. It returns authorized user's ID or error if authorization failed.

func (*Auth) GrantAdminPermissions

func (a *Auth) GrantAdminPermissions(ctx context.Context, id uuid.UUID) error

GrantAdminPermissions grants all necessary permissions to perform admin role to the user with the given id.

func (*Auth) GrantDefaultUserPermissions

func (a *Auth) GrantDefaultUserPermissions(ctx context.Context, id uuid.UUID) error

GrantDefaultUserPermissions grants all default permissions to the user with given id.

These permissions are required for users to allow them to perform day-to-day tasks in the system, such as for example: changing password.

type FileCreateWithOwnerRequest

type FileCreateWithOwnerRequest struct {
	// ID is unique identifier of the file.
	ID uuid.UUID

	// OwnerID is unique identifier of owner user.
	OwnerID uuid.UUID

	// Parent is optional ID of parent directory. If Parent.Valid is equal to
	// false, then File modelled by FileReadResponse has no parent.
	Parent uuid.NullUUID

	// Name is the name of the file.
	Name string

	// Content of the file.
	Content []byte

	// MIME is MIMEtype of the file.
	MIME string
}

FileCreateWithOwnerRequest holds arguments for creating new file as owner.

type FileDeleteRepository

type FileDeleteRepository interface {
	// FileDeleteWithRoles removes file or directory with its children and all
	// roles assigned to the given file. It removes  children roles also in
	// case of directory.
	FileDeleteWithRoles(context.Context, uuid.UUID) error
}

FileDeleteRepository removes files and directories from the file storage.

type FileOwnerReader

type FileOwnerReader interface {
	// FileOwnerRead returns unique user's ID of owner of file with given file ID.
	FileOwnerRead(ctx context.Context, fileID uuid.UUID) (uuid.UUID, error)
}

FileOwnerReader reads ID of owner of given file.

type FileReadRepository

type FileReadRepository interface {
	// FileRead returns all the content and metadata associated with file stored
	// in the Okrzeja's storage with given file ID.
	FileRead(ctx context.Context, fileID uuid.UUID) (*FileReadResponse, error)

	// FileReadOfUser returns file data of file owned by user with given username.
	// If there is no such file or user, it returns ErrFileNotFound error.
	FileReadOfUser(ctx context.Context, owner, path string) (*FileReadResponse, error)

	// FilesReadFromDirectory returns all files being stored currently in the directory
	// with provided unique identifier.
	FilesReadFromDirectory(context.Context, uuid.UUID) ([]FileReadResponse, error)
}

FileReadRepository reads files from storage.

type FileReadResponse

type FileReadResponse struct {
	// ID is unique identifier of the file.
	ID uuid.UUID

	// Parent is optional ID of parent directory. If Parent.Valid is equal to
	// false, then File modelled by FileReadResponse has no parent.
	Parent uuid.NullUUID

	// Content of the file.
	Content []byte

	// Name is the name of the file.
	Name string

	// Size is length in bytes for the regular file.
	Size int64

	// MIME is MIMEtype of the file.
	MIME string

	// LastUpdated is datetime when file was updated last time.
	LastUpdated time.Time
}

FileReadResponse constains a file data and metadata.

func (*FileReadResponse) IsDir

func (res *FileReadResponse) IsDir() bool

IsDir returns true if file from response is directory.

func (*FileReadResponse) IsRoot

func (res *FileReadResponse) IsRoot() bool

IsRoot returns true if file from response is root directory.

type FileWriteContentRequest

type FileWriteContentRequest struct {
	// ID is unique identifier of the file.
	ID uuid.UUID

	// Content to be updated.
	Content []byte
}

FileWriteContentRequest holds arguments for updating content of the file with provided unique ID.

type FileWriteNameRequest

type FileWriteNameRequest struct {
	// ID is unique identifier of the file.
	ID uuid.UUID

	// Name of the file to be updated.
	Name string
}

FileWriteNameRequest holds arguments for updating name of the file with provided unique ID.

type FileWriteRepository

type FileWriteRepository interface {
	// FileCreateWithOwner creates new file or directory with provided user ID as owner. It
	// returns ErrFilenameTaken, if there is already file with given name and the same
	// parent ID.
	FileCreateWithOwner(context.Context, FileCreateWithOwnerRequest) error

	// FileWriteContent writes new content to the existing file with provided ID.
	// Returns ErrFileNotFound if there is no file with given ID.
	FileWriteContent(context.Context, FileWriteContentRequest) error

	// FileWriteName updates name of the already existing file with provided ID.
	// Returns ErrFileNotFound if there is no file with given ID.
	FileWriteName(context.Context, FileWriteNameRequest) error
}

FileWriteRepository writes files and directories to the file storage.

type Files

type Files struct {
	Reader        FileReadRepository
	Writer        FileWriteRepository
	Deleter       FileDeleteRepository
	AccountReader ReadAccountRepository
}

Files is a service for CRUD operations on files owned by users.

func (*Files) DirectoryCreate

func (f *Files) DirectoryCreate(ctx context.Context, req rest.NewDirectoryRequest) (*rest.NewFileResponse, error)

DirectoryCreate creates new directory with requested properties.

func (*Files) DirectoryRead

func (f *Files) DirectoryRead(ctx context.Context, dirID uuid.UUID) (*rest.DirectoryReadResponse, error)

DirectoryRead returns useful metadata of directory with given ID and its children files.

func (*Files) FileCreate

func (f *Files) FileCreate(ctx context.Context, req rest.NewFileRequest) (*rest.NewFileResponse, error)

FileCreate creates new file with requested properties and sane default values like default content.

func (*Files) FileDelete

func (f *Files) FileDelete(ctx context.Context, id uuid.UUID) error

FileDelete removes file or directory with given unique ID from filesystem. All children of removed directory are also removed.

func (*Files) FileRead

func (f *Files) FileRead(ctx context.Context, fileID uuid.UUID) (*rest.FileReadResponse, error)

FileRead returns metadata and content of the file with given ID.

func (*Files) FileUpdateContent

func (f *Files) FileUpdateContent(ctx context.Context, req rest.FileUpdateContentRequest) error

FileUpdateContent updated content of the file with given unique ID.

func (*Files) FileUpdateName

func (f *Files) FileUpdateName(ctx context.Context, req rest.FileUpdateNameRequest) error

FileUpdateName updates name of the file with given unique ID.

func (*Files) PersonalFileSystem

func (f *Files) PersonalFileSystem(ctx context.Context) http.FileSystem

PersonalFileSystem returns http.FileSystem that is able to read files from users' personal file systems.

func (*Files) RootDirectory

func (f *Files) RootDirectory(ctx context.Context, uid uuid.UUID) (uuid.UUID, error)

RootDirectory returns unique identifier of root file for user with given user ID.

type PermissionDecorator

type PermissionDecorator struct {
	AuthService            *Auth
	WrappedAccountStorage  AccountsCreator
	WrappedAdminRepository AdminWriteRepository
}

PermissionDecorator grants default default necessary permissions for different actors in the system.

func (*PermissionDecorator) AccountCreate

AccountCreate creates new account for requested user. It should return ErrUsernameAlreadyTaken error if there is already user with requested username.

func (*PermissionDecorator) AccountsCreate

func (p *PermissionDecorator) AccountsCreate(ctx context.Context, reqs []AccountCreateRequest) error

AccountsCreate creates new accounts for requested users. It should return ErrUsernameAlreadyTaken error if there is already user with username from requested batch of users.

func (*PermissionDecorator) AdminMakeNow

func (p *PermissionDecorator) AdminMakeNow(ctx context.Context, id uuid.UUID) error

AdminMakeNow tags user with given ID as admin account with promotion date set to the current time.

type ReadAccountRepository

type ReadAccountRepository interface {
	// ReadAccount returns account data of user with given unique user ID.
	ReadAccount(ctx context.Context, uid uuid.UUID) (*ReadAccountResponse, error)

	// ReadAccountByUsername returns account data of user with given username.
	ReadAccountByUsername(ctx context.Context, username string) (*ReadAccountResponse, error)

	// AccountsRead returns limited group of accounts.
	//
	// Query is optional query string. See AccountsReadFromRequest for more info about query
	// string.
	AccountsRead(ctx context.Context, limit int, query string) ([]ReadAccountResponse, error)

	// AccountsReadFrom returns limited group of accounts that had been created after creation
	// date of account of user with given ID.
	AccountsReadFrom(ctx context.Context, req AccountsReadFromRequest) ([]ReadAccountResponse, error)
}

ReadAccountRepository is storage repository for reading already existing user data.

type ReadAccountResponse

type ReadAccountResponse struct {
	// ID is unique user identifier.
	ID uuid.UUID

	// Username is unique username of user.
	Username string

	// Password is hashed password for user's account.
	Password []byte

	// CreatedAt is time of account creation.
	CreatedAt time.Time
}

ReadAccountResponse holds response data for reading account operations.

type Role

type Role string

Role is the role of the user assigned to single resource.

const (
	// RoleOwner marks user as the initial owner of the resource. Owner
	// can read, write, and delete its resource.
	RoleOwner Role = "owner"

	// RoleAdmin marks user as the administrator of the system with
	// all permissions to use given resource, just the same way as
	// RoleOwner.
	RoleAdmin Role = "admin"
)

type RolesReadRepository

type RolesReadRepository interface {
	// RolesRead returns slice of roles assigned to given resource and owned
	// by user with provided unique identifier.
	RolesRead(ctx context.Context, req RolesReadRequest) ([]Role, error)
}

RolesReadRepository reads data from roles storage.

type RolesReadRequest

type RolesReadRequest struct {
	// ResourceName is the name of resource. It identifies
	// group of roles related to given resource.
	ResourceName string

	// ResourceID is unique identifier of resource. It can alsob be a glob
	// pattern, see ResourceIDGlob.
	ResourceID string

	// UserID is unique identifier of user.
	UserID uuid.UUID
}

RolesReadRequest holds request arguments for reading roles from repository.

type RolesWriteRepository

type RolesWriteRepository interface {
	// RolesWrite writes rule based on the RolesWriteRequest to the roles storage.
	RolesWrite(context.Context, RolesWriteRequest) error
}

RolesWriteRepository writes data to the roles storage.

type RolesWriteRequest

type RolesWriteRequest struct {
	// ResourceName is the name of resource. It identifies
	// group of roles related to given resource.
	ResourceName string

	// ResourceID is unique identifier of resource. It can also be a glob
	// pattern, see ResourceIDGlob.
	ResourceID string

	// Role for given rule.
	Role Role

	// UserID is unique identifier of user.
	UserID uuid.UUID
}

RolesWriteRequest holds arguments for writing roles to the storage.

type Users

Users service operates on user's data by creating new accounts and modifying existing user's account data.

func (*Users) UserChangePassword

func (s *Users) UserChangePassword(ctx context.Context, req rest.UserPasswordChangeRequest) error

UserChangePassword changes password of user with given user ID to the provided new password.

func (*Users) UserDelete

func (s *Users) UserDelete(ctx context.Context, id uuid.UUID) error

UserDelete removes user with given unique ID from the system.

func (*Users) UserPasswordUpdate

func (s *Users) UserPasswordUpdate(ctx context.Context, req rest.UserPasswordUpdateRequest) error

UserPasswordUpdate updates user's password on his/her behalf. It returns error if authorization with old password fails or new password is invalid.

func (*Users) UserRegister

func (u *Users) UserRegister(
	ctx context.Context, req rest.UserRegisterRequest,
) (*rest.UserRegisterResponse, error)

UserRegister creates new account for user.

func (*Users) UsersReadFrom

func (s *Users) UsersReadFrom(
	ctx context.Context, req rest.UsersReadFromRequest,
) ([]rest.UserReadResponse, error)

UserReadFrom reads limited number of user accounts that were created after account with given ID.

func (*Users) UsersReadFromUsername

func (s *Users) UsersReadFromUsername(
	ctx context.Context,
	req rest.UsersReadFromUsernameRequest,
) ([]rest.UserReadResponse, error)

UserReadFrom reads limited number of user accounts that were created after account with given ID.

func (*Users) UsersReadInit

func (s *Users) UsersReadInit(ctx context.Context, query string) ([]rest.UserReadResponse, error)

UsersReadInit initialize querying user accounts. It returns limited number of user accounts. You can use last user ID from given slice and UserReadFrom method to query for more entries.

func (*Users) UsersRegister

func (u *Users) UsersRegister(
	ctx context.Context,
	reqs []rest.UserRegisterRequest,
) error

UsersRegister creates multiple user accounts. It should fail if creation of at least single user account also fails.

Source Files

activities.go admin.go auth.go fileserver.go service.go users.go

Directories

PathSynopsis
service/configPackage config implements service for manipulating static and dynamic application's configuration.
service/httpxPackage httpx implements Okrzeja's HTTP server and specifies required services to run it.
service/logPackage log implements logging and telemetry utilities for okrzeja web server.
service/restPackage rest provides HATEOS-compliant HTTP REST handlers and defines contracts used by those handlers.
Version
v0.0.0-20231010043146-4292577f982b (latest)
Published
Oct 10, 2023
Platform
linux/amd64
Imports
14 packages
Last checked
1 day ago

Tools for package owners.