120 lines
3.3 KiB
Go
120 lines
3.3 KiB
Go
package migrations
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.handmade.network/hmn/hmn/src/migration/types"
|
|
"git.handmade.network/hmn/hmn/src/oops"
|
|
"github.com/jackc/pgx/v5"
|
|
)
|
|
|
|
func init() {
|
|
registerMigration(DeleteInactiveUsers{})
|
|
}
|
|
|
|
type DeleteInactiveUsers struct{}
|
|
|
|
func (m DeleteInactiveUsers) Version() types.MigrationVersion {
|
|
return types.MigrationVersion(time.Date(2021, 8, 8, 13, 46, 55, 0, time.UTC))
|
|
}
|
|
|
|
func (m DeleteInactiveUsers) Name() string {
|
|
return "DeleteInactiveUsers"
|
|
}
|
|
|
|
func (m DeleteInactiveUsers) Description() string {
|
|
return "Delete inactive users and expired onetimetokens"
|
|
}
|
|
|
|
func (m DeleteInactiveUsers) Up(ctx context.Context, tx pgx.Tx) error {
|
|
var err error
|
|
res, err := tx.Exec(ctx,
|
|
`
|
|
DELETE FROM handmade_passwordresetrequest
|
|
USING handmade_onetimetoken
|
|
WHERE handmade_onetimetoken.expires < $1 AND handmade_passwordresetrequest.confirmation_token_id = handmade_onetimetoken.id;
|
|
`,
|
|
time.Now(),
|
|
)
|
|
if err != nil {
|
|
return oops.New(err, "failed to delete password reset requests")
|
|
}
|
|
fmt.Printf("Deleted %v expired password reset requests.\n", res.RowsAffected())
|
|
|
|
fmt.Printf("Deleting inactive users. This might take a minute.\n")
|
|
res, err = tx.Exec(ctx,
|
|
`
|
|
DELETE FROM auth_user
|
|
WHERE status = 1 AND date_joined < $1;
|
|
`,
|
|
time.Now().Add(-(time.Hour * 24 * 7)),
|
|
)
|
|
if err != nil {
|
|
return oops.New(err, "failed to delete inactive users")
|
|
}
|
|
fmt.Printf("Deleted %v inactive users.\n", res.RowsAffected())
|
|
|
|
_, err = tx.Exec(ctx, `
|
|
ALTER TABLE handmade_onetimetoken
|
|
DROP used;
|
|
ALTER TABLE handmade_onetimetoken
|
|
ADD owner_id INT REFERENCES auth_user(id) ON DELETE CASCADE;
|
|
|
|
ALTER TABLE handmade_userpending
|
|
DROP CONSTRAINT handma_activation_token_id_0b4a4b06_fk_handmade_onetimetoken_id;
|
|
`)
|
|
|
|
_, err = tx.Exec(ctx, `
|
|
UPDATE handmade_userpending
|
|
SET activation_token_id = NULL
|
|
WHERE (SELECT count(*) AS ct FROM handmade_onetimetoken WHERE id = activation_token_id) = 0;
|
|
`)
|
|
|
|
res, err = tx.Exec(ctx,
|
|
`
|
|
DELETE FROM handmade_onetimetoken
|
|
WHERE expires < $1
|
|
`,
|
|
time.Now(),
|
|
)
|
|
if err != nil {
|
|
return oops.New(err, "failed to delete expired tokens")
|
|
}
|
|
fmt.Printf("Deleted %v expired tokens.\n", res.RowsAffected())
|
|
|
|
fmt.Printf("Setting owner_id on onetimetoken\n")
|
|
_, err = tx.Exec(ctx, `
|
|
UPDATE handmade_onetimetoken
|
|
SET owner_id = (SELECT id FROM auth_user WHERE username = (SELECT username FROM handmade_userpending WHERE activation_token_id = handmade_onetimetoken.id LIMIT 1))
|
|
WHERE token_type = 1;
|
|
`)
|
|
if err != nil {
|
|
return oops.New(err, "failed to set owner_id on onetimetoken")
|
|
}
|
|
_, err = tx.Exec(ctx, `
|
|
UPDATE handmade_onetimetoken
|
|
SET owner_id = (SELECT user_id FROM handmade_passwordresetrequest WHERE confirmation_token_id = handmade_onetimetoken.id)
|
|
WHERE token_type = 2;
|
|
`)
|
|
if err != nil {
|
|
return oops.New(err, "failed to set owner_id on onetimetoken")
|
|
}
|
|
|
|
fmt.Printf("Setting registration_ip on auth_user\n")
|
|
_, err = tx.Exec(ctx, `
|
|
UPDATE auth_user
|
|
SET registration_ip = (SELECT ip FROM handmade_userpending WHERE handmade_userpending.username = auth_user.username LIMIT 1);
|
|
`)
|
|
if err != nil {
|
|
return oops.New(err, "failed to set owner_id on onetimetoken")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m DeleteInactiveUsers) Down(ctx context.Context, tx pgx.Tx) error {
|
|
panic("Implement me")
|
|
}
|