diff --git a/core/data/alembic/versions/5ea73f89d982_card_add_memo.py b/core/data/alembic/versions/5ea73f89d982_card_add_memo.py
new file mode 100644
index 0000000..84c8a18
--- /dev/null
+++ b/core/data/alembic/versions/5ea73f89d982_card_add_memo.py
@@ -0,0 +1,28 @@
+"""card_add_memo
+
+Revision ID: 5ea73f89d982
+Revises: 745448d83696
+Create Date: 2024-07-06 22:46:56.992152
+
+"""
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects import mysql
+
+# revision identifiers, used by Alembic.
+revision = '5ea73f89d982'
+down_revision = '745448d83696'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column('aime_card', sa.Column('memo', sa.VARCHAR(length=16), nullable=True))
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_column('aime_card', 'memo')
+ # ### end Alembic commands ###
diff --git a/core/data/schema/card.py b/core/data/schema/card.py
index 6205b4c..1865539 100644
--- a/core/data/schema/card.py
+++ b/core/data/schema/card.py
@@ -1,6 +1,6 @@
from typing import Dict, List, Optional
from sqlalchemy import Table, Column, UniqueConstraint
-from sqlalchemy.types import Integer, String, Boolean, TIMESTAMP, BIGINT
+from sqlalchemy.types import Integer, String, Boolean, TIMESTAMP, BIGINT, VARCHAR
from sqlalchemy.sql.schema import ForeignKey
from sqlalchemy.sql import func
from sqlalchemy.engine import Row
@@ -19,6 +19,7 @@ aime_card = Table(
Column("last_login_date", TIMESTAMP, onupdate=func.now()),
Column("is_locked", Boolean, server_default="0"),
Column("is_banned", Boolean, server_default="0"),
+ Column("memo", VARCHAR(16)),
UniqueConstraint("user", "access_code", name="aime_card_uk"),
mysql_charset="utf8mb4",
)
@@ -148,6 +149,11 @@ class CardData(BaseData):
if not result:
self.logger.error(f"Failed to change card access code from {old_ac} to {new_ac}")
+ async def set_memo_by_access_code(self, access_code: str, memo: str) -> None:
+ result = await self.execute(aime_card.update(aime_card.c.access_code == access_code).values(memo=memo))
+ if not result:
+ self.logger.error(f"Failed to add memo to card {access_code}")
+
def to_access_code(self, luid: str) -> str:
"""
Given a felica cards internal 16 hex character luid, convert it to a 0-padded 20 digit access code as a string
diff --git a/core/frontend.py b/core/frontend.py
index f15f58a..1d19bfe 100644
--- a/core/frontend.py
+++ b/core/frontend.py
@@ -476,10 +476,10 @@ class FE_User(FE_Base):
card_data.append({
'access_code': ac,
'status': status,
- 'chip_id': "", #None if c['chip_id'] is None else f"{c['chip_id']:X}",
- 'idm': "",
+ 'chip_id': c['chip_id'],
+ 'idm': c['idm'],
'type': c_type,
- "memo": ""
+ "memo": c['memo']
})
if "e" in request.query_params:
@@ -516,7 +516,42 @@ class FE_User(FE_Base):
return resp
async def edit_card(self, request: Request) -> RedirectResponse:
- return RedirectResponse("/user/", 303)
+ frm = await request.form()
+ usr_sesh = self.validate_session(request)
+ if not usr_sesh or not self.test_perm(usr_sesh.permissions, PermissionOffset.USERMOD):
+ return RedirectResponse("/gate/", 303)
+
+ frm = await request.form()
+ ac = frm.get("add_access_code", None)
+ if not ac:
+ return RedirectResponse("/user/?e=999", 303)
+
+ card = await self.data.card.get_card_by_access_code(ac)
+ if not card:
+ return RedirectResponse("/user/?e=2", 303)
+
+ if card['user'] != usr_sesh.user_id and not self.test_perm_minimum(usr_sesh.permissions, PermissionOffset.USERMOD):
+ return RedirectResponse("/user/?e=11", 303)
+
+ if frm.get("add_memo", None):
+ memo = frm.get("add_memo")
+ if len(memo) > 16 or len(memo) == 0:
+ return RedirectResponse("/user/?e=4", 303)
+ await self.data.card.set_memo_by_access_code(ac, memo)
+
+ if frm.get("add_felica_idm", None):
+ idm = frm.get('add_felica_idm')
+ if not all(c in string.hexdigits for c in idm):
+ return RedirectResponse("/user/?e=4", 303)
+ await self.data.card.set_idm_by_access_code(ac, idm)
+
+ if frm.get("add_mifare_chip_id", None):
+ chip_id: str = frm.get('add_mifare_chip_id')
+ if not all(c in string.hexdigits for c in idm):
+ return RedirectResponse("/user/?e=4", 303)
+ await self.data.card.set_chip_id_by_access_code(ac, int(chip_id, 16))
+
+ return RedirectResponse("/user/?s=4", 303)
async def add_card(self, request: Request) -> RedirectResponse:
return RedirectResponse("/user/", 303)
diff --git a/core/templates/user/index.jinja b/core/templates/user/index.jinja
index 1b6ec1d..578702c 100644
--- a/core/templates/user/index.jinja
+++ b/core/templates/user/index.jinja
@@ -49,11 +49,14 @@ function prep_edit_form(access_code, chip_id, idm, card_type, u_memo) {
fidm.value = idm;
memo.value = u_memo;
- if (card_type == "AmusementIC") {
+ if (access_code.startsWith("3") || access_code.startsWith("010")) {
+ cid.disabled = false;
+ fidm.disabled = true;
+ } else if (access_code.startsWith("5")) {
cid.disabled = true;
fidm.disabled = false;
} else {
- cid.disabled = false;
+ cid.disabled = true;
fidm.disabled = true;
}
}
@@ -91,9 +94,14 @@ Card added successfully
+{% if success is defined and success == 4 %}
+