bab29a83fa
Sweep all .go imports + go.mod, plus module-path refs in .golangci.yml, Dockerfile, swagger templates, locale example, and repo/wiki URLs (MokoGitea-Fork -> MokoGIT). Part of the MokoGIT rebrand. Claude-Session: https://claude.ai/code/session_01Bqe7fAuHQeiLueYfeHFrHw
106 lines
3.2 KiB
Go
106 lines
3.2 KiB
Go
// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package licensing
|
|
|
|
import (
|
|
"context"
|
|
|
|
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/models/db"
|
|
"code.mokoconsulting.tech/MokoConsulting/MokoGIT/modules/timeutil"
|
|
)
|
|
|
|
func init() {
|
|
db.RegisterModel(new(LicenseActivation))
|
|
}
|
|
|
|
// LicenseActivation tracks a domain that has activated a license.
|
|
type LicenseActivation struct {
|
|
ID int64 `xorm:"pk autoincr"`
|
|
LicenseID int64 `xorm:"INDEX NOT NULL"`
|
|
Domain string `xorm:"VARCHAR(255) NOT NULL"`
|
|
IPAddress string `xorm:"VARCHAR(64)"`
|
|
JoomlaVer string `xorm:"VARCHAR(20)"`
|
|
ActivatedAt timeutil.TimeStamp `xorm:"CREATED"`
|
|
LastSeenAt timeutil.TimeStamp
|
|
}
|
|
|
|
func (LicenseActivation) TableName() string {
|
|
return "license_activation"
|
|
}
|
|
|
|
// GetActivationsByLicense returns all domain activations for a license.
|
|
func GetActivationsByLicense(ctx context.Context, licenseID int64) ([]*LicenseActivation, error) {
|
|
var acts []*LicenseActivation
|
|
return acts, db.GetEngine(ctx).Where("license_id = ?", licenseID).Find(&acts)
|
|
}
|
|
|
|
// CountActivations returns the number of activated domains for a license.
|
|
func CountActivations(ctx context.Context, licenseID int64) (int64, error) {
|
|
return db.GetEngine(ctx).Where("license_id = ?", licenseID).Count(new(LicenseActivation))
|
|
}
|
|
|
|
// ActivateDomain registers a domain for a license. Returns the activation
|
|
// (existing or new) and whether it was newly created.
|
|
func ActivateDomain(ctx context.Context, licenseID int64, domain, ip, joomlaVer string, maxDomains int) (*LicenseActivation, bool, error) {
|
|
// Check if already activated
|
|
existing := new(LicenseActivation)
|
|
has, err := db.GetEngine(ctx).
|
|
Where("license_id = ? AND domain = ?", licenseID, domain).
|
|
Get(existing)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
if has {
|
|
// Update last seen
|
|
existing.LastSeenAt = timeutil.TimeStampNow()
|
|
existing.IPAddress = ip
|
|
if joomlaVer != "" {
|
|
existing.JoomlaVer = joomlaVer
|
|
}
|
|
_, _ = db.GetEngine(ctx).ID(existing.ID).Cols("last_seen_at", "ip_address", "joomla_ver").Update(existing)
|
|
return existing, false, nil
|
|
}
|
|
|
|
// Check domain limit (0 = unlimited)
|
|
if maxDomains > 0 {
|
|
count, err := CountActivations(ctx, licenseID)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
if count >= int64(maxDomains) {
|
|
return nil, false, ErrDomainLimitReached{LicenseID: licenseID, Max: maxDomains}
|
|
}
|
|
}
|
|
|
|
act := &LicenseActivation{
|
|
LicenseID: licenseID,
|
|
Domain: domain,
|
|
IPAddress: ip,
|
|
JoomlaVer: joomlaVer,
|
|
}
|
|
_, err = db.GetEngine(ctx).Insert(act)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
return act, true, nil
|
|
}
|
|
|
|
// DeactivateDomain removes a domain activation.
|
|
func DeactivateDomain(ctx context.Context, licenseID int64, domain string) error {
|
|
_, err := db.GetEngine(ctx).
|
|
Where("license_id = ? AND domain = ?", licenseID, domain).
|
|
Delete(new(LicenseActivation))
|
|
return err
|
|
}
|
|
|
|
// ErrDomainLimitReached is returned when a license has reached its max activated domains.
|
|
type ErrDomainLimitReached struct {
|
|
LicenseID int64
|
|
Max int
|
|
}
|
|
|
|
func (e ErrDomainLimitReached) Error() string {
|
|
return "license domain limit reached"
|
|
}
|