Documentation ¶
Index ¶
- Constants
- func ErrorCode(err error) string
- func ErrorMessage(err error) string
- func IsAdminContext(ctx context.Context) bool
- func NewContextWithUser(ctx context.Context, user *User) context.Context
- func UserIDFromContext(ctx context.Context) int
- type Auth
- type AuthFilter
- type AuthService
- type Blog
- type BlogFilter
- type BlogService
- type BlogUpdate
- type Comment
- type CommentFilter
- type CommentPayload
- type CommentService
- type CommentUpdate
- type Config
- type EmailService
- type Error
- type Event
- type EventHandler
- type EventService
- type FileService
- type NOPEventService
- type Payload
- type Project
- type ProjectFilter
- type ProjectService
- type Session
- type SubBlog
- type SubBlogFilter
- type SubBlogPayload
- type SubBlogService
- type SubBlogUpdate
- type Subscription
- type SubscriptionFilter
- type SubscriptionService
- type Topic
- type TopicLink
- type User
- type UserFilter
- type UserService
- type UserUpdate
Constants ¶
const ( ECONFLICT = "conflict" EINTERNAL = "internal" EINVALID = "invalid" ENOTFOUND = "not_found" ENOTIMPLEMENTED = "not_implemented" EUNAUTHORIZED = "unauthorized" )
Error codes which map good to http errors.
const ( // Sub blogs are branched under blogs. EventTopicNewSubBlog = "blog:sub_blog:new" // Comments are branched under sub blogs. EventTopicNewComment = "blog:sub_blog:comment:new" )
Event topics.
const (
AuthSourceGitHub = "github"
)
auth sources represent different OAuth providers, the system is currently supporting only github as a provider but its implemented with this issue taken in mind.
const SessionCookieName = "session"
SessionCookieName represents the name of the session cookie.
Variables ¶
This section is empty.
Functions ¶
func ErrorCode ¶
ErrorCode is a helper function to retrieve the error code from a pa.Error. returns an empty string if err is nil. returns EINTERNAL if the error isnt a pa.Error.
func ErrorMessage ¶
ErrorMessage is a helper function to retrieve the error message from pa.Error. returns an empty string if err is nil. returns "Internal error." if the error isnt a pa.Error.
func IsAdminContext ¶
IsAdminContext is a helper function to check if context: ctx is an admin context.
func NewContextWithUser ¶
NewContextWithUser enriches the context ctx with the user: user under the key userContextKey.
func UserIDFromContext ¶
UserIDFromContext is a helper function which returns only the id of the user under ctx. To only be used when checking id with id.
Types ¶
type Auth ¶
type Auth struct { // the pk of the auth. ID int `json:"id"` // fields linking the auth object back to the user. UserID int `json:"userID"` User *User `json:"user"` // the source from where the OAuth object comes from, ie: "github". Source string `json:"source"` SourceID string `json:"sourceID"` // OAuth credentials provided by the OAuth source. AccessToken string `json:"-"` RefreshToken string `json:"-"` Expiry *time.Time `json:"-"` // timestamps. CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` }
Auth represents an OAuth object in the system.
type AuthFilter ¶
type AuthFilter struct { // fields to filter on. ID *int `json:"id"` UserID *int `json:"userID"` Source *string `json:"source"` SourceID *string `json:"sourceID"` // restrictions on the result set, used for pagination and set limits. Offset int `json:"offset"` Limit int `json:"limit"` }
AuthFilter represents a filter used by FindAuths to filter the response.
type AuthService ¶
type AuthService interface { // FindAuthByID returns a auth based on the id. // returns ENOTFOUND if the auth doesent exist. FindAuthByID(ctx context.Context, id int) (*Auth, error) // FindAuths returns a range of auths and the length of the range. If filter // is specified FindAuths will apply the filter to return set response. FindAuths(ctx context.Context, filter AuthFilter) ([]*Auth, int, error) // CreateAuth creates a auth. Main entry point when creating a user. // The creation will only go through if the linking fields are attached or the object passes the validation. // On creation the auth will be linked to a user if found, otherwise the user gets created and the auth gets // linked to the user and the user linked to the auth through the linking fields. CreateAuth(ctx context.Context, auth *Auth) error // DeleteAuth permanently deletes a auth. The linked user wont be deleted bu will appear as // not validated. DeleteAuth(ctx context.Context, id int) error }
AuthService represents a service which manages auth in the system.
type Blog ¶
type Blog struct { // the pk of the blog. ID int `json:"id"` // the descriptive fields of the blog. Title string `json:"title"` Description string `json:"description"` SubBlogs []*SubBlog `json:"subBlogs"` // the list of sub blogs contained by the blog. // timestamps. CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` }
Blog represents an blog object in the system. Blog has no reason to store any user ID as the admin user is the only one who can interact with BlogService.CreateBlog().
type BlogFilter ¶
type BlogFilter struct { // fields to filter on. ID *int `json:"id"` Title *string `json:"title"` // restrictions on the result set, used for pagination and set limits. Offset int `json:"offset"` Limit int `json:"limit"` }
BlogFilter represents a filter used by FindBlogs to filter the response.
type BlogService ¶
type BlogService interface { // FindBlogByID returns a blog based on the id. // returns ENOTFOUND if the blog doesent exist. FindBlogByID(ctx context.Context, id int) (*Blog, error) // FindBlogs returns a range of blogs and the length of the range. If filter // is specified FindBlogs will apply the filter to return set response. FindBlogs(ctx context.Context, filter BlogFilter) ([]*Blog, int, error) // CreateBlog creates a blog. // returns EUNAUTHORIZED if used by anyone other then the adim user. CreateBlog(ctx context.Context, blog *Blog) error // UpdateBlog updates a blog based on the update field. // returns ENOTFOUND if blog doesent exist. // returns EUNAUTHORIZED if used by anyone other then the adim user. UpdateBlog(ctx context.Context, id int, update BlogUpdate) (*Blog, error) // DeleteBlog permanently deletes a blog. // returns ENOTFOUND if blog doesent exist. // returns EUNAUTHORIZED if used by anyone other then the adim user. DeleteBlog(ctx context.Context, id int) error }
BlogService represents a service which manages blogs in the system.
type BlogUpdate ¶
type BlogUpdate struct { // fields which can be updated. Title *string `json:"title"` Description *string `json:"description"` }
BlogUpdate represents an update used by UpdateBlog to update a blog.
type Comment ¶
type Comment struct { // the pk of the comment. ID int `json:"id"` // linking fields of the comment. SubBlogID int `json:"subBlogID"` UserID int `json:"userID"` User *User `json:"user"` // content of the comment. Content string `json:"content"` // timestamp. CreatedAt time.Time `json:"createdAt"` }
Comment represents a comment in the system.
type CommentFilter ¶
type CommentFilter struct { // fields to filter on. ID *int `json:"id"` SubBlogID *int `json:"SubBlogID"` UserID *int `json:"userID"` // restrictions on the result set, used for pagination and set limits. Offset int `json:"offset"` Limit int `json:"limit"` }
CommentFilter represents a filter used by FindComments to filter the response.
type CommentPayload ¶
type CommentPayload struct { Comment *Comment `json:"comment"` SubBlogID int `json:"subBlogID"` SubBlog *SubBlog `json:"subBlog"` }
CommentPayload represents the payload carried by a EventTopicNewComment -> ./event.go.
type CommentService ¶
type CommentService interface { // FindCommentByID returns a comment based on the id. // returns ENOTFOUND if the comment doesent exist. FindCommentByID(ctx context.Context, id int) (*Comment, error) // FindComments returns a range of comments and the length of the range. If filter // is specified FindComments will apply the filter to return set response. FindComments(ctx context.Context, filter CommentFilter) ([]*Comment, int, error) // CreateComment creates a comment. CreateComment(ctx context.Context, comment *Comment) error // UpdateComment updates a comment based on the update field. // returns ENOTFOUND if the comment doesent exist. // returns EUNAUTHORIZED if used by anyone other then the adim user. UpdateComment(ctx context.Context, id int, update CommentUpdate) (*Comment, error) // DeleteComment permanently deletes a comment. // returns ENOTFOUND if comment doesent exist. // returns EUNAUTHORIZED if used by anyone other then the user owning the comment. DeleteComment(ctx context.Context, id int) error }
CommentService represents a service which manages comments in the system.
type CommentUpdate ¶
type CommentUpdate struct { // fields which can be updated. Content *string `json:"content"` }
CommentUpdate represents an update used by UpdateComment to update a comment.
type Config ¶
type Config struct { Github struct { ClientID string `mapstructure:"client-id"` ClientSecret string `mapstructure:"client-secret"` AdminUserEmail string `mapstructure:"admin-user-email"` } `mapstructure:"github"` HTTP struct { Addr string `mapstructure:"addr"` Domain string `mapstructure:"domain"` BlockKey string `mapstructure:"block-key"` HashKey string `mapstructure:"hash-key"` FrontendURL string `mapstructure:"frontend-url"` } `mapstructure:"http"` Database struct { SqliteDSN string `mapstructure:"sqlite-dsn"` RedisDSN string `mapstructure:"redis-dsn"` } `mapstructure:"database"` Smtp struct { Addr string `mapstructure:"addr"` Identity string `mapstructure:"identity"` Username string `mapstructure:"username"` Password string `mapstructure:"password"` Host string `mapstructure:"host"` } `mapstructure:"smtp"` FileStructure struct { ProjectImagesDir string `mapstructure:"project-images-dir"` BlogImagesDir string `mapstructure:"blog-images-dir"` } `mapstructure:"file-structure"` }
Config layouts the .toml config file structure its expecting. uses mapstructure tags which is used by viper.
type EmailService ¶
type EmailService interface { // SendEmail will send a emails to the adresses provided in to. SendEmail(to []string, body, subject string) error }
EmailService represents a service which manages emails in the system.
type Error ¶
type Error struct { // Code to check the type of the error. Code string // Human readeable message. Message string }
Error is a struct containing full details about the error.
type Event ¶
type Event struct { // The topic of the event, ie: EventTopicNewSubBlog -> ./event.go. Topic string // The payload of the event, ie: BlogPayload -> ./event.go. Payload Payload }
Event is passed to EventHandler.
type EventHandler ¶
type EventHandler func(ctx context.Context, handler SubscriptionService, event Event) error
EventHandler represents a fucntion which is called on each event.
type EventService ¶
type EventService interface { // Push pushes event in the event queue. Push(ctx context.Context, event Event) error // RegisterHandler registers handler as the handler for topic. RegisterHandler(topic string, handler EventHandler) // RegisterSubscriptionsHandler registers the subscriptions manager. RegisterSubscriptionsHandler(hand SubscriptionService) }
EventService represents a service which manages events in the system.
func NewNOPEventService ¶
func NewNOPEventService() EventService
type FileService ¶
type FileService interface { // CreateFile creates a new file. CreateFile(ctx context.Context, path string, content io.Reader) error // DeletePath deletes path. DeleteFile(ctx context.Context, path string) error }
FileService represents a service which manages files in the system. Should be used to create / delete files in a served fs.
type NOPEventService ¶
type NOPEventService struct{}
NOPEventService is EventService which does nothing. Should only be used in tests.
func (*NOPEventService) Push ¶
func (n *NOPEventService) Push(ctx context.Context, event Event) error
func (*NOPEventService) RegisterHandler ¶
func (n *NOPEventService) RegisterHandler(topic string, handler EventHandler)
func (*NOPEventService) RegisterSubscriptionsHandler ¶
func (n *NOPEventService) RegisterSubscriptionsHandler(hand SubscriptionService)
type Payload ¶
type Payload interface{}
Payload is an iterface to pe used when accepting event payloads, ie: BlogPayload -> ./event.go.
type Project ¶
type Project struct { // pk in our system. ID int `json:"id"` // github api fields. Name string `json:"name"` Description string `json:"description"` Topics []string `json:"topics"` HtmlURL string `json:"html_url"` }
Project represents a github api repo response simplified. this is consumed by our frontend to avoid getting github rate-limited.
type ProjectFilter ¶
type ProjectFilter struct { // fields to filter on. ID *int `json:"id"` Name *string `json:"name"` // restrictions on the result set, used for pagination and set limits. Offset int `json:"offset"` Limit int `json:"limit"` }
ProjectFilter represents a filter used by FindProjects to filter the response.
type ProjectService ¶
type ProjectService interface { // FindProjectByID returns a project based on the id. // returns ENOTFOUND if the project doesent exist. FindProjectByID(ctx context.Context, id int) (*Project, error) // FindProjectByName returns a project based on the name. // returns ENOTFOUND if the project doesent exist. // (helper function to also return ENOTFOUND when filtering on name) FindProjectByName(ctx context.Context, name string) (*Project, error) // FindProjects returns a range of preojects and the length of the range. If filter // is specified FindProjects will apply the filter to return set response. FindProjects(ctx context.Context, filter ProjectFilter) ([]*Project, int, error) // CreateOrUpdateProject checks for existing id field on project or any duplicate name, if any // found the project field will be used to update the pointed to project. // returns EUNAUTHORIZED if not used by admin user or internally. CreateOrUpdateProject(ctx context.Context, project *Project) error // DeleteProject permanently deletes a project based on name. // returns ENOTFOUND if project doesent exist. // returns EUNAUTHORIZED if not used by admin user or internally. DeleteProject(ctx context.Context, name string) error }
ProjectService represents a service which manages projects in the system.
type Session ¶
type Session struct { UserID int `json:"userID"` IsAdmin bool `json:"isAdmin"` // Mainly used for auth 2.0 protocol dialogue to prevent CSRF attacks. // can also be used to store redirect urls and any other state type variables. State string `json:"state"` }
Session represents data stored per session under a secure cookie.
type SubBlog ¶
type SubBlog struct { // the pk of the sub blog. ID int `json:"id"` // the id of the blog under which the sub blog is. BlogID int `json:"blogID"` // the descriptive fields of the sub blog. Title string `json:"title"` Content string `json:"body"` Comments []*Comment `json:"comments"` // timestamps. CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` }
SubBlog represents an sub blog object in the system. SubBlog has no reason to store any user ID as the admin user is the only one who can interact with SubBlogService.CreateSubBlog().
type SubBlogFilter ¶
type SubBlogFilter struct { // fields to filter on. ID *int `json:"id"` Title *string `json:"title"` BlogID *int `json:"blogID"` // restrictions on the result set, used for pagination and set limits. Offset int `json:"offset"` Limit int `json:"limit"` }
SubBlogFilter represents a filter used by FindSubBlogs to filter the response.
type SubBlogPayload ¶
type SubBlogPayload struct { SubBlog *SubBlog `json:"subBlog"` BlogID int `json:"blogID"` Blog *Blog `json:"blog"` }
SubBlogPayload represents the payload carried by a EventTopicNewSubBlog -> ./event.go.
type SubBlogService ¶
type SubBlogService interface { // FindSubBlogByID returns a sub blog based on the id. // returns ENOTFOUND if the sub blog doesent exist. FindSubBlogByID(ctx context.Context, id int) (*SubBlog, error) // FindSubBlogs returns a range of sub blogs and the length of the range. If filter // is specified FindSubBlogs will apply the filter to return set response. FindSubBlogs(ctx context.Context, filter SubBlogFilter) ([]*SubBlog, int, error) // CreateSubBlog creates a sub blog. // returns EUNAUTHORIZED if used by anyone other then the adim user. CreateSubBlog(ctx context.Context, subBlog *SubBlog) error // UpdateSubBlog updates a sub blog based on the update field. // returns ENOTFOUND if sub blog doesent exist. // returns EUNAUTHORIZED if used by anyone other then the adim user. UpdateSubBlog(ctx context.Context, id int, update SubBlogUpdate) (*SubBlog, error) // DeleteSubBlog permanently deletes a sub blog. // returns ENOTFOUND if sub blog doesent exist. // returns EUNAUTHORIZED if used by anyone other then the adim user. DeleteSubBlog(ctx context.Context, id int) error }
SubBlogService represents a service which manages sub-blogs in the system.
type SubBlogUpdate ¶
type SubBlogUpdate struct { // fields which can be updated. Title *string `json:"title"` Content *string `json:"content"` }
SubBlogUpdate represents an update used by UpdateSubBlog to update a sub blog.
type Subscription ¶
type Subscription struct { // the pk of the subscription. ID int // the subscribed user. UserID int // topic to which the user is subscribed, ie: EventTopicNewBlog -> ./event.go. // each topic will map to a table in the database, logic handeled in service. Topic string // Payload is used to provide unique information about each Topic. The type of payload can be identified // by the topic, for example a Topic of type EventTopicNewBlog will come with a payload of type // BlogPayload -> ./event.go Payload Payload }
Subscription represents a subscription handeled by the event handler on an event / topic.
type SubscriptionFilter ¶
type SubscriptionFilter struct { // fields to filter on. ID *int `json:"id"` UserID *int `json:"userID"` Topic *string `json:"topic"` Payload Payload `json:"payload"` // restrictions on the result set, used for pagination and set limits. Offset int `json:"offset"` Limit int `json:"limit"` }
SubscriptionFilter represents a filter used by FindSubscriptions to filter the response.
type SubscriptionService ¶
type SubscriptionService interface { // FindSubscriptionByID returns a subscription based on the id and topic. // returns ENOTFOUND if the subscription doesent exist. FindSubscriptionByID(ctx context.Context, id int, topic string) (*Subscription, error) // FindSubscriptions returns a range of subscriptions and the length of the range. If filter // is specified FindSubscriptions will apply the filter to return set response. FindSubscriptions(ctx context.Context, filter SubscriptionFilter) ([]*Subscription, int, error) // CreateSubscription creates a subscription on topic. User is passed through context. CreateSubscription(ctx context.Context, subscription *Subscription) error // DeleteSubscription permanently deletes a subscription. Returns EUNAUTHORIZED if the user owning the subscription // isnt the one calling and ENOTFOUND id the subscription doesent exist. User is passed through context. DeleteSubscription(ctx context.Context, id int, topic string) error }
SubscriptionService represents a service which manages subscriptions in the system.
type User ¶
type User struct { // the pk of the user. ID int `json:"id"` // name / email Name string `json:"name"` Email string `json:"email"` // apikey for the user to communicate to the api on behalf of the user. APIKey string `json:"-"` // timestamps. CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` // assosciated auths. Auths []*Auth `json:"auths"` // field to identify the user as an admin. IsAdmin bool `json:"isAdmin"` }
User represents an user in the system.
func UserFromContext ¶
UserFromContext pulls the user from context ctx.
type UserFilter ¶
type UserFilter struct { // fields to filter on. ID *int `json:"id"` Email *string `json:"email"` APIKey *string `json:"apiKey"` // restrictions on the result set, used for pagination and set limits. Offset int `json:"offset"` Limit int `json:"limit"` }
UserFilter represents a filter used by FindUsers to filter the response.
type UserService ¶
type UserService interface { // FindUserByID returns a user based on id. // returns ENOTFOUND if the user doesent exist. FindUserByID(ctx context.Context, id int) (*User, error) // FindUsers returns a range of users and the length of the range. If filter // is specified FindUsers will apply the filter to return set response. FindUsers(ctx context.Context, filter UserFilter) ([]*User, int, error) // CreateUser creates an user. To only be used in testing, the main pipeline when creating an user // starts over at CreateAuth -> ./auth.go CreateUser(ctx context.Context, user *User) error // UpdateUser updates a user based on the update field. // returns ENOTFOUND if the user doesent exist. // returns EUHATHORIZED if the caller isnt trying to update himself. UpdateUser(ctx context.Context, id int, update UserUpdate) (*User, error) // DeleteUser permanently deletes a user. This also permanently deletes all of the users assosiacions // such as: auths, comments. // returns ENOTFOUND if user doesent exist. // returns EUHATHORIZED if the caller isnt trying to delete himself. DeleteUser(ctx context.Context, id int) error }
UserService represents a service which manages users in the system.
type UserUpdate ¶
type UserUpdate struct { // fields which can be updated. Name *string `json:"name"` Email *string `json:"email"` ApiKey *string `json:"apiKey"` // TODO: test api key update. }
UserUpdate represents an update used by UpdateUser to update a user.