<commit_before>package models

import (
	"encoding/json"
	"fmt"
	"reflect"
	"regexp"
	"time"

	"github.com/dockercn/docker-bucket/utils"
)

const (
	ORG_MEMBER = "M"
	ORG_OWNER  = "O"
)

type User struct {
	Username      string //
	Password      string //
	Repositories  string //用户的所有 Respository
	Organizations string //用户所属的所有组织
	Email         string //Email 可以更换，全局唯一
	Fullname      string //
	Company       string //
	Location      string //
	Mobile        string //
	URL           string //
	Gravatar      string //如果是邮件地址使用 gravatar.org 的 API 显示头像，如果是上传的用户显示头像的地址。
	Created       int64  //
	Updated       int64  //
}

//在全局 user 存储的的 Hash 中查询到 user 的 key，然后根据 key 再使用 Exists 方法查询是否存在数据
func (user *User) Has(username string) (bool, []byte, error) {
	if key, err := LedisDB.HGet([]byte(GetServerKeys("user")), []byte(GetObjectKey("user", username))); err != nil {
		return false, []byte(""), err
	} else if key != nil {
		if name, err := LedisDB.HGet(key, []byte("Username")); err != nil {
			return false, []byte(""), err
		} else if name != nil {
			//已经存在了用户的 Key，接着判断用户是否相同
			if string(name) != username {
				return true, key, fmt.Errorf("已经存在了 Key，但是用户名不相同 %s ", name)
			}
			return true, key, nil
		} else {
			return false, []byte(""), nil
		}
	} else {
		return false, []byte(""), nil
	}
}

//创建用户数据，如果存在返回错误信息。
func (user *User) Put(username string, passwd string, email string) error {
	//检查用户的 Key 是否存在
	if has, _, err := user.Has(username); err != nil {
		return err
	} else if has == true {
		//已经存在用户
		return fmt.Errorf("已经存在用户 %s", username)
	} else {
		//检查用户名和 Organization 的 Name 是不是冲突
		org := new(Organization)
		if h, _, e := org.Has(username); e != nil {
			return err
		} else if h == true {
			return fmt.Errorf("已经存在相同名称的组织 %s", username)
		}

		//检查用户名合法性，参考实现标准：
		//https://github.com/docker/docker/blob/28f09f06326848f4117baf633ec9fc542108f051/registry/registry.go#L27
		validNamespace := regexp.MustCompile(`^([a-z0-9_]{4,30})$`)
		if !validNamespace.MatchString(username) {
			return fmt.Errorf("用户名必须是 4 - 30 位之间，且只能由 a-z，0-9 和 下划线组成")
		}

		//检查密码合法性
		if len(passwd) < 5 {
			return fmt.Errorf("密码必须等于或大于 5 位字符以上")
		}

		//检查邮箱合法性
		validEmail := regexp.MustCompile(`^[a-z0-9A-Z]+([\-_\.][a-z0-9A-Z]+)*@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)*\.)+[a-zA-Z]+$`)
		if !validEmail.MatchString(email) {
			return fmt.Errorf("Email 格式不合法")
		}

		//生成随机的 Object Key
		key := utils.GeneralKey(username)

		user.Username = username
		user.Password = <PASSWORD>
		user.Email = email

		user.Updated = time.Now().Unix()
		user.Created = time.Now().Unix()

		//保存 User 对象的数据
		if err := user.Save(key); err != nil {
			return err
		} else {
			//在全局 @user 数据中保存 key 信息
			if _, err := LedisDB.HSet([]byte(GetServerKeys("user")), []byte(GetObjectKey("user", username)), key); err != nil {
				return err
			}

			return nil
		}
	}
}

//根据用户名和密码获取用户
func (user *User) Get(username, passwd string) (bool, error) {
	//检查用户的 Key 是否存在
	if has, key, err := user.Has(username); err != nil {
		return false, err
	} else if has == true {
		//读取密码的值进行判断是否密码相同
		if password, err := LedisDB.HGet(key, []byte("Password")); err != nil {
			return false, err
		} else {
			if string(password) != passwd {
				return false, nil
			}
			return true, nil
		}
	} else {
		//没有用户的 Key 存在
		return false, fmt.Errorf("不存在 %s 的用户数据", username)
	}
}

//重置用户的密码
func (user *User) ResetPasswd(username, password string) error {
	//检查用户的 Key 是否存在
	if has, key, err := user.Has(username); err != nil {
		return err
	} else if has == true {
		user.Password = password

		if err := user.Save(key); err != nil {
			return err
		}
	} else {
		//没有用户的 Key 存在
		return fmt.Errorf("不存在 %s 的用户数据", username)
	}

	return nil
}

//用户创建镜像仓库后，在 user 的 Repositories 字段保存相应的记录
//repository 字段是 Repository 的全局 Key
func (user *User) AddRepository(username, repository, key string) error {
	var (
		u   []byte
		has bool
		err error
	)

	repoMap := make(map[string]string, 0)

	//检查用户的 Key 是否存在
	if has, u, err = user.Has(username); err != nil {
		return err
	} else if has == true {
		if repo, err := LedisDB.HGet(u, []byte("Repositories")); err != nil {
			return err
		} else if repo != nil {
			if e := json.Unmarshal(repo, &repoMap); e != nil {
				return nil
			}
			if value, exist := repoMap[repository]; exist == true && value == key {
				return fmt.Errorf("已经存在了 Repository 数据")
			}
		}
	} else if has == false {
		return fmt.Errorf("不存在 %s 的用户数据", username)
	}

	//在 Map 中增加 repository 记录
	repoMap[repository] = key
	//JSON Marshall
	repo, _ := json.Marshal(repoMap)

	if _, err := LedisDB.HSet(u, []byte("Repositories"), repo); err != nil {
		return err
	}

	return nil
}

//用户删除镜像仓库后，在 user 的 Repositories 中删除相应的记录
func (user *User) RemoveRepository(username, repository string) error {
	return nil
}

//向用户添加 Organization 数据
func (user *User) AddOrganization(username, org, member string) error {
	return nil<commit_msg>修改 AddRepository 方法中 repoMap 的变量命名；增加 RemoveRepository 方法<commit_after>package models

import (
	"encoding/json"
	"fmt"
	"reflect"
	"regexp"
	"time"

	"github.com/dockercn/docker-bucket/utils"
)

const (
	ORG_MEMBER = "M"
	ORG_OWNER  = "O"
)

type User struct {
	Username      string //
	Password      string //
	Repositories  string //用户的所有 Respository
	Organizations string //用户所属的所有组织
	Email         string //Email 可以更换，全局唯一
	Fullname      string //
	Company       string //
	Location      string //
	Mobile        string //
	URL           string //
	Gravatar      string //如果是邮件地址使用 gravatar.org 的 API 显示头像，如果是上传的用户显示头像的地址。
	Created       int64  //
	Updated       int64  //
}

//在全局 user 存储的的 Hash 中查询到 user 的 key，然后根据 key 再使用 Exists 方法查询是否存在数据
func (user *User) Has(username string) (bool, []byte, error) {
	if key, err := LedisDB.HGet([]byte(GetServerKeys("user")), []byte(GetObjectKey("user", username))); err != nil {
		return false, []byte(""), err
	} else if key != nil {
		if name, err := LedisDB.HGet(key, []byte("Username")); err != nil {
			return false, []byte(""), err
		} else if name != nil {
			//已经存在了用户的 Key，接着判断用户是否相同
			if string(name) != username {
				return true, key, fmt.Errorf("已经存在了 Key，但是用户名不相同 %s ", name)
			}
			return true, key, nil
		} else {
			return false, []byte(""), nil
		}
	} else {
		return false, []byte(""), nil
	}
}

//创建用户数据，如果存在返回错误信息。
func (user *User) Put(username string, passwd string, email string) error {
	//检查用户的 Key 是否存在
	if has, _, err := user.Has(username); err != nil {
		return err
	} else if has == true {
		//已经存在用户
		return fmt.Errorf("已经存在用户 %s", username)
	} else {
		//检查用户名和 Organization 的 Name 是不是冲突
		org := new(Organization)
		if h, _, e := org.Has(username); e != nil {
			return err
		} else if h == true {
			return fmt.Errorf("已经存在相同名称的组织 %s", username)
		}

		//检查用户名合法性，参考实现标准：
		//https://github.com/docker/docker/blob/28f09f06326848f4117baf633ec9fc542108f051/registry/registry.go#L27
		validNamespace := regexp.MustCompile(`^([a-z0-9_]{4,30})$`)
		if !validNamespace.MatchString(username) {
			return fmt.Errorf("用户名必须是 4 - 30 位之间，且只能由 a-z，0-9 和 下划线组成")
		}

		//检查密码合法性
		if len(passwd) < 5 {
			return fmt.Errorf("密码必须等于或大于 5 位字符以上")
		}

		//检查邮箱合法性
		validEmail := regexp.MustCompile(`^[a-z0-9A-Z]+([\-_\.][a-z0-9A-Z]+)*@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)*\.)+[a-zA-Z]+$`)
		if !validEmail.MatchString(email) {
			return fmt.Errorf("Email 格式不合法")
		}

		//生成随机的 Object Key
		key := utils.GeneralKey(username)

		user.Username = username
		user.Password = <PASSWORD>
		user.Email = email

		user.Updated = time.Now().Unix()
		user.Created = time.Now().Unix()

		//保存 User 对象的数据
		if err := user.Save(key); err != nil {
			return err
		} else {
			//在全局 @user 数据中保存 key 信息
			if _, err := LedisDB.HSet([]byte(GetServerKeys("user")), []byte(GetObjectKey("user", username)), key); err != nil {
				return err
			}

			return nil
		}
	}
}

//根据用户名和密码获取用户
func (user *User) Get(username, passwd string) (bool, error) {
	//检查用户的 Key 是否存在
	if has, key, err := user.Has(username); err != nil {
		return false, err
	} else if has == true {
		//读取密码的值进行判断是否密码相同
		if password, err := LedisDB.HGet(key, []byte("Password")); err != nil {
			return false, err
		} else {
			if string(password) != passwd {
				return false, nil
			}
			return true, nil
		}
	} else {
		//没有用户的 Key 存在
		return false, fmt.Errorf("不存在 %s 的用户数据", username)
	}
}

//重置用户的密码
func (user *User) ResetPasswd(username, password string) error {
	//检查用户的 Key 是否存在
	if has, key, err := user.Has(username); err != nil {
		return err
	} else if has == true {
		user.Password = password

		if err := user.Save(key); err != nil {
			return err
		}
	} else {
		//没有用户的 Key 存在
		return fmt.Errorf("不存在 %s 的用户数据", username)
	}

	return nil
}

//用户创建镜像仓库后，在 user 的 Repositories 字段保存相应的记录
//repository 字段是 Repository 的全局 Key
func (user *User) AddRepository(username, repository, key string) error {
	var (
		u   []byte
		has bool
		err error
	)

	r := make(map[string]string, 0)

	//检查用户的 Key 是否存在
	if has, u, err = user.Has(username); err != nil {
		return err
	} else if has == true {
		if repo, err := LedisDB.HGet(u, []byte("Repositories")); err != nil {
			return err
		} else if repo != nil {
			if e := json.Unmarshal(repo, &r); e != nil {
				return nil
			}
			if value, exist := r[repository]; exist == true && value == key {
				return fmt.Errorf("已经存在了镜像仓库数据")
			}
		}
	} else if has == false {
		return fmt.Errorf("不存在 %s 的用户数据", username)
	}

	//在 Map 中增加 repository 记录
	r[repository] = key
	//JSON Marshall
	repo, _ := json.Marshal(r)

	if _, err := LedisDB.HSet(u, []byte("Repositories"), repo); err != nil {
		return err
	}

	return nil
}

//用户删除镜像仓库后，在 user 的 Repositories 中删除相应的记录
func (user *User) RemoveRepository(username, repository string) error {
	var (
		u   []byte
		has bool
		err error
	)

	r := make(map[string]string, 0)

	//检查用户的 Key 是否存在
	if has, u, err = user.Has(username); err != nil {
		return err
	} else if has == true {
		if repo, err := LedisDB.HGet(u, []byte("Repositories")); err != nil {
			return err
		} else if repo != nil {
			if e := json.Unmarshal(repo, &r); e != nil {
				return nil
			}
			if _, exist := r[repository]; exist == false {
				return fmt.Errorf("不存在要删除的镜像仓库数据")
			}
		}
	} else if has == false {
		return fmt.Errorf("不存在 %s 的用户数据", username)
	}

	//在 Map 中删除 repository 记录
	delete(r, repository)
	//JSON Marshall
	repo, _ := json.Marshal(r)

	if _, err := LedisDB.HSet(u, []byte("Repositories"), repo); err != nil {
		return err
	}

	return nil
}

//向用户添加 Organization 数据
func (user *User) AddOrganization(username, org, member string) error {
	return nil
{'fraction_non_alphanumeric': 0.1551348793185045, 'fraction_numerical': 0.010695693327023189, 'mean_word_length': 3.0716763005780345, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1249574', 'n_tokens_mistral': 4775, 'n_tokens_neox': 4566, 'n_words': 1074}