Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
alankm committed Jan 5, 2016
1 parent 5c380dd commit 2b6157a
Show file tree
Hide file tree
Showing 8 changed files with 1,299 additions and 1 deletion.
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
language: go
sudo: false
go:
- tip
before_install:
- go get github.com/axw/gocov/gocov
- go get github.com/mattn/goveralls
- go get github.com/modocache/gover
- if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
script:
- go test -coverprofile=privileges.coverprofile
- $HOME/gopath/bin/gover
- $HOME/gopath/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright {yyyy} {name of copyright owner}
Copyright 2016 Sisa-Tech Pty Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
![travis](https://travis-ci.org/alankm/privileges.svg)
[![Coverage Status](https://coveralls.io/repos/alankm/privileges/badge.svg?branch=master&service=github)](https://coveralls.io/github/alankm/privileges?branch=master)

# privileges
A golang package to implement *nix style file permissions including users and groups management.
248 changes: 248 additions & 0 deletions commands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
package privileges

import (
"database/sql"
"errors"
)

var (
errDenied = errors.New("access denied")
)

// Privileges provides a handle to access the Privileges database and methods.
type Privileges struct {
db *sql.DB
path string
}

// Key contains validation information required to determine what permissions
// the user has when they attempt to execute any functions.
type Key struct {
p *Privileges
username string
hashword string
}

// New creates the privileges database at the provided path and returns a handle
// for use by other packages.
func New(path string) (*Privileges, error) {

return loadDatabase(path)

}

// Login takes a raw username and password string provided by a client and
// returns a key with their credentials for Privileges functions if the
// credentials are accepted. Otherwise an error is thrown.
func (p *Privileges) Login(username, password string) (*Key, error) {

key := new(Key)
key.username = username
key.p = p
err := p.login(key, password)
return key, err

}

// NewUser creates a new user with the provided username and password. The new
// user will not be part of any groups. Errors should only return if the user
// already exists or if the key does not have permission.
func (key *Key) NewUser(username, password string) error {

if key.valid() && key.su() {
return key.p.newUser(username, password)
}

return errDenied

}

// SetPassword changes a users password. If there exists a user with the
// username, that user's password will be changed to the provided password as
// long as the key has permission to do so (is the key of the user being changed
// or is the key of a user with super user privileges)
func (key *Key) SetPassword(user, password string) error {

if key.valid() {

if key.username == user {

key.p.changePassword(user, password)
k, err := key.p.Login(user, password)
key.hashword = k.hashword
return err

} else if key.su() {
return key.p.changePassword(user, password)
}

}

return errDenied

}

// DeleteUser deletes the user with the given username, as long as the provided
// key has super user privileges and the target isn't root or the key.
func (key *Key) DeleteUser(user string) error {

if key.valid() && key.su() {
if user != key.username && user != rootName {
return key.p.deleteUser(user)
}
}

return errDenied

}

// NewGroup creates a new group with the provided name. Only returns error if
// a group with that name already exists or if a bad key was provided.
func (key *Key) NewGroup(name string) error {

if key.valid() && key.su() {
return key.p.newGroup(name)
}

return errDenied

}

// DeleteGroup deletes the group with the given name, as long as the provided
// key has super user privileges and the target isn't the root group.
func (key *Key) DeleteGroup(group string) error {

if key.valid() && key.su() {
if !(group == rootGroup) {
return key.p.deleteGroup(group)
}
}

return errDenied

}

// SetGid changes the user's gid to the provided group, provided that it exists.
func (key *Key) SetGid(user, group string) error {

if key.valid() {
if key.su() || (user == key.username && key.p.inGroup(user, group)) {
return key.p.setGid(user, group)
}
}

return errDenied

}

// Gid returns the user's gid.
func (key *Key) Gid(user string) string {

return key.p.gid(user)

}

// AddToGroup adds an existing user to an existing group. Returns an error if
// the key is invalid or if the username or group do not exist.
func (key *Key) AddToGroup(user, group string) error {

if key.valid() && key.su() {
return key.p.addToGroup(user, group)
}

return errDenied

}

// InGroup returns true only if the provided key, username, and groupname
// are all valid, and the user is a member of the group. Otherwise false.
func (key *Key) InGroup(user, group string) bool {

return key.p.inGroup(user, group)

}

// RemoveFromGroup removes the user from the group as long as the provided key
// has super user privileges and it is not attempting to remove root from the
// root group.
func (key *Key) RemoveFromGroup(user, group string) error {

if key.valid() && key.su() {
if !(user == rootName && group == rootGroup) {
return key.p.removeFromGroup(user, group)
}
}

return errDenied

}

// ListUsers returns a list of all the users in the system. No key is required.
func (key *Key) ListUsers() []string {

return key.p.listUsers()

}

// ListGroups returns a list of groups that exist in Privileges. No key is
// required to view this list.
func (key *Key) ListGroups() []string {

return key.p.listGroups()

}

// ListUsersGroups returns a list of all the groups a user belongs to. No key
// is required to view this list.
func (key *Key) ListUsersGroups(user string) []string {

return key.p.listUsersGroups(user)

}

// ListUsersWithGid returns a list of all the users who currently have their gid
// set to the provided group.
func (key *Key) ListUsersWithGid(group string) []string {

return key.p.listUsersWithGid(group)

}

// Chmod aims to be identical to the linux command as much as possible.
func (key *Key) Chmod(mod string, obj PrivelegedObject) error {

if key.valid() && (key.su() || obj.Permissions().Owner() == key.username) {
return obj.Permissions().set(mod)
}

return errDenied

}

// Chown aims to be identical to the linux command as much as possible.
func (key *Key) Chown(user string, obj PrivelegedObject) error {

if key.valid() && key.su() && key.p.isUser(user) {
obj.Permissions().owner = user
return nil
}

return errDenied

}

// Chgrp aims to be identical to the linux command as much as possible.
func (key *Key) Chgrp(group string, obj PrivelegedObject) error {

if key.valid() && key.p.isGroup(group) {

if key.su() || (obj.Permissions().owner == key.username && key.p.inGroup(key.username, group)) {
obj.Permissions().group = group
return nil
}

}

return errDenied

}

0 comments on commit 2b6157a

Please sign in to comment.