async def authenticate(info: RModels.Authserver_Authenticate): user: Account = Account.get(Email=info.username) if not user: raise exceptions.InvalidCredentials() if not user_auth_cooling_bucket.get(user.Email): user_auth_cooling_bucket.setByTimedelta(user.Email, "LOCKED") else: raise exceptions.InvalidCredentials() if not bcrypt.checkpw(info.password.encode(), user.Password): raise (exceptions.InvalidCredentials()) TokenUnit = Token(user, ClientToken=info.clientToken) auth_token_pool.setByTimedelta(TokenUnit.AccessToken, TokenUnit) result = { "accessToken": TokenUnit.AccessToken.hex, "clientToken": TokenUnit.ClientToken, "availableProfiles": [ i.FormatCharacter(unsigned=True) for i in list(user.Characters) ], "selectedProfile": {} } # print(data.get("clientToken"), TokenUnit.ClientToken) if user.Characters.count() == 1: # 如果只拥有一个角色, 则自动绑定, 并修改result TokenUnit.setupCharacter(list(user.Characters)[0]) result['selectedProfile'] = list(user.Characters)[0].FormatCharacter(unsigned=True) else: del result['selectedProfile'] if info.requestUser: result['user'] = { "id": user.Id.hex, "properties": [] } return Response(result)
async def resources_account(accountId: uuid.UUID, optionalAccount: Optional[Account] = Depends( depends.O_N_Owen)): with orm.db_session: account: Account = Account.get(Id=accountId) if not account: raise exceptions.NoSuchResourceException() return { "accountId": account.Id, "email": "".join([account.Email[0:3], "*" * (len(account.Email) - 6), account.Email[-3:]]), "username": account.AccountName, "characters": [ { "characterId": i.Id, "player": { "id": i.PlayerId, "name": i.PlayerName } } for i in account.Characters if i.Public ], "resources": [ { "id": i.Id, "name": i.Name, "createAt": i.CreatedAt, "metadata": { "type": i.Type, "model": i.Model } } for i in account.OwnedResources if not i.IsPrivate or\ accountId == (optionalAccount.Id if optionalAccount else None) ] }
async def mostima_register_request(register_info: MostimaRegister, request: Request): attempt_assert_occupy = Account.get(Email=register_info.email) if attempt_assert_occupy: raise exceptions.OccupyExistedAddress({ "accountId": attempt_assert_occupy.Id }) # 尝试断言: 有无Email相同账号 # 断言被跳过, 无Email相同账号 if not MostimaBuckets.requestLimit.get(register_info.email): MostimaBuckets.requestLimit.setByTimedelta(register_info.email, "LOCKED", delta={ "seconds": 60 }) else: raise exceptions.FrequencyLimit({ "email": register_info.email }) # 生成verifyId verifyId = String(config['natrium']['mostima']['request']['verifyId-length']) salt = bcrypt.gensalt() requests_bucket: AioCacheBucket = MostimaBuckets.requests try: emailer.send_mail(register_info.email, { 'subject': Ts_("mostima.mail_content.subject"), "content_text": Ts_("mostima.mail_content.content_text")\ .format(verify_url=urlunparse( ParseResult( scheme=request.url.scheme, netloc=request.url.netloc, path="/natrium/mostima/register/request/verify", params="", query=urlencode({ "verifyId": verifyId }), fragment="" ) )) }) requests_bucket.setByTimedelta(verifyId, { "email": register_info.email, "name": register_info.accountName, "password": bcrypt.hashpw(register_info.password.encode(), salt), "salt": salt, "redirectTo": register_info.redirectTo }) except Exception as e: print(e) return selected_jsonencoder( MostimaRequest_Response(operator="failed").dict(), status_code=500 ) return MostimaRequest_Response(operator="success")
async def signout(info: RModels.Authserver_Signout): user: Account = Account.get(Email=info.username) if not user: raise exceptions.InvalidCredentials() if not user_auth_cooling_bucket.get(user.Email): user_auth_cooling_bucket.setByTimedelta(user.Email, "LOCKED") else: raise exceptions.InvalidCredentials() if not bcrypt.checkpw(info.password.encode("utf-8"), user.Password): raise exceptions.InvalidCredentials() for i in Token.getManyTokens(user): auth_token_pool.delete(i.AccessToken) return Response(status_code=204)
async def authserver_signout(authinfo: AccountAuth): account = Account.get(Email=authinfo.email) if not account: raise exceptions.InvalidCredentials() if not VerifyLocks.get(account.Id): VerifyLocks.setByTimedelta(account.Id, "LOCKED") else: raise exceptions.FrequencyLimit() AuthentidcateVerifyResult = bcrypt.checkpw(authinfo.password.encode(), account.Password) if not AuthentidcateVerifyResult: raise exceptions.InvalidCredentials() for i in TokenBucket: if TokenBucket.get(i).Account.Id == account.Id: TokenBucket.delete(i) return {"operator": "success"}
async def os_char_create(createInfo: models.CharacterCreate, account: Account = Depends( depends.AccountFromRequest)): if not res.verify(createInfo.create.name, res.CharacterName): raise exceptions.NonCompliantMsg() if Character.get(PlayerName=createInfo.create.name): raise exceptions.OccupyExistedAddress() account = Account.get(Id=account.Id) character = Character(PlayerId=OfflinePlayerUUID(createInfo.create.name), PlayerName=createInfo.create.name, Owner=account, CreatedAt=dt.now(), UpdatedAt=dt.now(), Public=createInfo.create.public) orm.commit() return character.format_self()
async def mostima_register_request_verify(verifyId: str, request: Request): verify_result = requests_bucket.get(verifyId) if not verify_result: raise exceptions.BrokenData({ "position": "query_params.verifyId" }) result = Account( Email=verify_result['email'], AccountName=verify_result['name'], Password=verify_result['password'], Salt=verify_result['salt'] ) orm.commit() if verify_result['redirectTo']: redirect: ParseResult = urlparse(verify_result['redirectTo']) redirect.query = urlencode({ "accountId": result.Id }) return RedirectResponse(urlunparse(redirect), status_code=302) return { "id": result.Id }
async def authserver_authenticate(authinfo: AuthenticateRequest): account = Account.get(Email=authinfo.email) if not account: raise exceptions.InvalidCredentials() if not VerifyLocks.get(account.Id): VerifyLocks.setByTimedelta(account.Id, "LOCKED") else: raise exceptions.FrequencyLimit() AuthentidcateVerifyResult = bcrypt.checkpw(authinfo.password.encode(), account.Password) if not AuthentidcateVerifyResult: raise exceptions.InvalidCredentials() token = Token(account, authinfo.authenticate.clientToken) TokenBucket.setByTimedelta(token.AccessToken, token) result = { "auth": { "accessToken": token.AccessToken.hex, "clientToken": token.ClientToken, "metadata": { "stages": { "create": token.CreateAt.rfc2822(), "alive": token.AliveDate.rfc2822(), "expire": token.ExpireDate.rfc2822(), } } } } if authinfo.requestAccount: result['account'] = { "id": account.Id.hex, "email": account.Email, "createAt": maya.MayaDT(account.CreatedAt.timestamp()).rfc2822(), "rank": account.Permission } return result
async def amadeus_upload( bgTasks: BackgroundTasks, file: UploadFile = File(...), name: str = Query(..., min_length=4, max_length=60, regex=res.ResourceName), Model: enums.MCTextureModel = Query("auto", alias="model"), Type: enums.MCTextureType = Query(..., alias="type"), Private: bool = False, Protect: bool = False, uploader: Account = Depends(depends.AccountFromRequestForm(alias="auth")) ): """参数name为要创建的资源名称.\n 通过表单API上传图片, 名称"file"\n 通过表单发送认证, 名称"auth".\n 可用get query传参: \n ``` url http://127.0.0.1:8000/natrium/amadeus/upload/aResourceName?type=skin&strict=true&model=alex ``` """ # 常量分配 Original: bool = True # 在库中是否是第一个被创建的 OriginalResource: Optional[Resource] = None OriginalUploader: Optional[Account] = None if Private and Protect: raise exceptions.DuplicateRegulations() try: image: Image.Image = Image.open(BytesIO(await file.read())) except PIL.UnidentifiedImageError: raise exceptions.NonCompliantMsg({ "filename": file.filename }) finally: await file.close() width, height = image.size if image.format != "PNG": raise exceptions.NonCompliantMsg({ "image.format": { "value": image.format, "assert": "PNG" } }) if height > config['natrium']['upload']['picture-size']['height'] or\ width > config['natrium']['upload']['picture-size']['width']: raise exceptions.NonCompliantMsg() image.resize(( int(width / 22) * 32 if width % 22 == 0 else width, int(width / 17) * 32 if height % 17 == 0 else height )) pictureContentHash = hashing.PicHash(image) attempt_select = orm.select(i for i in Resource if i.PicHash == pictureContentHash) if attempt_select.exists(): # 如果真的有上传的数据一样的 Original = False for i in attempt_select[:]: # 询问数据库, 找到原始作者 # 考虑加入uploader找寻. if not i.Origin: OriginalResource = i OriginalUploader = i.Owner break if not OriginalResource or\ not OriginalUploader: # 判断是否找到了, 如果没找到, 说明数据库信息受损 raise exceptions.BrokenData({ "PictureHash": pictureContentHash, "ExceptionRaisedTime": maya.now() }) # 如果有attempt_select, 就一定有一个origin. # 判断是否是原作者闲着没事干, 重新上传了一个. if OriginalUploader.Id == uploader.Id: raise exceptions.OccupyExistedAddress({ "originalResource": { "id": OriginalResource.Id, "owner": OriginalUploader.Id }, "uploader": { "id": uploader.Id } }) else: # ...或者是其他人, 这种情况我们需要特殊处理 # 由于Protect的受限度较低, 故放在上面点. if OriginalResource.Protect: if Protect or Private: raise exceptions.PermissionDenied({ "originalResource": { "id": OriginalResource.Id, "owner": OriginalUploader.Id, "protect": OriginalResource.Protect, "private": OriginalResource.Private }, "uploader": { "id": uploader.Id } }) else: # 但是你本来就可以设为这个啊, 为啥要自己整一路去? raise exceptions.OccupyExistedAddress({ "originalResource": { "id": OriginalResource.Id, "owner": OriginalUploader.Id, "protect": OriginalResource.Protect, }, "uploader": { "id": uploader.Id } }) elif OriginalResource.IsPrivate: # 如果私有, 则不允许任何人上传/使用/设保护/私有等 raise exceptions.OccupyExistedAddress({ "originalResource": { "id": OriginalResource.Id, "owner": OriginalUploader.Id, "protect": OriginalResource.Protect, }, "uploader": { "id": uploader.Id } }) else: # 你什么私有保护什么的都没开? 别开你自己的私有保护什么的就OK. if Protect or Private: raise exceptions.PermissionDenied({ "originalResource": { "id": OriginalResource.Id, "owner": OriginalUploader.Id }, "uploader": { "id": uploader.Id }, "options": { 'protect': Protect, "private": Private } }) else: # 找寻上传者是否也曾经上传过该材质 assert_the_same = orm.select(i for i in Resource\ if i.PicHash == pictureContentHash and \ i.Owner.Id == uploader.Id) if assert_the_same.exists(): ats_first: Resource = assert_the_same.first() raise exceptions.OccupyExistedAddress({ "ownedResource": { "id": ats_first.Id, "name": ats_first.Name }, "uploader": { "id": uploader.Id } }) if Model == "auto": Model = ['steve', 'alex'][skin.isSilmSkin(image)] account = Account.get(Id=uploader.Id) resource = Resource( PicHash = pictureContentHash, Name = name, PicHeight = height, PicWidth = width, Model = Model, Type = Type, Owner = account, IsPrivate = Private, Protect = Protect, Origin = OriginalResource ) if Original: bgTasks.add_task(Save, image, pictureContentHash) orm.commit() return { "operator": "success", "metadata": resource.format_self(requestHash=True) }