Skip to content

Commit

Permalink
Initial development of the API endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
alexyz79 committed Sep 16, 2024
1 parent c8ec7a4 commit 23b62b2
Show file tree
Hide file tree
Showing 16 changed files with 772 additions and 265 deletions.
60 changes: 60 additions & 0 deletions pkg/auth/authproviders/fileprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,63 @@ func (a *FileAuthProvider) LoadUsers() error {
}
return nil
}

func (a *FileAuthProvider) GetRole(username string) (string, error) {
err := a.LoadUsers()
if err != nil {
return "", err
}
a.userStoreMux.Lock()
defer a.userStoreMux.Unlock()
for i, user := range a.users.Users {
if user.Username == username {
return a.users.Users[i].Role, nil
}
}

return "", fmt.Errorf("user not found")
}

func (a *FileAuthProvider) GetUser(username string) (UserView, error) {
err := a.LoadUsers()
if err != nil {
return UserView{}, err
}
a.userStoreMux.Lock()
defer a.userStoreMux.Unlock()
for i, user := range a.users.Users {
if user.Username == username {
return UserView{
Username: a.users.Users[i].Username,
Role: a.users.Users[i].Role,
}, nil
}
}
return UserView{}, fmt.Errorf("user not found")
}

func (a *FileAuthProvider) SetRole(username, role string) error {
err := a.LoadUsers()
if err != nil {
return err
}
a.userStoreMux.Lock()
defer a.userStoreMux.Unlock()
for i, user := range a.users.Users {
if user.Username == username {
a.users.Users[i].Role = role
data, err := json.MarshalIndent(a.users, "", " ")
if err != nil {
return err
}
file, err := os.Create(a.config.FilePath)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(data)
return err
}
}
return fmt.Errorf("user not found")
}
39 changes: 32 additions & 7 deletions pkg/auth/authproviders/memoryprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ import (

type MemoryAuthProvide struct {
AuthProvider
users map[string]string
users map[string]*User
}

func NewMemoryAuthProvider(config json.RawMessage) AuthProvider {
return &MemoryAuthProvide{
users: make(map[string]string),
users: make(map[string]*User),
}
}

func (a *MemoryAuthProvide) AuthenticateUser(username, password string) bool {
if storedPassword, ok := a.users[username]; ok {
return storedPassword == HashPassword(password)
if user, ok := a.users[username]; ok {
return user.Password == HashPassword(password)
}
return false
}
Expand All @@ -50,7 +50,7 @@ func (a *MemoryAuthProvide) AddUser(username, password string) error {
return fmt.Errorf("user already exists")
}

a.users[username] = HashPassword(password)
a.users[username].Password = HashPassword(password)
return nil
}

Expand All @@ -77,15 +77,40 @@ func (a *MemoryAuthProvide) ChangePassword(username, password string) error {
return fmt.Errorf("user does not exist")
}

a.users[username] = HashPassword(password)
a.users[username].Password = HashPassword(password)
return nil
}

func (a *MemoryAuthProvide) DropUsers() error {
a.users = make(map[string]string)
a.users = make(map[string]*User)
return nil
}

func (a *MemoryAuthProvide) LoadUsers() error {
return fmt.Errorf("not implemented")
}

func (a *MemoryAuthProvide) GetRole(username string) (string, error) {
if user, ok := a.users[username]; ok {
return user.Role, nil
}
return "", fmt.Errorf("user does not exist")
}

func (a *MemoryAuthProvide) GetUser(username string) (UserView, error) {
if user, ok := a.users[username]; ok {
return UserView{
Username: user.Username,
Role: user.Role,
}, nil
}
return UserView{}, fmt.Errorf("user does not exist")
}

func (a *MemoryAuthProvide) SetRole(username, role string) error {
if user, ok := a.users[username]; ok {
user.Role = role
return nil
}
return fmt.Errorf("user does not exist")
}
15 changes: 15 additions & 0 deletions pkg/auth/authproviders/nullprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,18 @@ func (a *NullAuthProvider) DropUsers() error {
func (a *NullAuthProvider) LoadUsers() error {
return fmt.Errorf("not implemented")
}

func (a *NullAuthProvider) GetRole(username string) (string, error) {
if username == "admin" {
return "admin", nil
}
return "viewer", nil
}

func (a *NullAuthProvider) GetUser(username string) (UserView, error) {
return UserView{}, fmt.Errorf("not implemented")
}

func (a *NullAuthProvider) SetRole(username, role string) error {
return fmt.Errorf("not implemented")
}
19 changes: 19 additions & 0 deletions pkg/auth/authproviders/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ type AuthProvider interface {
AuthenticateUser(username, password string) bool
AddUser(username, password string) error
RemoveUser(username string) error
GetRole(username string) (string, error)
SetRole(username, role string) error
GetUsers() ([]string, error)
ChangePassword(username, password string) error
DropUsers() error
LoadUsers() error
GetUser(username string) (UserView, error)
}

type AuthProviderFactory func(config json.RawMessage) AuthProvider
Expand Down Expand Up @@ -72,6 +75,10 @@ func DropUsers() error {
return authProvider.DropUsers()
}

func GetRole(username string) (string, error) {
return authProvider.GetRole(username)
}

func InitializeAuthProvider(provider string, config json.RawMessage) error {
switch provider {
case "file":
Expand All @@ -85,3 +92,15 @@ func InitializeAuthProvider(provider string, config json.RawMessage) error {
}
return nil
}

func LoadUsers() error {
return authProvider.LoadUsers()
}

func GetUser(username string) (UserView, error) {
return authProvider.GetUser(username)
}

func SetRole(username, role string) error {
return authProvider.SetRole(username, role)
}
6 changes: 6 additions & 0 deletions pkg/auth/authproviders/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ package authproviders
type User struct {
Username string `json:"username"`
Password string `json:"password"`
Role string `json:"role"`
}

type UserView struct {
Username string `json:"username"`
Role string `json:"role"`
}

type Users struct {
Expand Down
12 changes: 12 additions & 0 deletions pkg/auth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ func InitializeAuth(data json.RawMessage) error {
return authproviders.InitializeAuthProvider(authConfig.Provider, authConfig.Settings)
}

func GetRole(username string) (string, error) {
return authproviders.GetRole(username)
}

func CheckCredentials(username, password string) bool {
return authproviders.AuthenticateUser(username, password)
}
Expand All @@ -82,3 +86,11 @@ func ChangePassword(username, password string) error {
func DropUsers() error {
return authproviders.DropUsers()
}

func GetUser(username string) (authproviders.UserView, error) {
return authproviders.GetUser(username)
}

func SetRole(username, role string) error {
return authproviders.SetRole(username, role)
}
33 changes: 30 additions & 3 deletions pkg/auth/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"github.com/golang-jwt/jwt/v5"
)

func createJWT(userID string) (string, error) {
func createJWT(userID, role string) (string, error) {
// Define token expiration time
expirationTime := time.Now().Add(time.Hour * time.Duration(authConfig.ExpirationTime)) // 1 hour expiry

Expand All @@ -37,7 +37,7 @@ func createJWT(userID string) (string, error) {
"sub": userID, // Subject or user ID
"exp": expirationTime.Unix(), // Expiration time
"iat": time.Now().Unix(), // Issued at time
"role": "user", // Custom claim (e.g., user role)
"role": role, // Custom claim (e.g., user role)
}

// Create a new token using the HS256 signing method
Expand Down Expand Up @@ -76,8 +76,13 @@ func verifyJWT(tokenString string) (jwt.MapClaims, error) {
}

func CreateToken(userId, password string) (string, error) {

if CheckCredentials(userId, password) {
return createJWT(userId)
role, err := GetRole(userId)
if err != nil || role == "" {
role = "viewer"
}
return createJWT(userId, role)
}
return "", fmt.Errorf("invalid credentials")
}
Expand All @@ -99,3 +104,25 @@ func VerifyToken(token string) bool {
_, err := verifyJWT(token)
return err == nil
}

func GetRoleFromToken(token string) (string, error) {
claims, err := verifyJWT(token)
if err != nil {
return "", err
}
if role, ok := claims["role"].(string); ok {
return role, nil
}
return "", fmt.Errorf("role not found")
}

func GetUserFromToken(token string) (string, error) {
claims, err := verifyJWT(token)
if err != nil {
return "", err
}
if sub, ok := claims["sub"].(string); ok {
return sub, nil
}
return "", fmt.Errorf("user id not found")
}
11 changes: 11 additions & 0 deletions pkg/m3uprovider/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,14 @@ func LoadFromFile(path string) (*m3uparser.M3UPlaylist, error) {

return Load(config)
}

func LoadFromBytes(data []byte) (*m3uparser.M3UPlaylist, error) {

config := PlaylistConfig{}
err := json.Unmarshal(data, &config)
if err != nil {
return nil, err
}

return Load(config)
}
Loading

0 comments on commit 23b62b2

Please sign in to comment.